Index: trunk/src/VBox/VMM/VMM.cpp
===================================================================
--- trunk/src/VBox/VMM/VMM.cpp	(revision 20543)
+++ trunk/src/VBox/VMM/VMM.cpp	(revision 20545)
@@ -380,4 +380,13 @@
     STAM_REG(pVM, &pVM->vmm.s.StatRZCallVMSetError,         STAMTYPE_COUNTER, "/VMM/RZCallR3/VMSetError",       STAMUNIT_OCCURENCES, "Number of VMMCALLHOST_VM_SET_ERROR calls.");
     STAM_REG(pVM, &pVM->vmm.s.StatRZCallVMSetRuntimeError,  STAMTYPE_COUNTER, "/VMM/RZCallR3/VMRuntimeError",   STAMUNIT_OCCURENCES, "Number of VMMCALLHOST_VM_SET_RUNTIME_ERROR calls.");
+
+#ifdef VBOX_WITH_STATISTICS
+    for (VMCPUID i = 0; i < pVM->cCPUs; i++)
+    {
+        STAMR3RegisterF(pVM, &pVM->aCpus[i].vmm.s.CallHostR0JmpBuf.cbUsedMax,  STAMTYPE_U32_RESET, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,      "Max amount of stack used.", "/VMM/Stack/CPU%u/Max", i);
+        STAMR3RegisterF(pVM, &pVM->aCpus[i].vmm.s.CallHostR0JmpBuf.cbUsedAvg,  STAMTYPE_U32,       STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,      "Average stack usage.",      "/VMM/Stack/CPU%u/Avg", i);
+        STAMR3RegisterF(pVM, &pVM->aCpus[i].vmm.s.CallHostR0JmpBuf.cUsedTotal, STAMTYPE_U64,       STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Number of stack usages.",   "/VMM/Stack/CPU%u/Uses", i);
+    }
+#endif
 }
 
Index: trunk/src/VBox/VMM/VMMInternal.h
===================================================================
--- trunk/src/VBox/VMM/VMMInternal.h	(revision 20543)
+++ trunk/src/VBox/VMM/VMMInternal.h	(revision 20545)
@@ -170,4 +170,13 @@
     /** EBP/RBP at the time of the jump to ring 3. */
     RTHCUINTREG                 SavedEbp;
+
+    /** Stats: Max amount of stack used. */
+    uint32_t                    cbUsedMax;
+    /** Stats: Average stack usage. (Avg = cbUsedTotal / cUsedTotal) */
+    uint32_t                    cbUsedAvg;
+    /** Stats: Total amount of stack used. */
+    uint64_t                    cbUsedTotal;
+    /** Stats: Number of stack usages. */
+    uint64_t                    cUsedTotal;
 } VMMR0JMPBUF;
 /** Pointer to a ring-0 jump buffer. */
Index: trunk/src/VBox/VMM/VMMInternal.mac
===================================================================
--- trunk/src/VBox/VMM/VMMInternal.mac	(revision 20543)
+++ trunk/src/VBox/VMM/VMMInternal.mac	(revision 20545)
@@ -78,4 +78,10 @@
     .SavedEbp       resq 1
 %endif
+
+    ; Statistics
+    .cbUsedMax      resd 1
+    .cbUsedAvg      resd 1
+    .cbUsedTotal    resq 1
+    .cUsedTotal     resq 1
 endstruc
 
Index: trunk/src/VBox/VMM/VMMR0/VMMR0JmpA-amd64.asm
===================================================================
--- trunk/src/VBox/VMM/VMMR0/VMMR0JmpA-amd64.asm	(revision 20543)
+++ trunk/src/VBox/VMM/VMMR0/VMMR0JmpA-amd64.asm	(revision 20545)
@@ -27,4 +27,15 @@
 %include "iprt/err.mac"
 %include "VBox/param.mac"
+
+
+;*******************************************************************************
+;*  Defined Constants And Macros                                               *
+;*******************************************************************************
+%define RESUME_MAGIC    07eadf00dh
+%define STACK_PADDING   0eeeeeeeeeeeeeeeeh
+
+
+; For vmmR0LoggerWrapper. (The other architecture(s) use(s) C99 variadict macros.)
+extern NAME(RTLogLogger)
 
 
@@ -94,5 +105,5 @@
     mov     rdi, r15
     mov     rcx, VMM_STACK_SIZE / 8
-    mov     rax, 00eeeeeeeeffeeeeeeeh
+    mov     rax, qword 0eeeeeeeffeeeeeeeh
     repne stosq
     mov     [rdi - 10h], rbx
@@ -205,6 +216,6 @@
     ;
 %ifdef VBOX_STRICT
-    pop     eax                         ; magic
-    cmp     eax, 0f00dbed0h
+    pop     rax                         ; magic
+    cmp     rax, RESUME_MAGIC
     je      .magic_ok
     mov     ecx, 0123h
@@ -252,5 +263,5 @@
     pushf
 %ifdef VBOX_STRICT
-    push    dword 0f00dbed0h
+    push    RESUME_MAGIC
 %endif
 
@@ -333,5 +344,5 @@
 %ifdef VBOX_STRICT
     pop     rax                         ; magic
-    cmp     eax, 0f00dbed0h
+    cmp     rax, RESUME_MAGIC
     je      .magic_ok
     mov     ecx, 0123h
Index: trunk/src/VBox/VMM/VMMR0/VMMR0JmpA-x86.asm
===================================================================
--- trunk/src/VBox/VMM/VMMR0/VMMR0JmpA-x86.asm	(revision 20543)
+++ trunk/src/VBox/VMM/VMMR0/VMMR0JmpA-x86.asm	(revision 20545)
@@ -27,4 +27,11 @@
 %include "iprt/err.mac"
 %include "VBox/param.mac"
+
+
+;*******************************************************************************
+;*  Defined Constants And Macros                                               *
+;*******************************************************************************
+%define RESUME_MAGIC    07eadf00dh
+%define STACK_PADDING   0eeeeeeeeh
 
 
@@ -81,5 +88,5 @@
     mov     edi, esi
     mov     ecx, VMM_STACK_SIZE / 4
-    mov     eax, 0eeeeeeeeh
+    mov     eax, STACK_PADDING
     repne stosd
  %endif
@@ -96,24 +103,50 @@
     mov     esp, esi                    ; Switch stack!
     call    eax
-    and     dword [esi + 1ch], byte 0   ; clear marker.
+    and     dword [esi + 1ch], byte 0   ; reset marker.
 
  %ifdef VBOX_STRICT
-    mov     esi, [ebx + VMMR0JMPBUF.pvSavedStack]
-    cmp     [esi], 0eeeeeeeeh           ; Check for stack overflow
+    ; Calc stack usage and check for overflows.
+    mov     edi, [ebx + VMMR0JMPBUF.pvSavedStack]
+    cmp     dword [edi], STACK_PADDING  ; Check for obvious stack overflow.
     jne     .stack_overflow
-    cmp     [esi + 04h], 0eeeeeeeeh
-    jne     .stack_overflow
-    cmp     [esi + 08h], 0eeeeeeeeh
-    jne     .stack_overflow
-    cmp     [esi + 0ch], 0eeeeeeeeh
-    jne     .stack_overflow
-    cmp     [esi + 10h], 0eeeeeeeeh
-    jne     .stack_overflow
-    cmp     [esi + 20h], 0eeeeeeeeh
-    jne     .stack_overflow
-    cmp     [esi + 30h], 0eeeeeeeeh
-    jne     .stack_overflow
-    mov     dword [esi], 0h             ; Reset the marker
- %endif
+    mov     esi, eax                    ; save eax
+    mov     eax, STACK_PADDING
+    mov     ecx, VMM_STACK_SIZE / 4
+    cld
+    repe scasd
+    mov     eax, esi                    ; restore eax in case of overflow (esi remains used)
+    mov     edi, VMM_STACK_SIZE
+    shl     ecx, 2                      ; *4
+    sub     edi, ecx
+    cmp     edi, VMM_STACK_SIZE - 64    ; Less than 64 bytes left -> overflow as well.
+    jae     .stack_overflow_almost
+
+    ; Update stack usage statistics.
+    cmp     edi, [ebx + VMMR0JMPBUF.cbUsedMax] ; New max usage?
+    jle     .no_used_max
+    mov     [ebx + VMMR0JMPBUF.cbUsedMax], edi
+.no_used_max:
+    ; To simplify the average stuff, just historize before we hit div errors.
+    inc     dword [ebx + VMMR0JMPBUF.cUsedTotal]
+    test    [ebx + VMMR0JMPBUF.cUsedTotal], dword 0c0000000h
+    jz      .no_historize
+    mov     dword [ebx + VMMR0JMPBUF.cUsedTotal], 2
+    mov     ecx, [ebx + VMMR0JMPBUF.cbUsedAvg]
+    mov     [ebx + VMMR0JMPBUF.cbUsedTotal], ecx
+    mov     dword [ebx + VMMR0JMPBUF.cbUsedTotal + 4], 0
+.no_historize:
+    add     [ebx + VMMR0JMPBUF.cbUsedTotal], edi
+    adc     dword [ebx + VMMR0JMPBUF.cbUsedTotal + 4], 0
+    mov     eax, [ebx + VMMR0JMPBUF.cbUsedTotal]
+    mov     edx, [ebx + VMMR0JMPBUF.cbUsedTotal + 4]
+    mov     ecx, [ebx + VMMR0JMPBUF.cUsedTotal]
+    div     ecx
+    mov     [ebx + VMMR0JMPBUF.cbUsedAvg], eax
+
+    mov     eax, esi                    ; restore eax (final, esi released)
+
+    mov     edi, [ebx + VMMR0JMPBUF.pvSavedStack]
+    mov     dword [edi], 0h             ; Reset the overflow marker.
+ %endif ; VBOX_STRICT
 
 %else  ; !VMM_R0_SWITCH_STACK
@@ -147,4 +180,10 @@
 .stack_overflow:
     mov     eax, VERR_INTERNAL_ERROR_5
+    mov     edx, ebx
+    jmp     .proper_return
+
+.stack_overflow_almost:
+    mov     eax, VERR_INTERNAL_ERROR
+    mov     edx, ebx
     jmp     .proper_return
 
@@ -168,5 +207,5 @@
     mov     eax, [xDX + VMMR0JMPBUF.pvSavedStack]
  %ifdef RT_STRICT
-    cmp     dword [eax], 0eeeeeeeeh
+    cmp     dword [eax], STACK_PADDING
  %endif
     lea     eax, [eax + VMM_STACK_SIZE - 32]
@@ -215,5 +254,5 @@
 %ifdef VBOX_STRICT
     pop     eax                         ; magic
-    cmp     eax, 0f00dbed0h
+    cmp     eax, RESUME_MAGIC
     je      .magic_ok
     mov     ecx, 0123h
@@ -249,5 +288,5 @@
     pushf
 %ifdef VBOX_STRICT
-    push    dword 0f00dbed0h
+    push    RESUME_MAGIC
 %endif
 
@@ -318,5 +357,5 @@
 %ifdef VBOX_STRICT
     pop     eax                         ; magic
-    cmp     eax, 0f00dbed0h
+    cmp     eax, RESUME_MAGIC
     je      .magic_ok
     mov     ecx, 0123h
Index: trunk/src/VBox/VMM/testcase/tstVMMR0CallHost-1.cpp
===================================================================
--- trunk/src/VBox/VMM/testcase/tstVMMR0CallHost-1.cpp	(revision 20543)
+++ trunk/src/VBox/VMM/testcase/tstVMMR0CallHost-1.cpp	(revision 20545)
@@ -23,10 +23,11 @@
 *   Header Files                                                               *
 *******************************************************************************/
+#include <VBox/err.h>
+#include <VBox/param.h>
+#include <iprt/alloca.h>
 #include <iprt/initterm.h>
 #include <iprt/string.h>
 #include <iprt/stream.h>
-#include <iprt/alloca.h>
 #include <iprt/test.h>
-#include <VBox/err.h>
 
 #define IN_VMM_R0
@@ -51,4 +52,8 @@
 /** The number of jumps we've done. */
 static unsigned volatile    g_cJmps;
+/** Number of bytes allocated last time we called foo(). */
+static size_t volatile      g_cbFoo;
+/** Number of bytes used last time we called foo(). */
+static intptr_t volatile    g_cbFooUsed;
 
 
@@ -56,7 +61,18 @@
 {
     /* allocate a buffer which we fill up to the end. */
-    size_t cb = (i % 5555) + 32;
+    size_t cb = (i % 1555) + 32;
+    g_cbFoo = cb;
     char  *pv = (char *)alloca(cb);
     RTStrPrintf(pv, cb, "i=%d%*s\n", i, cb, "");
+#ifdef VMM_R0_SWITCH_STACK
+    g_cbFooUsed = VMM_STACK_SIZE - ((uintptr_t)pv - (uintptr_t)g_Jmp.pvSavedStack);
+    RTTESTI_CHECK_MSG_RET(g_cbFooUsed < VMM_STACK_SIZE - 128, ("%#x - (%p - %p) -> %#x; cb=%#x i=%d\n", VMM_STACK_SIZE, pv, g_Jmp.pvSavedStack, g_cbFooUsed, cb, i), -15);
+#elif defined(RT_ARCH_AMD64)
+    g_cbFooUsed = (uintptr_t)g_Jmp.rsp - (uintptr_t)pv;
+    RTTESTI_CHECK_MSG_RET(g_cbFooUsed < VMM_STACK_SIZE - 128, ("%p - %p -> %#x; cb=%#x i=%d\n", g_Jmp.rsp, pv, g_cbFooUsed, cb, i), -15);
+#elif defined(RT_ARCH_X86)
+    g_cbFooUsed = (uintptr_t)g_Jmp.esp - (uintptr_t)pv;
+    RTTESTI_CHECK_MSG_RET(g_cbFooUsed < VMM_STACK_SIZE - 128, ("%p - %p -> %#x; cb=%#x i=%d\n", g_Jmp.esp, pv, g_cbFooUsed, cb, i), -15);
+#endif
 
     /* Do long jmps every 7th time */
@@ -92,9 +108,16 @@
 #endif
 
+    RTR0PTR R0PtrSaved = g_Jmp.pvSavedStack;
+    RT_ZERO(g_Jmp);
+    g_Jmp.pvSavedStack = R0PtrSaved;
+    memset((void *)g_Jmp.pvSavedStack, '\0', VMM_STACK_SIZE);
+    g_cbFoo = 0;
     g_cJmps = 0;
+    g_cbFooUsed = 0;
+
     for (int i = iFrom, iItr = 0; i != iTo; i += iInc, iItr++)
     {
         int rc = vmmR0CallHostSetJmp(&g_Jmp, (PFNVMMR0SETJMP)tst2, (PVM)i, 0);
-        RTTESTI_CHECK_MSG_RETV(rc == 0 || rc == 42, ("i=%d rc=%d setjmp\n", i, rc));
+        RTTESTI_CHECK_MSG_RETV(rc == 0 || rc == 42, ("i=%d rc=%d setjmp; cbFoo=%#x cbFooUsed=%#x\n", i, rc, g_cbFoo, g_cbFooUsed));
 
 #ifdef VMM_R0_SWITCH_STACK
@@ -113,4 +136,7 @@
     }
     RTTESTI_CHECK_MSG_RETV(g_cJmps, ("No jumps!"));
+    if (g_Jmp.cbUsedAvg || g_Jmp.cUsedTotal)
+        RTTestIPrintf(RTTESTLVL_ALWAYS, "cbUsedAvg=%#x cbUsedMax=%#x cUsedTotal=%#llx\n",
+                      g_Jmp.cbUsedAvg, g_Jmp.cbUsedMax, g_Jmp.cUsedTotal);
 }
 
@@ -131,5 +157,5 @@
     RTTestBanner(hTest);
 
-    g_Jmp.pvSavedStack = (RTR0PTR)RTTestGuardedAllocTail(hTest, 8192);
+    g_Jmp.pvSavedStack = (RTR0PTR)RTTestGuardedAllocTail(hTest, VMM_STACK_SIZE);
 
     /*
