Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KVM: Rudimentary support for VCPI #1880

Draft
wants to merge 16 commits into
base: devel
Choose a base branch
from
Draft

Conversation

bartoldeman
Copy link
Contributor

Implement basic VCPI support with limitations.
The limitations are:
$_dpmi = (0)
$_ems = (0)

  • don't use FDPP
  • use external XMS provider (HIMEM/FDXMS)

VCPI clients allocate memory from XMS only, so EMS needs to report 0 memory, and XMS needs to map identical "physical" memory starting at 0x110000, which would normally be taken by DPMI memory.

The page table maps LOW+HMA as usual, then a page at 0x110000 to monitor code implementing a monitor->VCPI client jump and a VCPI client -> VM86 jump. A page at 0x111000 contains the saved monitor GDTR/IDTR/CR3 values and a temporary stack, with hiword(esp)=0, for the client to use. The monitor code is much like Jemm's.

When KVM interrupts the VCPI client through a signal, DOSEMU does its regular things, but CANNOT modify any registers, as the client registers stay in the VM. pic_run() will see VIF is not set, so won't modify, and the kvm.c code needs to use KVM_INTERRUPT if pic_pending().
The only other place that has been adapted for a callback into vm86 is leavedos().

VGAEMU memory is unprotected for now, so updates aren't reliable, and VGA planar modes don't work.

DOOM is playable but a bit slow due to frequent VGA I/O port accesses which would normally go via instremu. Duke Nukem 3D runs but with choppy sound and incomplete screen updates.

@bartoldeman bartoldeman marked this pull request as draft January 18, 2023 00:51
@stsp stsp mentioned this pull request Jan 18, 2023
@stsp
Copy link
Member

stsp commented Jan 18, 2023

VCPI clients allocate memory from XMS only, so EMS needs to report 0 memory, and XMS needs to
map identical "physical" memory starting at 0x110000, which would normally be taken by DPMI memory.

I reverted that optimization in #1881.
Please let me know if this is what you
are looking for - that should allow vpci
to work with internal XMS.

Other than that - quite interesting, but
could you please describe exactly what
does this give us? win95?
Also you likely want to ruin the arm port,
don't you? :) Or maybe you want to move
to tcg, allowing the arm port to provide
vcpi too?

@stsp
Copy link
Member

stsp commented Jan 18, 2023

Have you considered the use of
the KVM_CAP_SYNC_REGS, as
in #1408 ?
Unless I am missing the actual
problem you are facing, with
SYNC_REGS the aforementioned
limitations will go away because
you will always have the right
registers at hands. Monitor then
doesn't have to save/restore them.

@stsp
Copy link
Member

stsp commented Jan 18, 2023

VGAEMU memory is unprotected for now, so updates aren't reliable, and VGA planar modes don't work.

We still have the vgacpy branch in #1099
Hmm, looks like we have many solutions
around, waiting for a problem. :) And
here it is, a problem.

@stsp
Copy link
Member

stsp commented Jan 18, 2023

The page table maps LOW+HMA as usual, then a page at 0x110000 to monitor code

Can you put it somewhere upwards,
into the "main_pool"?

@stsp
Copy link
Member

stsp commented Jan 18, 2023

By dirtying all pages. Can be improved using KVM_GET_DIRTY_LOG.

As in #198 ?

@bartoldeman
Copy link
Contributor Author

At the moment this is mostly a playground to see what is possible, with a VCPI client having full control over the VM, and to test some ideas, perhaps find some bugs, it also allows quick checking how DPMI provider X behaves vs. dosemu2's DPMI implementation. Then some of the ideas could go into devel before this would be merged.

This is for the moment a KVM only thing, nothing against Arm, just a bonus when KVM is there for now.

Sure Windows 95 and various games that need VCPI or flat real mode would be a bonus for sure.

The page table maps LOW+HMA as usual, then a page at 0x110000 to monitor code

Can you put it somewhere upwards,
into the "main_pool"?

How do you mean, moving the code and data page from the monitor to two pages allocated from the main pool?
I mean the whole monitor can be allocated from the main pool if we like now. Then we'd only have a single mmap for DOS addressable space.

VCPI spec says they must be mapped into the first 4MB (linear), could be in low space (e.g. I could put the VCPI<->VM86 switch code in bios.S), or mapped from somewhere high (which is what I'm doing now, monitor is high)

Note that before VCPI, KVM always identity maps, from guest virtual space to guest physical space. This keeps it consistent with native DPMI. But with VCPI the client has control over page tables so we only have control over physical space except (collaboratively!) for the first 1MB + 64k + up to 3 MB of virtual address space. That's why DPMI had to be disabled in the config, so that extmem is at physical (not linear) 0x110000.

As in #198 ?
yes

@stsp
Copy link
Member

stsp commented Jan 18, 2023

That's why DPMI had to be disabled in the config, so that extmem is at physical (not linear) 0x110000.

This part I don't understand.
dpmi_base is far above ext_mem.
They are quite unrelated.
With the reverts I did in a nearby
branch, ext_mem is going to be
mapped to the physical 0x110000
under KVM by the means of EPT.
So what is the problem?

@stsp
Copy link
Member

stsp commented Jan 18, 2023

ext_mem is aliased to some high space in
main_pool, and to 0x110000. Under KVM,
both these windows actually represent the
physical addresses. And the linear addresses
too, if we set up the identity page tables.
But I don't see any connection with dpmi,
could you please clarify?

@bartoldeman
Copy link
Contributor Author

oh I may be slightly out of date, as I see now that dpmi_base's default was moved from 8MB to 32MB. Which leaves max 31MB for extmem now.

Still for HX, 0x400000 (at 4MB linear) needs to be available for DPMI right, see #612?
So there's a conflict with extmem (if it uses more than 3MB, and mapped at 0x110000 linear) or is this handled somehow?

@stsp
Copy link
Member

stsp commented Jan 18, 2023

Yeah, that's right, and that part
I forgot to revert. :) Added the missing
reverts now.
Also I am not sure ext_mem is
actually mapped where it should,
even with reverts, because
MAPPING_INIT_LOWRAM alias
still seems to be done w/o ext_mem
size in low_mem_init(). But that's
trivial to fix.
So I suppose perhaps you don't
need to disable dpmi fully, just break
HX when vcpi switched on?

stsp added a commit that referenced this pull request Jan 18, 2023
... instead of in some high addresses.
This is needed for vcpi.
@stsp
Copy link
Member

stsp commented Jan 18, 2023

I added the patch that is supposed
to map it to kvm's phys addr now for
real. :)

@stsp
Copy link
Member

stsp commented Jan 18, 2023

So there's a conflict with extmem (if it uses more than 3MB, and mapped at 0x110000 linear) or is this handled
somehow?

In devel this is handled by mapping
ext_mem to higher addresses. Which
is the problem for vcpi, as under kvm
that "higher address" is a phys address.
In xms_rv branch this is handled by
lowering the ext_mem size...
But in a guest we don't need to map
ext_mem to any linear address. So perhaps
the better fix would be to leave things
as they are in devel and invent non-identity
maps for kvm? But that looks too tricky.

@stsp
Copy link
Member

stsp commented Jan 18, 2023

Well I guess the easiest solution for
now would be for you to just integrate
the xms_rv branch into yours, w/o pushing
it to devel. This will allow you to play with
3Mb of ext_mem, or increase it by the
cost of breaking HX, and later come up
with some other solution.

stsp added a commit that referenced this pull request Jan 18, 2023
This is needed for vcpi.
That way it is mapped to the right phys addr under kvm guest.
And it doesn't need to be shared that way as we only use the
identity mapping.
@stsp
Copy link
Member

stsp commented Jan 18, 2023

Hmm, perhaps I've found the simple
solution:
57c667b
Why not to just use dpmi_rsv_low
as ext_mem?

stsp added a commit that referenced this pull request Jan 18, 2023
This is needed for vcpi.
That way it is mapped to the right phys addr under kvm guest.
And it doesn't need to be shared that way as we only use the
identity mapping.

Don't auto-protect rsv_low in dpmi.
@stsp
Copy link
Member

stsp commented Jan 18, 2023

Except that then we shouldn't
write-protect reserved area, so
1e62ebf

@stsp
Copy link
Member

stsp commented Jan 18, 2023

xms_rv built and I think its quite
simple to apply to devel. Would
you like to check that it actually
helps vcpi?

stsp added a commit that referenced this pull request Jan 19, 2023
If we use identity mappings for ext_mem, then xms can't go
below 8Mb to harm HX.
So use identity mappings for xms too.
stsp added a commit that referenced this pull request Jan 20, 2023
If we use identity mappings for ext_mem, then xms can't go
below 8Mb to harm HX.
So use identity mappings for xms too.
stsp added a commit that referenced this pull request Jan 20, 2023
If we use identity mappings for ext_mem, then xms can't go
below 8Mb to harm HX.
So use identity mappings for xms too.
stsp added a commit that referenced this pull request Jan 20, 2023
If we use identity mappings for ext_mem, then xms can't go
below 8Mb to harm HX.
So use identity mappings for xms too.
stsp added a commit that referenced this pull request Jan 20, 2023
If we use identity mappings for ext_mem, then xms can't go
below 8Mb to harm HX.
So use identity mappings for xms too.
stsp added a commit that referenced this pull request Jan 20, 2023
This is needed for vcpi.
That way it is mapped to the right phys addr under kvm guest.
And it doesn't need to be shared that way as we only use the
identity mapping.

Don't auto-protect rsv_low in dpmi.
stsp added a commit that referenced this pull request Jan 20, 2023
If we use identity mappings for ext_mem, then xms can't go
below 8Mb to harm HX.
So use identity mappings for xms too.
@stsp
Copy link
Member

stsp commented Jan 20, 2023

I merged identity mapping for
ext_mem, so hope disabling DPMI
will not be needed for VCPI.

@stsp
Copy link
Member

stsp commented Feb 21, 2023

With this patch:

--- a/src/base/emu-i386/kvm.c
+++ b/src/base/emu-i386/kvm.c
@@ -1050,7 +1050,9 @@ static unsigned int kvm_run(void)
   }
 
   while (!exit_reason) {
+warn("enter %c\n", lowmem_base[(0xffff<<4)+0x10]);
     int ret = ioctl(vcpufd, KVM_RUN, NULL);
+warn("exit %c\n", lowmem_base[(0xffff<<4)+0x10]);
     int errn = errno;
 
     /* KVM should only exit for four reasons:

I eventually see in the log:

Warning: enter M
Warning: exit .

So the game corrupts HMA and freedos
is any "better" only because it doesn't have
the proper HMA manager.

@stsp
Copy link
Member

stsp commented Feb 21, 2023

CS is 0x2a8 on enter and mcbs are:

ADDR(LOW) PARAS  OWNER
0263:0000 0x0013 [CRUSADER - Environment]
0277:0000 0x0770 [CRUSADER]
09e8:0000 0x0100 [9ced - Data]

So its a crusader's CS.

@bartoldeman
Copy link
Contributor Author

ok, this could be an A20-line issue then. I think perhaps some place needs to force a20 on to make this work.

@bartoldeman
Copy link
Contributor Author

The dosbox instructions have some loadfix stuff in them, so that may be it!

@stsp
Copy link
Member

stsp commented Feb 21, 2023

OK I see the bug actually... or
a part of it. Give me a bit of time.

stsp added a commit that referenced this pull request Feb 21, 2023
Our debugger queries the HMA start at boot.
And fdpp is too permissive and just enables HMA at that point.
Check if HMA is actually enabled before querying its start.
That avoids problems.
@stsp
Copy link
Member

stsp commented Feb 21, 2023

Should now be fixed.
The problem is that our debugger
queried the HMA start, and fdpp is
too permissive and just enables HMA
if it wasn't enabled already.
Its undesirable when the program
wants to use HMA on its own as
crusader does.
So I added an extra check to the debugger.
Could also restrict fdpp, but oh well.

Note that with DOS=HIGH the problem
will re-appear. But who cares if its not
a default. :)

Implement basic VCPI support with limitations.
The limitations are:
$_dpmi = (0)
$_ems = (0)
* don't use FDPP
* use external XMS provider (HIMEM/FDXMS)

VCPI clients allocate memory from XMS only, so EMS needs to report 0 memory,
and XMS needs to map identical "physical" memory starting at 0x110000, which
would normally be taken by DPMI memory.

The page table maps LOW+HMA as usual, then a page at 0x110000 to monitor code
implementing a monitor->VCPI client jump and a VCPI client -> VM86 jump.
A page at 0x111000 contains the saved monitor GDTR/IDTR/CR3 values and
a temporary stack, with hiword(esp)=0, for the client to use. The monitor code
is much like Jemm's.

When KVM is interrupts the VCPI client through a signal, DOSEMU does its regular
things, but CANNOT modify any registers, as the client registers stay in the VM.
pic_run() will see VIF is not set, so won't modify, and the kvm.c code needs
to use KVM_INTERRUPT if pic_pending().
The only other place that has been adapted for a callback into vm86 is leavedos().

VGAEMU memory is unprotected for now, so updates aren't reliable, and VGA planar
modes don't work.

DOOM is playable but a bit slow due to frequent VGA I/O port accesses which would
normally go via instremu. Duke Nukem 3D runs but with choppy sound and incomplete
screen updates.
By dirtying all pages. Can be improved using KVM_GET_DIRTY_LOG.
Much like in dosemu2#198, use the KVM API to track which VGA pages have been written to.
Don't map the physical memory for the VGA buffer then so that all accesses
cause an MMIO KVM exit. instremu isn't read for paged memory, and probably
this will be fast enough with coalesced MMIO.
Gives much better speed in VGAEMU planar modes.
This allows command line executables to run properly with VCPI and non-zero
config.dpmi.

For DJGPP that means running cwsdpmi explicitly, and for DOS4GW,
SET DOS16M=11

Still needs $_ems=(4), a low enough value so that EMS is enabled but
doesn't let VCPI allocate any memory from it.
So that graphics work with VCPI where $_dpmi is not (0).
Otherwise report "unsupported" for int67/ah=de. This should fix CI.
Applies the page allocator to the physical memory area starting at 16M up to
16M + $_ems. To do: deal with DPMI overlaps if $_ems > 16M.
This removes all special requirements on dosemu.conf parameters for using
VCPI.
$_vcpi = (0) by default, any other value for now means "on" but in future
some value > $_ems can denote higher amounts of VCPI memory than EMS memory.
Some VCPI applications rely on page table mappings between the EMS page
frame and high memory, so we must set them up and release them on demand
as alias mappings.
@bartoldeman
Copy link
Contributor Author

Yes it works now, thanks, just with noisy error messages when internal XMS is used.
Also the DOSEMU2 window title bar now changed CRUSADER to some strange characters, but will try to narrow down when that started. It's all consistent between FDPP and fdkernel though now!

bartoldeman added a commit to bartoldeman/dosemu2 that referenced this pull request Feb 22, 2023
When config.xms_map_size < config.xms_size (it is default), the lock_EMB may
fail for blocks (partly) above 16MB. This isn't fatal and e.g. Crusader Demo
will just keep retrying with smaller sizes until it succeeds, so don't spew
out this issue to the terminal and leave it to the XMS debug log (dosemu2#1880)
When entering VCPI, we need to convert PROT_NONE maps into MMIO maps,
dirty logging is always ok.
bartoldeman added a commit to bartoldeman/dosemu2 that referenced this pull request Feb 22, 2023
XMS now allows mappings up to $_dpmi_base but the mappings need to
start at 15MB to allow DMA.

If XMS is disabled ($_xms=(0)), extmem can then go up to
$_dpmi_base, otherwise up to 15MB.

To allow mapping all XMS memory, $_xms is now limited to be
<= config.xms_map_size = dpmi_base - (1024+64)k - extmem,
otherwise Crusader Demo will complain (dosemu2#1880)

All the config checks are now done in a scrub function, to allow
clean early exit.
bartoldeman added a commit to bartoldeman/dosemu2 that referenced this pull request Feb 25, 2023
XMS now allows mappings up to $_dpmi_base (default: at 32MB), but the
mappings need to start at 15MB or lower to allow at least 1MB that can be
accessed via DMA. So now all XMS memory can be mapped in the default
configuration for 16MB of XMS, so Crusader Demo will not complain once
VCPI is in (dosemu2#1880).

If XMS is disabled ($_xms=(0)), extmem can then go up to$_dpmi_base,
otherwise up to 15MB.

All the config checks are now done in a scrub function, to allow
clean early exit.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants