OSDev.org
https://forum.osdev.org/

Enter to V86, perform BIOS Interrupt and return back to PM
https://forum.osdev.org/viewtopic.php?f=1&t=33390
Page 1 of 2

Author:  MrLolthe1st [ Mon Dec 24, 2018 10:06 am ]
Post subject:  Enter to V86, perform BIOS Interrupt and return back to PM

So, i'm have a, may be, very dumb question: how to enter to V86, perform BIOS Interrupt and return back to PM?
I'm wrote that code(In kernel) to enter to a v86:
Code:
      mov $_lo1, %ebx #Save return address to ebx
      pushf
      orl  $131072, (%esp)#Turn on VM flag
      movl   $0x0, %eax
      pushl   %eax #Segment 0   
      mov      $0x8400, %eax #Offset 0x8400
      pushl   %eax
      mov 24(%esp), %eax #Some arg to eax
      iret            #Go to V86
      _lo1:            

And now i'm trying to run that code(it executes, but on int 10h it fails)
Code:
mov dx,0
mov ss,dx
mov sp, 0x8C00
mov dx, ax
mov ax, 0x4f02
int 10h ;Crashes here
;How to retrun back?

Thanks,
Aleksandr

Author:  pvc [ Mon Dec 24, 2018 10:30 am ]
Post subject:  Re: Enter to V86, perform BIOS Interrupt and return back to

Some hits:
Try to jmp $ before int 0x10 in QEMU and see if you are really running v86 mode and if your registers are all correct using builtin monitor.
Check if your IVT is mapped to virtual address 0 and is not trashed (happens easily if you have some uncaught NULL pointer dereferences).
The way I return from v86 mode is I use int 0xFE instruction and catch it in the v86 monitor as a special interrupt.

I assume you have proper v86 monitor (the emulation layer for privileged 16 bit instructions) in place.

Author:  MrLolthe1st [ Mon Dec 24, 2018 10:40 am ]
Post subject:  Re: Enter to V86, perform BIOS Interrupt and return back to

Yes, i'm checked with bochs, i'm working in v86, and registers have right values. But, i'm never corrupt the IVT, because i'm run that code from kernel start(for easily debug).
<bochs:9> xp /1w 0x40
[bochs]:
0x0000000000000040 <bogus+ 0>: 0xc0000152
<bochs:10> s
Next at t=1597216600
(0) [0x000000008403] 0000:8403 (unk. ctxt): mov ss, bx ; 8ed3
<bochs:11> s
Next at t=1597216601
(0) [0x000000008405] 0000:8405 (unk. ctxt): mov sp, 0x8c00 ; bc008c
<bochs:12> s
Next at t=1597216602
(0) [0x000000008408] 0000:8408 (unk. ctxt): mov dx, ax ; 89c2
<bochs:13> s
Next at t=1597216603
(0) [0x00000000840a] 0000:840a (unk. ctxt): mov ax, 0x4f02 ; b8024f
<bochs:14> s
Next at t=1597216604
(0) [0x00000000840d] 0000:840d (unk. ctxt): int 0x10 ; cd10
<bochs:15> s
01597216604e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
01597216604e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)
01597216604i[CPU0 ] CPU is in v8086 mode (active)
01597216604i[CPU0 ] CS.mode = 16 bit
01597216604i[CPU0 ] SS.mode = 16 bit
01597216604i[CPU0 ] EFER = 0x00000000
01597216604i[CPU0 ] | EAX=00004f02 EBX=00000000 ECX=00000000 EDX=0000010f
...

Author:  pvc [ Mon Dec 24, 2018 10:58 am ]
Post subject:  Re: Enter to V86, perform BIOS Interrupt and return back to

Quote:
01597216604e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
01597216604e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)


Looks like your v86 int instruction emulation is not in place or is not working. You get general protection fault at int 0x10 instruction (which is correct). And after that you get double fault. And then, I assume, triple fault (which means machine reset).
The way v86 monitor works is that you are supposed to catch that first GPF and emulate that instruction.

EDIT:
Here you can see how you can do that. That's some standalone code I've sent to another user as an EXAMPLE (he didn't understand that piece I think ;) and just blindly copypasted all of it into his kernel).
EDIT2:
Code in previous link had a nasty bug.
download/file.php?id=3874

Author:  MrLolthe1st [ Mon Dec 24, 2018 11:09 am ]
Post subject:  Re: Enter to V86, perform BIOS Interrupt and return back to

What is a monitor? I've saw that: https://wiki.osdev.org/Virtual_Monitor, but understood nothing.

Author:  pvc [ Mon Dec 24, 2018 11:16 am ]
Post subject:  Re: Enter to V86, perform BIOS Interrupt and return back to

V86 Monitor is a piece of code that emulates 16 bit, otherwise privileged, instructions.
For example:
You can't execute hlt instruction in 32 bit userland protected mode. It will generate GPF. But let's say you want hlt instruction to be available in userland so you catch an exception it generates and subtitute it with, let's say, current thread suspend code. The same applies to V86 since it's just 16 bit userland code. If you want to use int instruction you have to catch GPF it generates and emulate that instruction in your kernel.

Author:  MrLolthe1st [ Mon Dec 24, 2018 11:57 am ]
Post subject:  Re: Enter to V86, perform BIOS Interrupt and return back to

But for what i'm need to emulate it? I'm want to execute BIOS interrupt. How i can catch GPFs?

Author:  quirck [ Mon Dec 24, 2018 12:17 pm ]
Post subject:  Re: Enter to V86, perform BIOS Interrupt and return back to

Emulation is needed so that the real-mode code is executed in controlled manner, so that you can decide, for example, whether you allow it to perform i/o, etc.

If you don't want to bother with v8086 monitor, maybe just returning to real mode, calling the int, and returning back to pm would be easier?

Author:  MrLolthe1st [ Mon Dec 24, 2018 12:18 pm ]
Post subject:  Re: Enter to V86, perform BIOS Interrupt and return back to

quirck, скинь ВК/телегу :)

Author:  pvc [ Mon Dec 24, 2018 12:23 pm ]
Post subject:  Re: Enter to V86, perform BIOS Interrupt and return back to

GPFs are just interrupts. Interrupts with number 13 to be exact.
About instruction emulation.
Some instructions can be considered unsafe. Some may lead to inconsistency in hardware (like in and out). These have to be emulated. Imagine that your multitasking OS is waiting for an interrupt from HDD and some other thread executes cli instruction and crashes just because. What will happen?
.
.
.
HDD driver will never receive that interrupt. And the system will freeze.
That's why some instructions need to be emulated.

Author:  MrLolthe1st [ Mon Dec 24, 2018 12:38 pm ]
Post subject:  Re: Enter to V86, perform BIOS Interrupt and return back to

So, i'm set handler for 13th interrupt, what next? What that handler must do(i'm won't use v86 for other tasks, only for change videomode)?

Author:  pvc [ Mon Dec 24, 2018 12:43 pm ]
Post subject:  Re: Enter to V86, perform BIOS Interrupt and return back to

Good. Then you need to know what instruction caused the exception. For that you need to get faulting instruction EIP. From that you can get the instruction which caused the fault.

Author:  MrLolthe1st [ Mon Dec 24, 2018 12:55 pm ]
Post subject:  Re: Enter to V86, perform BIOS Interrupt and return back to

But when fault throws, what i'm need to do, in example, on interrupt?

Author:  pvc [ Mon Dec 24, 2018 1:00 pm ]
Post subject:  Re: Enter to V86, perform BIOS Interrupt and return back to

That's really OS dependent thing.

in my example the code for instruction 'int n' was:
Code:
else if(opcode == 0xCD)
    { // int n
        byte intNo = peekb(state->CS, ++state->IP);
        if(intNo == 0xFE)
        { // special interrupt
            //memcpy(state, &vm86CPUState, sizeof(MachineState));
            size_t size = sizeof(MachineState);
            byte *dst = (byte *)state;
            byte *src = (byte *)&vm86CPUState;
            while(size--) *dst++ = *src++;
            return true;
        }
        pushw(state, state->FLAGS);
        state->EFLAGS &= ~((1 << 8) | (1 << 9) | (1 << 18));
        pushw(state, state->CS);
        pushw(state, ++state->IP);
        state->CS = peekw(0x0000, 4 * intNo + 2);
        state->IP = peekw(0x0000, 4 * intNo);
        return true;
    }


I have no idea how your interrupt stack frame looks like. That's one thing YOU have to resolve.

Author:  MrLolthe1st [ Mon Dec 24, 2018 1:17 pm ]
Post subject:  Re: Enter to V86, perform BIOS Interrupt and return back to

Ok. So, i've set GPF handler, but when i'm trying to call 'int 10h', GPF hadn't executed, qemu says:
(qemu) qemu: fatal: invalid tss type

Page 1 of 2 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/