The context is that I'm calling DOS interrupts from DPMI using int31 / ax=0x300, and you have to tell it what stack you want the real mode call to have. By default you get a small stack of about 20 bytes which isn't nearly enough. Experimentally I've found that 128 bytes is still too small and 512 seems to work, but it'd be nice to have a definitive source as to what it should be.
I’m not aware of any official documentation of MS-DOS’s stack requirements for interrupt 0x21; in any case, that wouldn’t paint the full picture since any TSR or driver hooking the interrupt could add to the required stack size without providing any means of determining how much extra room it required.
The real mode stack is also provided by the DPMI host, and is usually located in the DPMI host data area allocated by the client prior to its initial switch into protected mode. The real mode stack is at least 200H bytes in size and is always located in locked memory. Interrupts that are reflected to real mode, as well as calls to real mode interrupt handlers or procedures via Int 31H Functions 0300H, 0301H, or 0302H, will use this stack.
So as far as the DPMI specification is concerned, the answer is 512 bytes. This was already the case in version 0.9 of the specification:
The DPMI host will provide the client with a real mode stack that is at least 200h bytes in size and will always be locked. Interrupts that are reflected into real mode, as well as calls made using the translation services, will be reflected on this stack. DPMI hosts will not automatically switch stacks for hardware interrupt processing in real mode since DOS performs this function automatically.
Your findings suggest that at least some DPMI implementations provide a (much) smaller stack; Ralf Brown’s Interrupt List agrees, saying “DPMI will provide a small (30 words) real mode stack if SS:SP is zero”. I imagine there’s a reason behind the 512-byte minimum in the specification, so I take this as confirmation of your findings: the default stack can’t be relied upon (whatever the specification says), but having the caller provide a 512-byte stack should be sufficient.
Typically you’d use a DOS extender which would provide a protected-mode interrupt 0x21 handler and take care of all this for you, but presumably that’s not applicable here.