Paul Durrant [Sat, 30 Jan 2021 18:08:34 +0000 (18:08 +0000)]
Add XENBUS_SHARED_INFO method to check whether event upcalls are supported
Upcalls can only be supported on a vCPU that has a vcpu_info structure
available to Xen; that is one with a vcpu_id < XEN_LEGACY_MAX_VCPUS (32) or
one that has explicitly registered a vcpu_info. This is determined during
SharedInfoAcquire() but the information needs to be avalable to the code in
evtchn.c. Hence this patch adds a new 'UpcallSupported' method to
XENBUS_SHARED_INFO (consequently bumping the interface version to 3).
These are the last of the v8 PDO versions. The v9 drivers have been available
for a long time now so these versions can be retired. This allows support for
XENBUS_EVTCHN v4, XENBUS_STORE v1 and XENBUS_GNTTAB v1 interfaces to be
removed.
NOTE: Without this patch then adding new interface versions is essentially
blocked, as a single extra PDO revision will trigger an assertion in
PdoQueryId() in XENBUS because the length of the buffer for
'BusQueryCompatibleIDs' will exceed REGSTR_VAL_MAX_HCID_LEN (1024).
Paul Durrant [Sat, 30 Jan 2021 14:35:56 +0000 (14:35 +0000)]
Make vcpu_info registration conditional on number of vCPUs
It is unnecessary to explicitly register vcpu_info structures for VMs with
XEN_LEGACY_MAX_VCPUS (32) vCPUs or fewer as the array embedded in the
shared_info structure can be used instead, saving a small amount of memory and
speeding up boot slightly. NOTE: events may only be delivered to a vCPU with a
vcpu_info structure that is available to Xen.
This patch adds a registry override in the form of a registry parameter of
the XEN driver, 'RegisterVcpuInfo'. If this parameter is present and set
to zero then vcpu_info structures are not registered (regardless of vCPU
count), meaning that event channel binding may fail for some vCPUs in the
system (i.e. those with vcpu_id >= 32). If the parameter is present and set
to a non-zero value then vcpu_info structures are always registered (as is
the case without this patch). However, if the parameter is missing (which is
the default case) then vcpu_info structures will be registered only if the
vCPU count exceeds 32.
NOTE: The logic checking XEN_LEGACY_MAX_VCPUS in EvtchnIsProcessorEnabled()
doesn't really belong there. The code in shared_info.c knows whether
a vcpu_info is available but querying this will require a new version
of XENBUS_SHARED_INFO. This will be addressed in a subsequent patch.
Paul Durrant [Sat, 30 Jan 2021 14:29:22 +0000 (14:29 +0000)]
Allocate SYSTEM_PROCESSOR array up-front
Most code uses KeQueryMaximumProcessorCountEx() to determine the number of
CPUs in the system, so remove the one and only caller of
SystemProcessorCount(), remove it from the XEN_API and allocate the array
up-front (also using KeQueryMaximumProcessorCountEx()) rather than growing
it in response to each processor callback.
Paul Durrant [Fri, 29 Jan 2021 18:51:02 +0000 (18:51 +0000)]
Introduce XENBUS_SHARED_INFO_PROCESSOR to hold per-CPU state
This allows the vcpu_info pointer and vcpu_id to be retrieved once for each
vCPU during SharedInfoAcquire(). It also provides a convenient place to
save the event port that terminated the previous poll (which, for fairness, is
where the next poll starts from).
Paul Durrant [Fri, 29 Jan 2021 18:41:21 +0000 (18:41 +0000)]
Fix ASSERTion failure in FdoDisconnectInterrupt()
Currently the ASSERT(IsZeroMemory(...)) will fail because nothing zeroes
the interrupt count added in commit 162545540cb9 ("Make sure the interrupt
handler for each vCPU is run..."). This patch sets it to zero just after
calling IoDisconnectInterruptEx() (which unhooks FdoInterruptCallback(), where
the count is incremented).
Paul Durrant [Fri, 29 Jan 2021 18:35:32 +0000 (18:35 +0000)]
Remove bogus ASSERTion
The ASSERT(Index > 0) in DriverQueryId() in XENFILT appears to have started
to fail in Windows 10 2004. It is bogus as it will fail if an underlying
driver passes back an empty buffer from either BusQueryHardwareIDs or
BusQueryCompatibleIDs, yet DriverQueryId() will cope perfectly will in these
circimstances, passing back en empty string to its caller. This patch simply
removes the ASSERT().
Owen Smith [Thu, 28 Jan 2021 11:51:20 +0000 (11:51 +0000)]
Add AutoRebootTimeout configuration
Add registry value AutoRebootTimeout, which if set, is used as the
Timeout value passed to InitiateSystemShutdownEx. If not set, use the
default value of 60 seconds.
Owen Smith [Wed, 6 Jan 2021 16:17:50 +0000 (16:17 +0000)]
Fail XS_DIRECTORY for paths with no children
When a xenstore path has no children, a response is generated which
contains only the double null terminator. Detect a 0-length response
payload and return STATUS_OBJECT_PATH_NOT_FOUND to indicate that this
path does not have any children
Owen Smith [Tue, 15 Dec 2020 16:29:07 +0000 (16:29 +0000)]
Add AutoReboot capability
Setting HKLM\System\CCS\Services\xenbus_monitor\AutoReboot to non-zero
will allow xenbus_monitor to trigger a reboot when another driver
requests a reboot. AutoReboot is set to the maximum number of reboots
to perform. Auto reboots display a message with a 60 second timeout.
This setting can be used to allow headless/unmonitored VMs to complete
the neccessary number of reboots to return to PV disks/networks. Without
this capability its possible to update the driver on a parent device,
which may prompt for a reboot. After this reboot, its likely that
emulated devices are used whilst drivers are rebound to the device
nodes. This can leave headless/unmonitored VMs in a state where emulated
devices are in use with a pending reboot. If network settings have been
changed for PV devices (e.g. static IP addressing), then the VM may not
be accessible over RDP or similar connections.
RebootCount is cleared when no pending required reboots are detected.
Paul Durrant [Fri, 4 Dec 2020 20:01:41 +0000 (20:01 +0000)]
Make sure the interrupt handler for each vCPU is run...
... after enabling event channel delivery.
New versions of Xen have this sequence in their map_vcpu_info() function:
/*
* Mark everything as being pending just to make sure nothing gets
* lost. The domain will get a spurious event, but it can cope.
*/
if ( !has_32bit_shinfo(d) )
write_atomic(&new_info->native.evtchn_pending_sel, ~0);
else
write_atomic(&vcpu_info(v, evtchn_pending_sel), ~0);
vcpu_mark_events_pending(v);
whereas older versions code this differently:
/*
* Mark everything as being pending just to make sure nothing gets
* lost. The domain will get a spurious event, but it can cope.
*/
vcpu_info(v, evtchn_upcall_pending) = 1;
for ( i = 0; i < BITS_PER_EVTCHN_WORD(d); i++ )
set_bit(i, &vcpu_info(v, evtchn_pending_sel));
The crucial difference is that in the older variant there is no call to
vcpu_mark_events_pending() which means that, for an HVM guest at least,
the upcall function that clears 'evtchn_upcall_pending' does not get
run and hence no events will be received on that vCPU.
This patch makes sure the upcall function for each vCPU is run at least once
thereby ensuring that 'evtchn_upcall_pending' is cleared.
NOTE: The patch also adds a 'Count' to each XENBUS_INTERRUPT object,
incremented each time the interrupt is triggred, and emits a log line
when the value transitions from zero.
Paul Durrant [Fri, 27 Nov 2020 09:47:53 +0000 (09:47 +0000)]
Register memory for struct vcpu_info
This must only be done once for each vCPU in the lifetime of the VM. The
PFNs of the allocated memory are therefore saved in the registry such that
they can be recovered if XEN.SYS is unloaded and re-loaded.
A new VM is created to resume a suspended image loaded from storage or
migrated in, so a call to the new SystemProcessorRegisterVcpuInfo() is also
added into the 'sync' early callback for each vCPU. This invocation specifies
a 'force' flag, since the state of the VM's memory will show that the
vcpu_info has already been registered.
References to the legacy vcpu_info structures embedded in the shared_info are
replaced and the limit of XEN_LEGACY_MAX_VCPUS is removed from the 2-level
event channel implementation.
NOTE: SystemVirtualCpuIndex() is also renamed to SystemProcessorVcpuId()
for consistency, and it is co-located with the new
SystemProcessorVcpuInfo() function.
It is also necessary to disable warning C4146 (unary minus operator
applied to unsigned type) in xen.vcxproj as this is done by the
P2ROUNDUP() macro.
Paul Durrant [Mon, 30 Nov 2020 13:52:09 +0000 (13:52 +0000)]
Re-work the code in sync.c to provide per-CPU 'early' and 'late' callbacks...
... and then use these to drive the XENBUS_SUSPEND callbacks, rather than them
being called directly from SuspendTrigger().
Since the clients of the XENBUS_SUSPEND interface only expect one invocation
of each callback, rather then one per-CPU, they are only invoked from the
sync.c callback for CPU 0. A subsequent patch will introduce a function that
must be called from the 'early' callback for each CPU.
NOTE: The call to KeGetCurrentProcessorNumberEx() made in SyncRelease() is
relocated to __SyncRelease(), as that is the place where the CPU index
is actually used.
Paul Durrant [Sat, 28 Nov 2020 17:38:29 +0000 (17:38 +0000)]
Introduce DriverGet/PutNamedPages()
A subsequent patch will need a mechanism to allocate memory that persists
for the lifetime of the VM. Because it is possible for the XEN.SYS module
can be unloaded, references to the PFNs of the allocated buffer are stored
under a volatile registry key such that they can be re-discovered if XEN.SYS
is re-loaded.
DriverGetNamedPages() will either allocate or discover PFNs and wrap them in
an MDL which is then mapped and passed back to the caller.
DriverPutNamedPages() will unmap the PFNs but not free them (since they
will have been written into the registry by DriverGetNamedPages()).
NOTE: There is also a whitespace fix in the call to RegistryCreateSubKey()
for the 'ParametersKey' in driver.c.
Paul Durrant [Fri, 27 Nov 2020 09:06:37 +0000 (09:06 +0000)]
Generalize per-processor DPC in SYSTEM
The DPC is currently used only for acquiring and display per-processor
information but a subsequent patch will also use the DPC for another purpose.
Hence this patch creates a general SystemProcessorDpc() call-back that then
calls a slightly modified SystemProcessorInformation() (which is renamed
SystemProcessorInitialize()) to fulfil the original purpose.
This patch also adds a mechanism for the per-processor DPCs to pass back
a status code to the main initialization code such that it can be aborted if
any of them fail. A new SystemProcessorTeardown() function is added to do
cleanup, and hence we can verify the SYSTEM_PROCESSOR structures are zeroed
in SystemDeregisterProcessorChangeCallback().
Currently no failure is possible during SystemProcessorDpc() but this will
change with the addition of a subsequent patch.
NOTE: __SystemProcessorCount() is relocated earlier in system.c as it now
needs to be called by SystemDeregisterProcessorChangeCallback(). It
is relocated earlier than strictly necessary for this, but
subsequent patches will do further function relocation and add additonal
funcrtions that also rely on __SystemProcessorCount() being in its new
position.
Paul Durrant [Sat, 28 Nov 2020 17:44:01 +0000 (17:44 +0000)]
Re-work ASSERTion to avoid issues with VERIFIER list checks
The current mechanism of ASSERTing that there is a single item on the list
seems to fail when list checking is turned on in VERIFIER. Avoid going round
the back of the list macros by instead ASSERTing that the list is empty, once
the entry is removed.
Paul Durrant [Wed, 25 Nov 2020 19:57:36 +0000 (19:57 +0000)]
Don't restrict event channels to vCPU 0...
... when using the 2-level event channel ABI.
With a small modification to track port numbers per-vcpu, the 2-level polling
code will happily deal with event channels bound to any vCPU up to
XEN_LEGACY_MAX_VCPUS. We just need to be careful to only process events on the
correct vCPU, to avoid list corruption. Hence, the newly introduced 'Pending'
flag needs to be set atomically in case we re-bind an event channel whilst a
poll is in progress.
The XEN_LEGACY_MAX_VCPUS limit is because the 2-level poll currently relies
on using the vcpu_info array embedded in the shared_info. This limit will be
removed in a subsequent patch.
Paul Durrant [Wed, 25 Nov 2020 19:24:05 +0000 (19:24 +0000)]
Provide a registry override to disable use of per-vcpu event channel upcalls
There is already a REG_DWORD (UseEvtchnFifoAbi) to disable use of FIFO event
channels and force a fall-back to 2-level. This patch adds another
(UseEvtchnUpcall) to disable use of per-vcpu upcalls and force a fall-back to
the callback via.
Paul Durrant [Wed, 25 Nov 2020 18:58:58 +0000 (18:58 +0000)]
Tolerate any failure of __FdoVirqCreate() in the VIRQ_TIMER case
In pratice __FdoVirqCreate() won't return STATUS_NOT_SUPPORTED since the
XENBUS_EVTCHN(Open, ...) doesn't return a status code and ERRNO_TO_STATUS()
(inside VcpuSetPeriodicTimer()) doesn't translate any Xen errno to that
status code, therefore the check in FdoVirqInitialize() is actually bogus.
This patch simply tolerates any status code returned by __FdoVirqCreate()
when creating a VIRQ_TIMER and then gates enabling the watchdog on there
being at least one VIRQ_TIMER successfully created.
Paul Durrant [Wed, 25 Nov 2020 18:07:01 +0000 (18:07 +0000)]
Don't veto event channel binding if it's not necessary
Currently binding is vetoed if 'UpcallEnabled' is not set, but this is not
necessary if the selected processor is 0, as the callback via will also
interrupt that CPU.
Paul Durrant [Wed, 25 Nov 2020 17:55:55 +0000 (17:55 +0000)]
Avoid non-zero memory ASSERTion if FdoVirqInitialize() fails
FdoVirqTeardown() should also be called from the 'fail1' label to clean up
'VirqList'. This patch also modifies FdoVirqTeardown() to make sure 'VirqLock'
is properly zeroed.
Paul Durrant [Thu, 19 Nov 2020 10:11:07 +0000 (10:11 +0000)]
Add "XEN:WATCHDOG=" system start option to specify a watchdog time-out
When this option supplies a non-zero value (in seconds) for the time-out,
XENBUS will open a VIRQ_TIMER channel bound to each active processor (unless
prevent from doing so by the lack of a FIFO Xen event channel ABI, in which
case there will only be one VIRQ_TIMER on vCPU 0). The Xen domain watchdog
will be programmed to shut the domain down after the time-out period has
elapsed and each VIRQ_TIMER will be programmed to fire at intervals of half
the watchdog period in order that the last vCPU to receive the event
notification will pat the watchdog.
This option will therefore cause lengthy event delivery or processing stalls
to be fatal to the domain, which can be useful for debugging and in some I/O
fail-over cluster scenarios.
Paul Durrant [Thu, 19 Nov 2020 09:58:11 +0000 (09:58 +0000)]
Slightly modify the way balloon initialization is done in fdo.c
Currently only one system start option "XEN:BALLOON=" modifies the behaviour
of FDO creation. A subsequent patch will add another option. This patch is
to avoid inconsistency in the code when that is done.
The FdoIsBalloonEnabled() function is replaced with FdoBalloonInitialize(),
which inlines what FdoCreate() would previously have done when
FdoIsBalloonEnabled() returned TRUE. A matching FdoBalloonTeardown()
function is also introduced for the sake of symmetry.
Paul Durrant [Thu, 19 Nov 2020 09:28:24 +0000 (09:28 +0000)]
Add XENBUS_DEBUG callback into fdo.c to dump VIRQ information
The callback iterates the list of open VIRQ channels and dumps information
about each. This is currently limited to its vCPU binding, and to enable
this information to be dumped it is necessary to save that information in the
XENBUS_VIRQ structure.
Paul Durrant [Thu, 19 Nov 2020 09:14:31 +0000 (09:14 +0000)]
Add support for Xen (VCPUOP) periodic timers
This patch imports the Xen VCPUOP public header (public/vcpu.h) and adds a new
source module in to the XEN_API implementation (vcpu.c) containing a new
VcpuSetPeriodicTimer() helper function.
This patch does not introduce callers of the new API. Those will be
introduced in a subsequent patch.
Paul Durrant [Thu, 19 Nov 2020 09:08:32 +0000 (09:08 +0000)]
Add functions to XEN_API to facilitate use of a domain watchdog
The SCHEDOP_watchdog hypercall allows a domain to program a watchdog time-
out (in seconds) after which it will be shut down.
This patch adds a helper function into sched.c to make the hypercall and also
adds new SystemSetWatchdog() and SystemStopWatchdog() functions that provide
a more friendly API to the functionality.
This patch does not introduce callers of the new API. Those will be
introduced in a subsequent patch.
Paul Durrant [Tue, 17 Nov 2020 12:51:34 +0000 (12:51 +0000)]
Update the XENBUS_EVTCHN interface...
... to allow 'vcpu_id' to be sepcified to the EvtchnOpen() method, when
opening a VIRQ channel.
Non-global VIRQ channels (such as VIRQ_DEBUG and VIRQ_TIMER) can be bound to
a specific vCPU. To allow callers of EvtchnOpen() to do this, it is necessary
for extra arguments to be passed to EvtchnOpenVirq().
This patch updates the version of XENBUS_EVTCHN from 8 to 9, despite there
being no function type change (since EvtchnOpen() is a variadic method) and
modifies the implemention of EvtchnOpen() to pass the number of arguments to
its type-specific helpers. Hence EvtchnOpenVirq() can determine whether or
not it is being supplied with vCPU infomation.
Paul Durrant [Thu, 19 Nov 2020 08:17:44 +0000 (08:17 +0000)]
Use Windows types in XEN_API event channel functions
Other XEN_API functions use Windows types rather than Xen types in most cases.
There is no good reason why functions related to event channels need expose
types such as 'domid_t' or 'evtchn_port_t' to callers, especially when the
callers already use USHORT and ULONG types (respectively) for those quantities.
Troy Crosley [Thu, 5 Nov 2020 21:38:31 +0000 (16:38 -0500)]
Ensure DifRemove coinst routine runs on uninstall.
In Windows 10 version 2004, The coinstallers' DIF_INSTALLDEVICE routines
do not get called on driver uninstall. In previous versions of Windows,
this occurs as part of the uninstall during the null device install and
is the only time DifRemove gets called to perform cleanup. Work around
this change by calling DifRemove from DIF_SELECTBESTCOMPATDRV, which is
the only coinstaller request that seems to happen on uninstall in
Windows 10 version 2004. In addition, improve the null driver test to
also check if DriverInfoData.DriverType is equal to SPDIT_CLASSDRIVER or
SPDIT_COMPATDRIVER, which is necessary as of some Windows version (at
least Windows 10 version 1803).
Signed-off-by: Joel Upham <uphamj@ainfosec.com> Signed-off-by: Troy Crosley <troycrosley@gmail.com>
Extra hunk added to squash ERROR_NO_COMPAT_DRIVERS when it is passed into
DIF_SELECTBESTCOMPATDRV post-processing.
Inherit versioning info from environment if present
As the drivers stabilize and mature, there is an ever-growing
chance that other opensource virtualization projects will adopt
them. Allow external projects to inject their own versioning
into the drivers instead of hardcoding the latest winpv version.
Signed-off-by: Nicholas Tsirakis <tsirakisn@ainfosec.com> Acked-by: Owen Smith <owen.smith@citrix.com>
Often times we only need to build a driver for a single
targeted architecture. Continue to build both by default,
but allow the user to specify one if desired.
Signed-off-by: Nicholas Tsirakis <tsirakisn@ainfosec.com>
Use [string]::IsNullOrEmpty($Arch)
These bugchecks have been observed in recent updates of Server 2019.
This patch, rather than replacing calls to MmAllocatePagesForMdlEx() with
calls to MmMapLockedPagesSpecifyCache(), just avoids passing
MM_DONT_ZERO_ALLOCATION to work round the bug.
The patch instead passes MM_ALLOCATE_FULLY_REQUIRED, which arguably should
have always been passed for allocations larger than a single page. It also
fixes a formatting issue.
Reported-by: Jan Bakuwel <jan.bakuwel@gmail.com> Signed-off-by: Paul Durrant <pdurrant@amazon.com>
Owen Smith [Wed, 4 Mar 2020 13:27:23 +0000 (13:27 +0000)]
Reorder StorePollLocked and StoreDisable
StoreDisable will close and NULL the event channel, then StorePollLocked
will attempt to call EVTCHN(GetCount...) with the NULLed pointer. This
will lead to a D1 BSOD.
When updating from v8.x to v9.x, XENFILT is removed from System and Hdc
class UpperFilter by the removal of the v8.x XenBus. When v9.x XenBus
loads, the filter state is not set, and XenBus will fail AddDevice
without re-adding XenFilt to the UpperFilters.
Paul Durrant [Thu, 20 Feb 2020 09:08:41 +0000 (09:08 +0000)]
Continue checking for emulated type if not PCI or IDE
When determining the XENFILT_EMULATED_OBJECT_TYPE, keep trying all
supplied HardwareIDs/CompatibleIDs until an exact match is made. If an
early match is made that is not a valid type, ignore the match and
continue checking for either "PCI" or "IDE".
This covers situations where XENFILTS's Parameters key contains stale
strings from previous (v8.x) versions, and fixes an upgrade failure when
upgrading v8.x to v9.x
Signed-off-by: Owen Smith <owen.smith@citrix.com>
[Re-structured] Signed-off-by: Paul Durrant <pdurrant@amazon.com>
Paul Durrant [Fri, 15 Nov 2019 14:02:28 +0000 (14:02 +0000)]
Avoid a small race window that can lead to stuck EvtchnWait() calls
Make sure an event is ack-ed before Channel->Count is incremented
otherwise EvtchnGetCount() could sample the incremented value whilst new
events would be missed. Thus EvtchnWait() could end up waiting for a
Count value that my never be reached.
Paul Durrant [Wed, 2 Oct 2019 11:14:45 +0000 (12:14 +0100)]
Update XENFILT_EMULATED IsDiskPresent() method...
...to match how XENVBD actually uses it.
XENVBD erroneously passes the disk number of the PV disk as the target
number, which is incorrect for disk numbers more than 1. E.g. disk 3 should
equate to controller 1, target 1.
This patch adapts the method to that use by dropping the extraneous
Controller and Lun parameters and properly interpreting the Target
parameter.
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Paul Durrant [Wed, 2 Oct 2019 07:59:17 +0000 (08:59 +0100)]
Determine emulated device type from HardwareIDs or CompatibleIDs
These names are a little less arbitrary than the DeviceID and this change
also allows matching on class code for PCI devices, rather than a specific
vendor/device combo.
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Paul Durrant [Fri, 27 Sep 2019 09:19:00 +0000 (10:19 +0100)]
Ackowledge that tracked emulated objects are strictly...
...PCI devices or IDE disks.
Do this by renaming the type values both internally and in the registry.
The parsing code in emulated.c doesn't need to change but the type is now
passed into EmulatedSetObjectDeviceData() and EmulatedSetObjectDiskData()
so that they may cope with non-PCI devices or non-IDE disks in future.
Also, re-name XENFILT_EMULATED_OBJECT_TYPE_INVALID to
XENFILT_EMULATED_OBJECT_TYPE_UNKNOWN to more accurately reflect its
meaning.
NOTE: This patch also re-works DriverGetEmulatedType() slightly to do
the registry look-up of the DeviceID itself. This allows the fail
labels to be removed from DriverAddDevice().
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Paul Durrant [Tue, 24 Sep 2019 12:40:58 +0000 (13:40 +0100)]
Don't BUG() just because we can't get a super-page
When XENBUS is unloaded, it is necessary to re-populate the memory hole
that was created to host the shared info page, grant table shared frames,
etc. The hole is created by doing an order 9 XENMEM_decrease_reservation,
but this does not necessarily mean that Xen can re-populate it with an
order 9 allocation (i.e. a 2M super-page). Currently, such a failure will
cause an immediate BUG(), whereas what the code should do is to re-try
using order 0 (i.e. normal 4k page) allocations, and only BUG() if that
doesn't work.
This patch fixes the issue.
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
determines whether Windows programs the RTC in local time or UTC. If the
value is zero or missing (which is the default) then the RTC will be
programmed in local time, otherwise it will be programmed in UTC.
Since the emulated RTC and the Xen wall-clock are kept in sync, it is
necessary to know which mode Windows is operating in to correctly interpret
the wall-clock value. This patch checks the registry value on boot (it is
necessary to reboot after modifying it for it to take effect) and reports
the RTC operating mode along-side the Xen wall-clock in a updated
GetTime method in version 3 of the XENBUS_SHARED_INFO interface.
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Paul Durrant [Mon, 16 Sep 2019 12:27:53 +0000 (13:27 +0100)]
Tolerate running in a non-Xen VM
If a disk image with XENBUS installed is booted in a non-Xen environment
then this will currently lead to a BSOD. This patch makes things fail
more gracefully by:
a) Making sure an attempt at a hypercall doesn't indirect into an
uninitialized hypercall page.
b) Making XenTouch() in XEN handle a STATUS_NOT_IMPLEMENTED failure from
XenVersion(), and have XENBUS and XENFILT use this failure mode to
quiesce themselved.
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Paul Durrant [Thu, 5 Sep 2019 15:21:55 +0000 (16:21 +0100)]
Stop using contiguous memory for slabs
Slab memory does not need to be (physically) contiguous and it is much
faster to use non-paged pool memory, so just used __CacheAllocate/Free()
for slab memory as well as internal house-keeping structures.
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Paul Durrant [Wed, 4 Sep 2019 16:36:25 +0000 (17:36 +0100)]
Improve the performance of the slab allocator
This patch makes a couple of changes which testing shows to improve
performance.
Firstly the slabs are now sorted such that the most occupied slab is on
the head of the list. This should lead to a smaller number of slabs, each
with a higher occupancy, which reduces the overall amount of memory
consumed and the number of 'Ctor' invocations (NB: a Ctor may also
allocate other memory).
Secondly, rather than destroying a slab as soon as its occupancy falls to
zero, defer freeing to the re-introduced monitor thread. This takes freeing
(and associated invocations of Dtor) off the performance critical paths
and also allows an empty slab to be re-used, avoiding calls to
CacheCreateSlab() (and hence more Ctor invocations).
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Owen Smith [Wed, 21 Aug 2019 09:55:22 +0000 (10:55 +0100)]
Handle ActiveLocationInformation value not found
v8.2 drivers do not set ActiveLocationInformation, so when upgrading
xenbus to v9.0, xenfilt fails during PdoSetDeviceInformation.
Allow xenfilt to handle missing ActiveLocationInformation, and make
xenbus add ActiveLocationInformation and ActiveInstanceID, if missing,
for the active device.
Paul Durrant [Tue, 20 Aug 2019 13:13:41 +0000 (14:13 +0100)]
Have another go at __CacheMaskScan()
Trying to BUG() at the end of the function if an available index is not
found is proving to be too challenging for the compilier. It seems that,
in general, a free build may object if there's (an effectively dead) return
statement after the BUG() and a checked build will fail if the return
statement is *not* there. Rock. Hard place.
This patch instead gets rid of the BUG(), makes __CacheMaskScan() return
and out-of-range index if there is no available index and then adds a
suitable BUG_ON() into CacheGetObjectFromSlab(), the only caller.
The patch also fixes a hole in the logic where an out-of-range index
could have been returned if it was less than the maximum occupancy
rounded up to the next 32-bit boundary.
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Owen Smith [Fri, 14 Jun 2019 16:36:01 +0000 (17:36 +0100)]
Use NonPagedPool for Active device properties
ActiveDeviceId and ActiveInstanceId can be used at DISPATCH_LEVEL, and
therefore cannot use PagedPool. When these values are returned via IRPs,
the value is copied into a PagedPool buffer for the IRP to use.
Paul Durrant [Fri, 31 May 2019 11:46:57 +0000 (12:46 +0100)]
Remove unreachable return statement
It appears than the newer compilers are happy that a return statement after
a BUG() is actually unreachable, and some compilers will actually warn to
that effect, so just blow it away.
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Paul Durrant [Thu, 30 May 2019 10:41:10 +0000 (11:41 +0100)]
Unconfuse XENBUS_CACHE_SLAB Allocated field
The purpose of the the field has become confused. It is actually an
allocation mask, but CacheInsertSlab() treats it as if it is an allocation
count.
This patch renames the allocation mask to 'Mask', the 'Count' field to
'MaximumOccupancy' (to better describe its purpose) and introduces a new
'CurrentOccupancy' counter.
This patch also makes sure the allocation mask can cover 'MaximumOccupancy'
and, since both CacheGetObjectFromSlab() and CachePutObjectToSlab() must
now be called under lock, it swaps the atomic bit-mask operations for
non-atomic mask manipulation.
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Paul Durrant [Thu, 30 May 2019 10:19:24 +0000 (11:19 +0100)]
Avoid double-free hazard in XENBUS_CACHE
Currently CachePut() calls CachePutObjectToSlab() without holding the cache
lock. This allows two concurrent calls to subsequently serialize on the lock
and both find Slab->Allocated == 0 (the second one actually testing freed
memory), leading to a double-free.
Moving the lock acquisition to before the call to CachePutObjectToSlab()
fixes this problem.
For consistency, this patch also makes it a requirement that
CachePutObjectToSlab() is called with the lock held, and adjusts
__CacheFlushMagazines() accordingly.
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Owen Smith [Wed, 29 May 2019 15:20:24 +0000 (16:20 +0100)]
Add BUILD_NUMBER to version string in XenStore
Append BUILD_NUMBER to the version stored in ~/drivers/<index>
This will help determine the exact version of drivers when
troubleshooting issues with limited access to the VMs
Paul Durrant [Mon, 20 May 2019 15:31:54 +0000 (16:31 +0100)]
Store (IRP_MN_QUERY_DEVICE_TEXT) DeviceTextLocationInformation...
...for active XENBUS instance.
When we 'trick' Windows into thinking that the active XENBUS device hasn't
moved (should it actually move in the PCI bus topology) we ought to make
sure that the location information remains constant as well is the
InstanceID. Thus it needs to be sampled and stored in the registry at
installation time. Subsequent patches will add the necessary code into
XENFILT to pull off the trick.
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Paul Durrant [Mon, 20 May 2019 14:43:34 +0000 (15:43 +0100)]
Avoid removing filters on upgrade installations
When upgrading XENBUS in a situation where XENVBD has made it uninstallable
(without reboot), DriverRemoveFunctionDeviceObject() in the old instance of
XENBUS will cause XENFILT to be removed as PCI and IDE upper filter. Then,
when the new instance of XENBUS starts, it will find an incompatible
version of XEN prior to adding the registery filter entries back in. Thus,
after the requested reboot XENFILT will non-functional and another reboot
will be required to re-instate it.
This patch removes the call to FiltersUninstall() from
DriverRemoveFunctionDeviceObject() and, instead, calls it from
DriverEntry() AFTER the compatibility check. This means that XENFILT will
remain installed across an upgrade and will only be removed if XENBUS
started but has no bound devices (i.e. it has actually been un-installed).
NOTE: This also fixes an unitialized pointer in FiltersUninstallClass().
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Paul Durrant [Mon, 29 Apr 2019 12:05:06 +0000 (13:05 +0100)]
Call Set-ExecutionPolicy in msbuild.exe
It appears that the default powershell execution policy prevents the sdv
target from running staticdv so we need to set the policy to 'Bypass'
before running msbuild.exe.
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Paul Durrant [Mon, 29 Apr 2019 08:40:09 +0000 (09:40 +0100)]
Use Invoke-Expression rather than & to run msbuild.exe
Older versions of powershell seem to have extreme difficulty with quoting
within strings passed to the & operator. Thankfully it seems the issues
can be avoided by building up a single command string then then passing
it to Invoke-Expression instead.
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Paul Durrant [Wed, 24 Apr 2019 13:18:28 +0000 (14:18 +0100)]
Handle archiving directly in package.vcxproj
The patch creates a custom 'Archive' target in package.vcxproj that runs
after 'TestSign'. This target handles archiving of the package so there
is no longer any need for the equivalent functionality in build.py and
build.ps1.
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Paul Durrant [Wed, 24 Apr 2019 09:04:31 +0000 (10:04 +0100)]
Invoke genfiles.ps1 from msbuild
The patch adds a new 'version.vcxproj' which other projects depend on.
This project's sole job is to invoke genfiles.ps1 to set up version.h and
xenbus.inf. Correspondingly the direct invocation of genfiles.ps1 is
removed from build.ps1 and equivalent functionality is removed from
build.py.
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Paul Durrant [Wed, 17 Apr 2019 16:51:15 +0000 (17:51 +0100)]
Re-work PowerShell build scripts
* build.ps1 has been renamed to msbuild.ps1 and made into a more basic
wrapper for invoking msbuild
* A new build.ps1 has been created to mirror the functionality of build.py
* package.ps1 has been folded into msbuild.ps1
All scripts have also had some level of cosmetic tidying and have been tested
in both the rs2 and rs5 EWDKs (with VS2015 and VS2017 respectively).
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Paul Durrant [Wed, 17 Apr 2019 15:06:49 +0000 (16:06 +0100)]
Stop using stampinf
There seems to be no way to prevent stampinf from using the current date,
which is going to make reproducible builds impossible. This patch moves
the date and version stamping into the build script (albeit using the
current date for the moment).
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Owen Smith [Thu, 11 Apr 2019 13:57:22 +0000 (14:57 +0100)]
Add PowerShell build scripts
* genfiles.ps1
Generate include/version.h and vs2017/xenbus.inf
This is intended to become a PreBuild step in the vcxproj
* build.ps1
Wraps running MSBuild for x86/x64
This is intended to become the entry point to build
* package.ps1
Coalesce the output from x86 and x64 package.vcxproj and generate the
resultant output zip file
This can be run directly from the build.ps1 script if required
* symstore.ps1
Store symbols from build output on symbol server
Signed-off-by: Owen Smith <owen.smith@citrix.com>
Fixed date formatting problems in genfiles.ps1 and renamed version._h_ to
version.tmpl.
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Owen Smith [Wed, 27 Mar 2019 16:35:34 +0000 (16:35 +0000)]
Fix parameter ordering
When the Order parameter was added to the MemoryPopulatePhysmap and
MemoryDecreaseReservation calls, the callers were transposing the Order
and Requested parameters.
Paul Durrant [Mon, 25 Mar 2019 16:36:22 +0000 (16:36 +0000)]
Avoid clearing unplug keys when binding to the non-active instance
If there is a secondary Xen PV PCI Device present in the VM then XENBUS
will bind to it as well as to the Xen Platform PCI Device, and the PV
device will be declare the 'active' instance.
During a driver upgrade, if it is found that the new version of the
XENBUS driver is not compatible with any child driver, the co-installer
will clear the registry keys controlling emulated device unplug to make
sure that storage and network connectivity are maintained after reboot
(until the child drivers are updated). This clearing of keys can, however,
occur multiple times if XENBUS is multiply bound whereas it only really
need occur when the instance bound to the active device is upgraded.
This patch adds a check into the co-installer to avoid clearing the
unplug keys when upgrading any non-active instance.
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Paul Durrant [Mon, 25 Mar 2019 11:45:16 +0000 (11:45 +0000)]
BalloonReleasePfnArray() is broken in several ways
When BalloonReleasePfnArray() attempts a decrease_reservation operation
then it is possible that not all the requested pages will be released.
In this eventuality, the function is supposed to pull the excess PFNs
that were added to the rangeset back out again and then allow the caller,
BalloonInflate(), to free the PFNs back to Windows.
The first bit of brokenness is that the arguments to RangeSetGet() are
permuted, such that it tries to get a range starting at PFN 1 rather than
a single PFN.
The next bit of brokenness is that the loop zeroes out the PFN value from
the array (presumably to satisfy the subsequent bogus ASSERTion) thus
causing the call to BalloonFreePfnArray() made by BalloonInflate() to
attempt to free PFN 0 potentially multiple times.
This patch fixes the code to do what it was intended to do.
Reported-by: Owen Smith <owen.smith@citrix.com> Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Paul Durrant [Fri, 18 Jan 2019 09:53:18 +0000 (09:53 +0000)]
Reduce time spent in the DbgPrint callback
Currently the log dispositions are serviced directly, meaning that all the
trapping for emulation is done synchronously, which is costly for
performance. This patch introduces a DPC to service the dispostions,
limiting the work done in the call back to simply copying the message
buffer and queuing the DPC.
Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
Owen Smith [Thu, 20 Dec 2018 17:23:14 +0000 (17:23 +0000)]
Ignore unused devices when checking for compatability
When upgrading, the coinstaller checks specific ENUM keys for devices.
If there are dangling references to software keys, the coinstaller will
fail. Dangling references are often caused by registry cleaners or user
attempts to ensure old drivers are purged, but cannot be completely
successful, as the ENUM keys are protected.
Change this behaviour to ignore dangling references in the registry.