XEN_API
NTSTATUS
-SystemVirtualCpuIndex(
+SystemProcessorVcpuId(
IN ULONG Cpu,
OUT unsigned int *vcpu_id
);
+XEN_API
+NTSTATUS
+SystemProcessorVcpuInfo(
+ IN ULONG Cpu,
+ OUT vcpu_info_t **Vcpu
+ );
+
+XEN_API
+NTSTATUS
+SystemProcessorRegisterVcpuInfo(
+ IN ULONG Cpu,
+ IN BOOLEAN Force
+ );
+
XEN_API
PHYSICAL_ADDRESS
SystemMaximumPhysicalAddress(
#include "dbg_print.h"
#include "assert.h"
#include "util.h"
+#include "driver.h"
#define XEN_SYSTEM_TAG 'TSYS'
UCHAR ProcessorID;
NTSTATUS Status;
KEVENT Event;
+ vcpu_info_t *Vcpu;
+ PBOOLEAN Registered;
} SYSTEM_PROCESSOR, *PSYSTEM_PROCESSOR;
typedef struct _SYSTEM_WATCHDOG {
PHYSICAL_ADDRESS MaximumPhysicalAddress;
BOOLEAN RealTimeIsUniversal;
SYSTEM_WATCHDOG Watchdog;
+ PMDL Mdl;
} SYSTEM_CONTEXT, *PSYSTEM_CONTEXT;
static SYSTEM_CONTEXT SystemContext;
return Context->ProcessorCount;
}
+XEN_API
+NTSTATUS
+SystemProcessorVcpuId(
+ IN ULONG Cpu,
+ OUT unsigned int *vcpu_id
+ )
+{
+ PSYSTEM_CONTEXT Context = &SystemContext;
+ PSYSTEM_PROCESSOR Processor = &Context->Processor[Cpu];
+ NTSTATUS status;
+
+ status = STATUS_UNSUCCESSFUL;
+ if (Cpu >= __SystemProcessorCount())
+ goto fail1;
+
+ *vcpu_id = Processor->ProcessorID;
+ return STATUS_SUCCESS;
+
+fail1:
+ return status;
+}
+
+XEN_API
+NTSTATUS
+SystemProcessorVcpuInfo(
+ IN ULONG Cpu,
+ OUT vcpu_info_t **Vcpu
+ )
+{
+ PSYSTEM_CONTEXT Context = &SystemContext;
+ PSYSTEM_PROCESSOR Processor = &Context->Processor[Cpu];
+ NTSTATUS status;
+
+ status = STATUS_UNSUCCESSFUL;
+ if (Cpu >= __SystemProcessorCount())
+ goto fail1;
+
+ ASSERT(*Processor->Registered);
+ *Vcpu = Processor->Vcpu;
+
+ return STATUS_SUCCESS;
+
+fail1:
+ return status;
+}
+
+XEN_API
+NTSTATUS
+SystemProcessorRegisterVcpuInfo(
+ IN ULONG Cpu,
+ IN BOOLEAN Force
+ )
+{
+ PSYSTEM_CONTEXT Context = &SystemContext;
+ PSYSTEM_PROCESSOR Processor = &Context->Processor[Cpu];
+ PMDL Mdl = Context->Mdl;
+ ULONG Offset;
+ PFN_NUMBER Pfn;
+ PHYSICAL_ADDRESS Address;
+ PUCHAR MdlMappedSystemVa;
+ NTSTATUS status;
+
+ status = STATUS_UNSUCCESSFUL;
+ if (Cpu >= __SystemProcessorCount())
+ goto fail1;
+
+ ASSERT(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA);
+ MdlMappedSystemVa = Mdl->MappedSystemVa;
+
+ Offset = sizeof (vcpu_info_t) * HVM_MAX_VCPUS;
+ Offset += sizeof (BOOLEAN) * Cpu;
+
+ Processor->Registered = (PBOOLEAN)(MdlMappedSystemVa + Offset);
+
+ Offset = sizeof (vcpu_info_t) * Cpu;
+
+ Processor->Vcpu = (vcpu_info_t *)(MdlMappedSystemVa + Offset);
+
+ Pfn = MmGetMdlPfnArray(Context->Mdl)[Offset >> PAGE_SHIFT];
+ Offset = Offset & (PAGE_SIZE - 1);
+
+ if (!*Processor->Registered || Force) {
+ unsigned int vcpu_id;
+
+ status = SystemProcessorVcpuId(Cpu, &vcpu_id);
+ ASSERT(NT_SUCCESS(status));
+
+ status = VcpuRegisterVcpuInfo(vcpu_id, Pfn, Offset);
+ if (!NT_SUCCESS(status))
+ goto fail2;
+
+ LogPrintf(LOG_LEVEL_INFO,
+ "XEN: REGISTER vcpu_info[%u]\n",
+ Cpu);
+
+ *Processor->Registered = TRUE;
+ }
+
+ Address.QuadPart = (ULONGLONG)Pfn << PAGE_SHIFT;
+ Address.QuadPart += Offset;
+
+ LogPrintf(LOG_LEVEL_INFO,
+ "XEN: vcpu_info[%u] @ %08x.%08x\n",
+ Cpu,
+ Address.HighPart,
+ Address.LowPart);
+
+ return STATUS_SUCCESS;
+
+fail2:
+ Error("fail2\n");
+
+ Processor->Vcpu = NULL;
+ Processor->Registered = NULL;
+
+fail1:
+ Error("fail1 (%08x)\n", status);
+
+ return status;
+}
+
+static VOID
+SystemProcessorDeregisterVcpuInfo(
+ IN ULONG Cpu
+ )
+{
+ PSYSTEM_CONTEXT Context = &SystemContext;
+ PSYSTEM_PROCESSOR Processor = &Context->Processor[Cpu];
+
+ Processor->Vcpu = NULL;
+ Processor->Registered = NULL;
+}
+
static
_Function_class_(KDEFERRED_ROUTINE)
_IRQL_requires_max_(DISPATCH_LEVEL)
ULONG Cpu;
PROCESSOR_NUMBER ProcNumber;
PSYSTEM_PROCESSOR Processor;
+ NTSTATUS status;
UNREFERENCED_PARAMETER(Dpc);
UNREFERENCED_PARAMETER(_Context);
SystemProcessorInitialize(Cpu);
+ status = SystemProcessorRegisterVcpuInfo(Cpu, FALSE);
+ if (!NT_SUCCESS(status))
+ goto fail1;
+
Info("<==== (%u:%u)\n", ProcNumber.Group, ProcNumber.Number);
Processor->Status = STATUS_SUCCESS;
KeSetEvent(&Processor->Event, IO_NO_INCREMENT, FALSE);
+
+ return;
+
+fail1:
+ Error("fail1 (%08x)\n", status);
+
+ Processor->Status = status;
+ KeSetEvent(&Processor->Event, IO_NO_INCREMENT, FALSE);
}
static
ProcessorChangeName(Change->State));
}
+static NTSTATUS
+SystemAllocateVcpuInfo(
+ VOID
+ )
+{
+ PSYSTEM_CONTEXT Context = &SystemContext;
+ ULONG Size;
+ NTSTATUS status;
+
+ Size = sizeof (vcpu_info_t) * HVM_MAX_VCPUS;
+ Size += sizeof (BOOLEAN) * HVM_MAX_VCPUS;
+ Size = P2ROUNDUP(Size, PAGE_SIZE);
+
+ Context->Mdl = DriverGetNamedPages("VCPU_INFO", Size >> PAGE_SHIFT);
+
+ status = STATUS_NO_MEMORY;
+ if (Context->Mdl == NULL)
+ goto fail1;
+
+ return STATUS_SUCCESS;
+
+fail1:
+ Error("fail1 (%08x)\n", status);
+
+ return status;
+}
+
+static VOID
+SystemFreeVcpuInfo(
+ VOID
+ )
+{
+ PSYSTEM_CONTEXT Context = &SystemContext;
+
+ DriverPutNamedPages(Context->Mdl);
+ Context->Mdl = NULL;
+}
+
static NTSTATUS
SystemRegisterProcessorChangeCallback(
VOID
PVOID Handle;
NTSTATUS status;
+ status = SystemAllocateVcpuInfo();
+ if (!NT_SUCCESS(status))
+ goto fail1;
+
Handle = KeRegisterProcessorChangeCallback(SystemProcessorChangeCallback,
NULL,
KE_PROCESSOR_CHANGE_ADD_EXISTING);
status = STATUS_UNSUCCESSFUL;
if (Handle == NULL)
- goto fail1;
+ goto fail2;
Context->ProcessorChangeHandle = Handle;
return STATUS_SUCCESS;
+fail2:
+ Error("fail2\n");
+
+ SystemFreeVcpuInfo();
+
fail1:
Error("fail1 (%08x)\n", status);
for (Cpu = 0; Cpu < __SystemProcessorCount(); Cpu++) {
PSYSTEM_PROCESSOR Processor = &Context->Processor[Cpu];
+ SystemProcessorDeregisterVcpuInfo(Cpu);
SystemProcessorTeardown(Cpu);
RtlZeroMemory(&Processor->Dpc, sizeof (KDPC));
__SystemFree(Context->Processor);
Context->Processor = NULL;
Context->ProcessorCount = 0;
+
+ SystemFreeVcpuInfo();
}
static NTSTATUS
return __SystemProcessorCount();
}
-XEN_API
-NTSTATUS
-SystemVirtualCpuIndex(
- IN ULONG Cpu,
- OUT unsigned int *vcpu_id
- )
-{
- PSYSTEM_CONTEXT Context = &SystemContext;
- PSYSTEM_PROCESSOR Processor = &Context->Processor[Cpu];
- NTSTATUS status;
-
- status = STATUS_UNSUCCESSFUL;
- if (Cpu >= __SystemProcessorCount())
- goto fail1;
-
- *vcpu_id = Processor->ProcessorID;
- return STATUS_SUCCESS;
-
-fail1:
- return status;
-}
-
XEN_API
PHYSICAL_ADDRESS
SystemMaximumPhysicalAddress(
if (!Processor->UpcallEnabled && Cpu != 0)
goto fail1;
- status = SystemVirtualCpuIndex(Cpu, &vcpu_id);
+ status = SystemProcessorVcpuId(Cpu, &vcpu_id);
ASSERT(NT_SUCCESS(status));
status = EventChannelBindVirq(Index, vcpu_id, &LocalPort);
LocalPort = Channel->LocalPort;
- status = SystemVirtualCpuIndex(Cpu, &vcpu_id);
+ status = SystemProcessorVcpuId(Cpu, &vcpu_id);
ASSERT(NT_SUCCESS(status));
status = EventChannelBindVirtualCpu(LocalPort, vcpu_id);
if (Processor->Interrupt == NULL)
continue;
- status = SystemVirtualCpuIndex(Cpu, &vcpu_id);
+ status = SystemProcessorVcpuId(Cpu, &vcpu_id);
ASSERT(NT_SUCCESS(status));
Vector = FdoGetInterruptVector(Context->Fdo, Processor->Interrupt);
if (!Processor->UpcallEnabled)
continue;
- status = SystemVirtualCpuIndex(Cpu, &vcpu_id);
+ status = SystemProcessorVcpuId(Cpu, &vcpu_id);
ASSERT(NT_SUCCESS(status));
(VOID) HvmSetEvtchnUpcallVector(vcpu_id, 0);
)
{
UNREFERENCED_PARAMETER(_Context);
+ UNREFERENCED_PARAMETER(Index);
- //
- // We currently rely on using the vcpu_info array that is embedded
- // in the shared_info.
- //
- return (Index < XEN_LEGACY_MAX_VCPUS) ? TRUE : FALSE;
+ return TRUE;
}
static BOOLEAN
unsigned int vcpu_id;
NTSTATUS status;
- status = SystemVirtualCpuIndex(Index, &vcpu_id);
+ status = SystemProcessorVcpuId(Index, &vcpu_id);
if (!NT_SUCCESS(status))
return FALSE;
DoneSomething = FALSE;
- status = SystemVirtualCpuIndex(Index, &vcpu_id);
+ status = SystemProcessorVcpuId(Index, &vcpu_id);
if (!NT_SUCCESS(status))
goto done;
if (Mdl == NULL)
goto fail1;
- status = SystemVirtualCpuIndex(Index, &vcpu_id);
+ status = SystemProcessorVcpuId(Index, &vcpu_id);
ASSERT(NT_SUCCESS(status));
Pfn = MmGetMdlPfnArray(Mdl)[0];
while (--Index >= 0) {
unsigned int vcpu_id;
- (VOID) SystemVirtualCpuIndex(Index, &vcpu_id);
+ (VOID) SystemProcessorVcpuId(Index, &vcpu_id);
Mdl = Context->ControlBlockMdl[vcpu_id];
Context->ControlBlockMdl[vcpu_id] = NULL;
unsigned int vcpu_id;
NTSTATUS status;
- status = SystemVirtualCpuIndex(Virq->Cpu, &vcpu_id);
+ status = SystemProcessorVcpuId(Virq->Cpu, &vcpu_id);
ASSERT(NT_SUCCESS(status));
(VOID) VcpuSetPeriodicTimer(vcpu_id, NULL);
if (Type == VIRQ_TIMER) {
LARGE_INTEGER Period;
- status = SystemVirtualCpuIndex(Cpu, &vcpu_id);
+ status = SystemProcessorVcpuId(Cpu, &vcpu_id);
ASSERT(NT_SUCCESS(status));
BUG_ON(Fdo->Watchdog == 0);
static BOOLEAN
SharedInfoUpcallPending(
- IN PINTERFACE Interface,
- IN ULONG Index
+ IN PINTERFACE Interface,
+ IN ULONG Index
)
{
- PXENBUS_SHARED_INFO_CONTEXT Context = Interface->Context;
- shared_info_t *Shared = Context->Shared;
- unsigned int vcpu_id;
- UCHAR Pending;
- NTSTATUS status;
+ vcpu_info_t *Vcpu;
+ UCHAR Pending;
+ NTSTATUS status;
- status = SystemVirtualCpuIndex(Index, &vcpu_id);
+ UNREFERENCED_PARAMETER(Interface);
+
+ status = SystemProcessorVcpuInfo(Index, &Vcpu);
if (!NT_SUCCESS(status))
return FALSE;
KeMemoryBarrier();
- Pending = _InterlockedExchange8((CHAR *)&Shared->vcpu_info[vcpu_id].evtchn_upcall_pending, 0);
+ Pending = _InterlockedExchange8((CHAR *)&Vcpu->evtchn_upcall_pending, 0);
return (Pending != 0) ? TRUE : FALSE;
}
PXENBUS_SHARED_INFO_CONTEXT Context = Interface->Context;
shared_info_t *Shared = Context->Shared;
unsigned int vcpu_id;
+ vcpu_info_t *Vcpu;
ULONG Port;
ULONG_PTR SelectorMask;
BOOLEAN DoneSomething;
DoneSomething = FALSE;
- status = SystemVirtualCpuIndex(Index, &vcpu_id);
+ status = SystemProcessorVcpuId(Index, &vcpu_id);
+ if (!NT_SUCCESS(status))
+ goto done;
+
+ status = SystemProcessorVcpuInfo(Index, &Vcpu);
if (!NT_SUCCESS(status))
goto done;
KeMemoryBarrier();
- SelectorMask = (ULONG_PTR)InterlockedExchangePointer((PVOID *)&Shared->vcpu_info[vcpu_id].evtchn_pending_sel, (PVOID)0);
+ SelectorMask = (ULONG_PTR)InterlockedExchangePointer((PVOID *)&Vcpu->evtchn_pending_sel, (PVOID)0);
KeMemoryBarrier();
PXENBUS_SHARED_INFO_CONTEXT Context = Interface->Context;
shared_info_t *Shared;
+ vcpu_info_t *Vcpu;
ULONG WcVersion;
ULONG TimeVersion;
ULONGLONG Seconds;
CHAR TscShift;
TIME_FIELDS TimeFields;
KIRQL Irql;
+ NTSTATUS status;
// Make sure we don't suspend
KeRaiseIrql(DISPATCH_LEVEL, &Irql);
Shared = Context->Shared;
+ status = SystemProcessorVcpuInfo(0, &Vcpu);
+ ASSERT(NT_SUCCESS(status));
+
// Loop until we can read a consistent set of values from the same update
do {
WcVersion = Shared->wc_version;
- TimeVersion = Shared->vcpu_info[0].time.version;
+ TimeVersion = Vcpu->time.version;
KeMemoryBarrier();
// Wallclock time at system time zero (guest boot or resume)
NanoSeconds = Shared->wc_nsec;
// Cached time in nanoseconds since guest boot
- SystemTime = Shared->vcpu_info[0].time.system_time;
+ SystemTime = Vcpu->time.system_time;
// Timestamp counter value when these time values were last updated
- Timestamp = Shared->vcpu_info[0].time.tsc_timestamp;
+ Timestamp = Vcpu->time.tsc_timestamp;
// Timestamp modifiers
- TscShift = Shared->vcpu_info[0].time.tsc_shift;
- TscSystemMul = Shared->vcpu_info[0].time.tsc_to_system_mul;
+ TscShift = Vcpu->time.tsc_shift;
+ TscSystemMul = Vcpu->time.tsc_to_system_mul;
KeMemoryBarrier();
// Version is incremented to indicate update in progress.
// LSB of version is set if update in progress.
// Version is incremented again once update has completed.
} while (Shared->wc_version != WcVersion ||
- Shared->vcpu_info[0].time.version != TimeVersion ||
+ Vcpu->time.version != TimeVersion ||
(WcVersion & 1) ||
(TimeVersion & 1));
Index < KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS);
Index++) {
PROCESSOR_NUMBER ProcNumber;
- unsigned int vcpu_id;
+ vcpu_info_t *Vcpu;
NTSTATUS status;
- status = SystemVirtualCpuIndex(Index, &vcpu_id);
+ status = SystemProcessorVcpuInfo(Index, &Vcpu);
if (!NT_SUCCESS(status))
continue;
"CPU %u:%u: PENDING: %s\n",
ProcNumber.Group,
ProcNumber.Number,
- Shared->vcpu_info[vcpu_id].evtchn_upcall_pending ?
+ Vcpu->evtchn_upcall_pending ?
"TRUE" :
"FALSE");
"CPU %u:%u: SELECTOR MASK: %p\n",
ProcNumber.Group,
ProcNumber.Number,
- (PVOID)Shared->vcpu_info[vcpu_id].evtchn_pending_sel);
+ (PVOID)Vcpu->evtchn_pending_sel);
}
for (Selector = 0; Selector < XENBUS_SHARED_INFO_EVTCHN_SELECTOR_COUNT; Selector += 4) {
LogPrintf(LOG_LEVEL_INFO,
"SUSPEND: EARLY (%u)\n", Cpu);
- if (!Context->Success || Cpu != 0)
+ if (!Context->Success)
return;
//
Context->Count++;
+ SystemProcessorRegisterVcpuInfo(Cpu, TRUE);
+
+ if (Cpu != 0)
+ return;
+
HypercallPopulate();
UnplugDevices();
<AdditionalIncludeDirectories>$(WindowsSdkDir)\include\km;..\..\include;..\..\include\xen;..\..\src\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>PROJECT=$(ProjectName);POOL_NX_OPTIN=1;NT_PROCESSOR_GROUPS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>EnableAllWarnings</WarningLevel>
- <DisableSpecificWarnings>4464;4711;4548;4820;4668;4255;6001;6054;28196;30030;30029;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <DisableSpecificWarnings>4146;4464;4711;4548;4820;4668;4255;6001;6054;28196;30030;30029;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<EnablePREfast>true</EnablePREfast>
</ClCompile>
<PreprocessorDefinitions>PROJECT=$(ProjectName);POOL_NX_OPTIN=1;NT_PROCESSOR_GROUPS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<IntrinsicFunctions>true</IntrinsicFunctions>
<WarningLevel>EnableAllWarnings</WarningLevel>
- <DisableSpecificWarnings>4464;4711;4770;4548;4820;4668;4255;5045;6001;6054;28196;30030;30029;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <DisableSpecificWarnings>4146;4464;4711;4770;4548;4820;4668;4255;5045;6001;6054;28196;30030;30029;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<EnablePREfast>true</EnablePREfast>
</ClCompile>
<PreprocessorDefinitions>PROJECT=$(ProjectName);POOL_NX_OPTIN=1;NT_PROCESSOR_GROUPS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<IntrinsicFunctions>true</IntrinsicFunctions>
<WarningLevel>EnableAllWarnings</WarningLevel>
- <DisableSpecificWarnings>4464;4711;4770;4548;4820;4668;4255;5045;6001;6054;26451;28196;30030;30029;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ <DisableSpecificWarnings>4146;4464;4711;4770;4548;4820;4668;4255;5045;6001;6054;26451;28196;30030;30029;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<EnablePREfast>true</EnablePREfast>
</ClCompile>