Subversion Repositories Kolibri OS

Rev

Rev 2150 | Rev 2166 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2150 Rev 2151
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2007-2008. All rights reserved. ;;
3
;; Copyright (C) KolibriOS team 2007-2008. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
7
 
8
$Revision: 2150 $
8
$Revision: 2151 $
9
 
9
 
10
; Virtual-8086 mode manager
10
; Virtual-8086 mode manager
11
; diamond, 2007, 2008
11
; diamond, 2007, 2008
12
 
12
 
13
DEBUG_SHOW_IO = 0
13
DEBUG_SHOW_IO = 0
14
 
14
 
15
struc V86_machine
15
struc V86_machine
16
{
16
{
17
; page directory
17
; page directory
18
        .pagedir dd     ?
18
        .pagedir dd     ?
19
; translation table: V86 address -> flat linear address
19
; translation table: V86 address -> flat linear address
20
        .pages  dd      ?
20
        .pages  dd      ?
21
; mutex to protect all data from writing by multiple threads at one time
21
; mutex to protect all data from writing by multiple threads at one time
22
        .mutex  dd      ?
22
        .mutex  dd      ?
23
; i/o permission map
23
; i/o permission map
24
        .iopm   dd      ?
24
        .iopm   dd      ?
25
.size = $
25
.size = $
26
}
26
}
27
virtual at 0
27
virtual at 0
28
V86_machine V86_machine
28
V86_machine V86_machine
29
end virtual
29
end virtual
30
 
30
 
31
; Create V86 machine
31
; Create V86 machine
32
; in: nothing
32
; in: nothing
33
; out: eax = handle (pointer to struc V86_machine)
33
; out: eax = handle (pointer to struc V86_machine)
34
;      eax = NULL => failure
34
;      eax = NULL => failure
35
; destroys: ebx, ecx, edx (due to malloc)
35
; destroys: ebx, ecx, edx (due to malloc)
36
v86_create:
36
v86_create:
37
; allocate V86_machine structure
37
; allocate V86_machine structure
38
        mov     eax, V86_machine.size
38
        mov     eax, V86_machine.size
39
        call    malloc
39
        call    malloc
40
        test    eax, eax
40
        test    eax, eax
41
        jz      .fail
41
        jz      .fail
42
; initialize mutex
42
; initialize mutex
43
        and     dword [eax+V86_machine.mutex], 0
43
        and     dword [eax+V86_machine.mutex], 0
44
; allocate tables
44
; allocate tables
45
        mov     ebx, eax
45
        mov     ebx, eax
46
; We allocate 4 pages.
46
; We allocate 4 pages.
47
; First is main page directory for V86 mode.
47
; First is main page directory for V86 mode.
48
; Second page:
48
; Second page:
49
; first half (0x800 bytes) is page table for addresses 0 - 0x100000,
49
; first half (0x800 bytes) is page table for addresses 0 - 0x100000,
50
; second half is for V86-to-linear translation.
50
; second half is for V86-to-linear translation.
51
; Third and fourth are for I/O permission map.
51
; Third and fourth are for I/O permission map.
52
        push    8000h           ; blocks less than 8 pages are discontinuous
52
        push    8000h           ; blocks less than 8 pages are discontinuous
53
        call    kernel_alloc
53
        call    kernel_alloc
54
        test    eax, eax
54
        test    eax, eax
55
        jz      .fail2
55
        jz      .fail2
56
        mov     [ebx+V86_machine.pagedir], eax
56
        mov     [ebx+V86_machine.pagedir], eax
57
        push    edi eax
57
        push    edi eax
58
        mov     edi, eax
58
        mov     edi, eax
59
        add     eax, 1800h
59
        add     eax, 1800h
60
        mov     [ebx+V86_machine.pages], eax
60
        mov     [ebx+V86_machine.pages], eax
61
; initialize tables
61
; initialize tables
62
        mov     ecx, 2000h/4
62
        mov     ecx, 2000h/4
63
        xor     eax, eax
63
        xor     eax, eax
64
        rep     stosd
64
        rep     stosd
65
        mov     [ebx+V86_machine.iopm], edi
65
        mov     [ebx+V86_machine.iopm], edi
66
        dec     eax
66
        dec     eax
67
        mov     ecx, 2000h/4
67
        mov     ecx, 2000h/4
68
        rep     stosd
68
        rep     stosd
69
        pop     eax
69
        pop     eax
70
; page directory: first entry is page table...
70
; page directory: first entry is page table...
71
        mov     edi, eax
71
        mov     edi, eax
72
        add     eax, 1000h
72
        add     eax, 1000h
73
        push    eax
73
        push    eax
74
        call    get_pg_addr
74
        call    get_pg_addr
75
        or      al, PG_UW
75
        or      al, PG_UW
76
        stosd
76
        stosd
77
; ...and also copy system page tables
77
; ...and also copy system page tables
78
; thx to Serge, system is located at high addresses
78
; thx to Serge, system is located at high addresses
79
        add     edi, (OS_BASE shr 20) - 4
79
        add     edi, (OS_BASE shr 20) - 4
80
        push    esi
80
        push    esi
81
        mov     esi, (OS_BASE shr 20) + sys_pgdir
81
        mov     esi, (OS_BASE shr 20) + sys_pgdir
82
        mov     ecx, 0x80000000 shr 22
82
        mov     ecx, 0x80000000 shr 22
83
        rep     movsd
83
        rep     movsd
84
 
84
 
85
        mov     eax, [ebx+V86_machine.pagedir]   ;root dir also is
85
        mov     eax, [ebx+V86_machine.pagedir]   ;root dir also is
86
        call    get_pg_addr                      ;used as page table
86
        call    get_pg_addr                      ;used as page table
87
        or      al, PG_SW
87
        or      al, PG_SW
88
        mov [edi-4096+(page_tabs shr 20)], eax
88
        mov [edi-4096+(page_tabs shr 20)], eax
89
 
89
 
90
        pop     esi
90
        pop     esi
91
; now V86 specific: initialize known addresses in first Mb
91
; now V86 specific: initialize known addresses in first Mb
92
        pop     eax
92
        pop     eax
93
; first page - BIOS data (shared between all machines!)
93
; first page - BIOS data (shared between all machines!)
94
; physical address = 0
94
; physical address = 0
95
; linear address = OS_BASE
95
; linear address = OS_BASE
96
        mov     dword [eax], 111b
96
        mov     dword [eax], 111b
97
        mov     dword [eax+800h], OS_BASE
97
        mov     dword [eax+800h], OS_BASE
98
; page before 0xA0000 - Extended BIOS Data Area (shared between all machines!)
98
; page before 0xA0000 - Extended BIOS Data Area (shared between all machines!)
99
; physical address = 0x9C000
99
; physical address = 0x9C000
100
; linear address = 0x8009C000
100
; linear address = 0x8009C000
101
; (I have seen one computer with EBDA segment = 0x9D80,
101
; (I have seen one computer with EBDA segment = 0x9D80,
102
; all other computers use less memory)
102
; all other computers use less memory)
103
        mov     ecx, 4
103
        mov     ecx, 4
104
        mov     edx, 0x9C000
104
        mov     edx, 0x9C000
105
        push    eax
105
        push    eax
106
        lea     edi, [eax+0x9C*4]
106
        lea     edi, [eax+0x9C*4]
107
@@:
107
@@:
108
        lea     eax, [edx + OS_BASE]
108
        lea     eax, [edx + OS_BASE]
109
        mov     [edi+800h], eax
109
        mov     [edi+800h], eax
110
        lea     eax, [edx + 111b]
110
        lea     eax, [edx + 111b]
111
        stosd
111
        stosd
112
        add     edx, 0x1000
112
        add     edx, 0x1000
113
        loop    @b
113
        loop    @b
114
        pop     eax
114
        pop     eax
115
        pop     edi
115
        pop     edi
116
; addresses 0xC0000 - 0xFFFFF - BIOS code (shared between all machines!)
116
; addresses 0xC0000 - 0xFFFFF - BIOS code (shared between all machines!)
117
; physical address = 0xC0000
117
; physical address = 0xC0000
118
; linear address = 0x800C0000
118
; linear address = 0x800C0000
119
        mov     ecx, 0xC0
119
        mov     ecx, 0xC0
120
@@:
120
@@:
121
        mov     edx, ecx
121
        mov     edx, ecx
122
        shl     edx, 12
122
        shl     edx, 12
123
        push    edx
123
        push    edx
124
        or      edx, 111b
124
        or      edx, 111b
125
        mov     [eax+ecx*4], edx
125
        mov     [eax+ecx*4], edx
126
        pop     edx
126
        pop     edx
127
        add     edx, OS_BASE
127
        add     edx, OS_BASE
128
        mov     [eax+ecx*4+0x800], edx
128
        mov     [eax+ecx*4+0x800], edx
129
        inc     cl
129
        inc     cl
130
        jnz     @b
130
        jnz     @b
131
        mov     eax, ebx
131
        mov     eax, ebx
132
        ret
132
        ret
133
.fail2:
133
.fail2:
134
        mov     eax, ebx
134
        mov     eax, ebx
135
        call    free
135
        call    free
136
.fail:
136
.fail:
137
        xor     eax, eax
137
        xor     eax, eax
138
        ret
138
        ret
139
 
139
 
140
; Destroy V86 machine
140
; Destroy V86 machine
141
; in: eax = handle
141
; in: eax = handle
142
; out: nothing
142
; out: nothing
143
; destroys: eax, ebx, ecx, edx (due to free)
143
; destroys: eax, ebx, ecx, edx (due to free)
144
v86_destroy:
144
v86_destroy:
145
        push    eax
145
        push    eax
146
        stdcall kernel_free, [eax+V86_machine.pagedir]
146
        stdcall kernel_free, [eax+V86_machine.pagedir]
147
        pop     eax
147
        pop     eax
148
        jmp     free
148
        jmp     free
149
 
149
 
150
; Translate V86-address to linear address
150
; Translate V86-address to linear address
151
; in: eax=V86 address
151
; in: eax=V86 address
152
;     esi=handle
152
;     esi=handle
153
; out: eax=linear address
153
; out: eax=linear address
154
; destroys: nothing
154
; destroys: nothing
155
v86_get_lin_addr:
155
v86_get_lin_addr:
156
        push    ecx edx
156
        push    ecx edx
157
        mov     ecx, eax
157
        mov     ecx, eax
158
        mov     edx, [esi+V86_machine.pages]
158
        mov     edx, [esi+V86_machine.pages]
159
        shr     ecx, 12
159
        shr     ecx, 12
160
        and     eax, 0xFFF
160
        and     eax, 0xFFF
161
        add     eax, [edx+ecx*4]        ; atomic operation, no mutex needed
161
        add     eax, [edx+ecx*4]        ; atomic operation, no mutex needed
162
        pop     edx ecx
162
        pop     edx ecx
163
        ret
163
        ret
164
 
164
 
165
; Sets linear address for V86-page
165
; Sets linear address for V86-page
166
; in: eax=linear address (must be page-aligned)
166
; in: eax=linear address (must be page-aligned)
167
;     ecx=V86 page (NOT address!)
167
;     ecx=V86 page (NOT address!)
168
;     esi=handle
168
;     esi=handle
169
; out: nothing
169
; out: nothing
170
; destroys: nothing
170
; destroys: nothing
171
v86_set_page:
171
v86_set_page:
172
        push    eax ebx
172
        push    eax ebx
173
        mov     ebx, [esi+V86_machine.pagedir]
173
        mov     ebx, [esi+V86_machine.pagedir]
174
        mov     [ebx+ecx*4+0x1800], eax
174
        mov     [ebx+ecx*4+0x1800], eax
175
        call    get_pg_addr
175
        call    get_pg_addr
176
        or      al, 111b
176
        or      al, 111b
177
        mov     [ebx+ecx*4+0x1000], eax
177
        mov     [ebx+ecx*4+0x1000], eax
178
        pop     ebx eax
178
        pop     ebx eax
179
        ret
179
        ret
180
 
180
 
181
; Allocate memory in V86 machine
181
; Allocate memory in V86 machine
182
; in: eax=size (in bytes)
182
; in: eax=size (in bytes)
183
;     esi=handle
183
;     esi=handle
184
; out: eax=V86 address, para-aligned (0x10 multiple)
184
; out: eax=V86 address, para-aligned (0x10 multiple)
185
; destroys: nothing
185
; destroys: nothing
186
; ­¥¤®¯¨á ­ !!!
186
; ­¥¤®¯¨á ­ !!!
187
;v86_alloc:
187
;v86_alloc:
188
;        push    ebx ecx edx edi
188
;        push    ebx ecx edx edi
189
;        lea     ebx, [esi+V86_machine.mutex]
189
;        lea     ebx, [esi+V86_machine.mutex]
190
;        call    wait_mutex
190
;        call    wait_mutex
191
;        add     eax, 0x1F
191
;        add     eax, 0x1F
192
;        shr     eax, 4
192
;        shr     eax, 4
193
;        mov     ebx, 0x1000  ; start with address 0x1000 (second page)
193
;        mov     ebx, 0x1000  ; start with address 0x1000 (second page)
194
;        mov     edi, [esi+V86_machine.tables]
194
;        mov     edi, [esi+V86_machine.tables]
195
;.l:
195
;.l:
196
;        mov     ecx, ebx
196
;        mov     ecx, ebx
197
;        shr     ecx, 12
197
;        shr     ecx, 12
198
;        mov     edx, [edi+0x1000+ecx*4] ; get linear address
198
;        mov     edx, [edi+0x1000+ecx*4] ; get linear address
199
;        test    edx, edx                ; page allocated?
199
;        test    edx, edx                ; page allocated?
200
;        jz      .unalloc
200
;        jz      .unalloc
201
;        mov     ecx, ebx
201
;        mov     ecx, ebx
202
;        and     ecx, 0xFFF
202
;        and     ecx, 0xFFF
203
;        add     edx, ecx
203
;        add     edx, ecx
204
;        cmp     dword [edx], 0          ; free block?
204
;        cmp     dword [edx], 0          ; free block?
205
;        jnz     .n
205
;        jnz     .n
206
;        cmp     dword [edx+4],
206
;        cmp     dword [edx+4],
207
;        and     [esi+V86_machine.mutex], 0
207
;        and     [esi+V86_machine.mutex], 0
208
;        pop     edi edx ecx ebx
208
;        pop     edi edx ecx ebx
209
;        ret
209
;        ret
210
 
210
 
211
uglobal
211
uglobal
212
sys_v86_machine dd      ?
212
sys_v86_machine dd      ?
213
endg
213
endg
214
 
214
 
215
; Called from kernel.asm at first stages of loading
215
; Called from kernel.asm at first stages of loading
216
; Initialize system V86 machine (used to simulate BIOS int 13h)
216
; Initialize system V86 machine (used to simulate BIOS int 13h)
217
init_sys_v86:
217
init_sys_v86:
218
        call    v86_create
218
        call    v86_create
219
        mov     [sys_v86_machine], eax
219
        mov     [sys_v86_machine], eax
220
        test    eax, eax
220
        test    eax, eax
221
        jz      .ret
221
        jz      .ret
222
        mov     byte [OS_BASE + 0x500], 0xCD
222
        mov     byte [OS_BASE + 0x500], 0xCD
223
        mov     byte [OS_BASE + 0x501], 0x13
223
        mov     byte [OS_BASE + 0x501], 0x13
224
        mov     byte [OS_BASE + 0x502], 0xF4
224
        mov     byte [OS_BASE + 0x502], 0xF4
225
        mov     byte [OS_BASE + 0x503], 0xCD
225
        mov     byte [OS_BASE + 0x503], 0xCD
226
        mov     byte [OS_BASE + 0x504], 0x10
226
        mov     byte [OS_BASE + 0x504], 0x10
227
        mov     byte [OS_BASE + 0x505], 0xF4
227
        mov     byte [OS_BASE + 0x505], 0xF4
228
        mov     esi, eax
228
        mov     esi, eax
229
        mov     ebx, [eax+V86_machine.pagedir]
229
        mov     ebx, [eax+V86_machine.pagedir]
230
; one page for stack, two pages for results (0x2000 bytes = 16 sectors)
230
; one page for stack, two pages for results (0x2000 bytes = 16 sectors)
231
        mov     dword [ebx+0x99*4+0x1000], 0x99000 or 111b
231
        mov     dword [ebx+0x99*4+0x1000], 0x99000 or 111b
232
        mov     dword [ebx+0x99*4+0x1800], OS_BASE + 0x99000
232
        mov     dword [ebx+0x99*4+0x1800], OS_BASE + 0x99000
233
        mov     dword [ebx+0x9A*4+0x1000], 0x9A000 or 111b
233
        mov     dword [ebx+0x9A*4+0x1000], 0x9A000 or 111b
234
        mov     dword [ebx+0x9A*4+0x1800], OS_BASE + 0x9A000
234
        mov     dword [ebx+0x9A*4+0x1800], OS_BASE + 0x9A000
235
        mov     dword [ebx+0x9B*4+0x1000], 0x9B000 or 111b
235
        mov     dword [ebx+0x9B*4+0x1000], 0x9B000 or 111b
236
        mov     dword [ebx+0x9B*4+0x1800], OS_BASE + 0x9B000
236
        mov     dword [ebx+0x9B*4+0x1800], OS_BASE + 0x9B000
237
if ~DEBUG_SHOW_IO
237
if ~DEBUG_SHOW_IO
238
; allow access to all ports
238
; allow access to all ports
239
        mov     ecx, [esi+V86_machine.iopm]
239
        mov     ecx, [esi+V86_machine.iopm]
240
        xor     eax, eax
240
        xor     eax, eax
241
        mov     edi, ecx
241
        mov     edi, ecx
242
        mov     ecx, 10000h/8/4
242
        mov     ecx, 10000h/8/4
243
        rep     stosd
243
        rep     stosd
244
end if
244
end if
245
.ret:
245
.ret:
246
        ret
246
        ret
247
 
247
 
248
struc v86_regs
248
struc v86_regs
249
{
249
{
250
; don't change the order, it is important
250
; don't change the order, it is important
251
        .edi    dd      ?
251
        .edi    dd      ?
252
        .esi    dd      ?
252
        .esi    dd      ?
253
        .ebp    dd      ?
253
        .ebp    dd      ?
254
                dd      ?       ; ignored
254
                dd      ?       ; ignored
255
        .ebx    dd      ?
255
        .ebx    dd      ?
256
        .edx    dd      ?
256
        .edx    dd      ?
257
        .ecx    dd      ?
257
        .ecx    dd      ?
258
        .eax    dd      ?
258
        .eax    dd      ?
259
        .eip    dd      ?
259
        .eip    dd      ?
260
        .cs     dd      ?
260
        .cs     dd      ?
261
        .eflags dd      ?       ; VM flag must be set!
261
        .eflags dd      ?       ; VM flag must be set!
262
        .esp    dd      ?
262
        .esp    dd      ?
263
        .ss     dd      ?
263
        .ss     dd      ?
264
        .es     dd      ?
264
        .es     dd      ?
265
        .ds     dd      ?
265
        .ds     dd      ?
266
        .fs     dd      ?
266
        .fs     dd      ?
267
        .gs     dd      ?
267
        .gs     dd      ?
268
.size = $
268
.size = $
269
}
269
}
270
virtual at 0
270
virtual at 0
271
v86_regs v86_regs
271
v86_regs v86_regs
272
end virtual
272
end virtual
273
 
273
 
274
; Run V86 machine
274
; Run V86 machine
275
; in: ebx -> registers for V86 (two structures: in and out)
275
; in: ebx -> registers for V86 (two structures: in and out)
276
;     esi = handle
276
;     esi = handle
277
;     ecx = expected end address (CS:IP)
277
;     ecx = expected end address (CS:IP)
278
;     edx = IRQ to hook or -1 if not required
278
;     edx = IRQ to hook or -1 if not required
279
; out: structure pointed to by ebx is filled with new values
279
; out: structure pointed to by ebx is filled with new values
280
;     eax = 1 - exception has occured, cl contains code
280
;     eax = 1 - exception has occured, cl contains code
281
;     eax = 2 - access to disabled i/o port, ecx contains port address
281
;     eax = 2 - access to disabled i/o port, ecx contains port address
282
;     eax = 3 - IRQ is already hooked by another VM
282
;     eax = 3 - IRQ is already hooked by another VM
283
; destroys: nothing
283
; destroys: nothing
284
v86_start:
284
v86_start:
285
        pushad
285
        pushad
286
 
286
 
287
        cli
287
        cli
288
 
288
 
289
        mov     ecx, [CURRENT_TASK]
289
        mov     ecx, [CURRENT_TASK]
290
        shl     ecx, 8
290
        shl     ecx, 8
291
        add     ecx, SLOT_BASE
291
        add     ecx, SLOT_BASE
292
 
292
 
293
        mov     eax, [esi+V86_machine.iopm]
293
        mov     eax, [esi+V86_machine.iopm]
294
        call    get_pg_addr
294
        call    get_pg_addr
295
        inc     eax
295
        inc     eax
296
        push    dword [ecx+APPDATA.io_map]
296
        push    dword [ecx+APPDATA.io_map]
297
        push    dword [ecx+APPDATA.io_map+4]
297
        push    dword [ecx+APPDATA.io_map+4]
298
        mov     dword [ecx+APPDATA.io_map], eax
298
        mov     dword [ecx+APPDATA.io_map], eax
299
        mov     dword [page_tabs + (tss._io_map_0 shr 10)], eax
299
        mov     dword [page_tabs + (tss._io_map_0 shr 10)], eax
300
        add     eax, 0x1000
300
        add     eax, 0x1000
301
        mov     dword [ecx+APPDATA.io_map+4], eax
301
        mov     dword [ecx+APPDATA.io_map+4], eax
302
        mov     dword [page_tabs + (tss._io_map_1 shr 10)], eax
302
        mov     dword [page_tabs + (tss._io_map_1 shr 10)], eax
303
 
303
 
304
        push    [ecx+APPDATA.dir_table]
304
        push    [ecx+APPDATA.dir_table]
305
        push    [ecx+APPDATA.saved_esp0]
305
        push    [ecx+APPDATA.saved_esp0]
306
        mov     [ecx+APPDATA.saved_esp0], esp
306
        mov     [ecx+APPDATA.saved_esp0], esp
307
        mov     [tss._esp0], esp
307
        mov     [tss._esp0], esp
308
 
308
 
309
        mov     eax, [esi+V86_machine.pagedir]
309
        mov     eax, [esi+V86_machine.pagedir]
310
        call    get_pg_addr
310
        call    get_pg_addr
311
        mov     [ecx+APPDATA.dir_table], eax
311
        mov     [ecx+APPDATA.dir_table], eax
312
        mov     cr3, eax
312
        mov     cr3, eax
313
 
313
 
314
;        mov     [irq_tab+5*4], my05
314
;        mov     [irq_tab+5*4], my05
315
 
315
 
316
; We do not enable interrupts, because V86 IRQ redirector assumes that
316
; We do not enable interrupts, because V86 IRQ redirector assumes that
317
; machine is running
317
; machine is running
318
; They will be enabled by IRET.
318
; They will be enabled by IRET.
319
;        sti
319
;        sti
320
 
320
 
321
        mov     eax, esi
321
        mov     eax, esi
322
        sub     esp, v86_regs.size
322
        sub     esp, v86_regs.size
323
        mov     esi, ebx
323
        mov     esi, ebx
324
        mov     edi, esp
324
        mov     edi, esp
325
        mov     ecx, v86_regs.size/4
325
        mov     ecx, v86_regs.size/4
326
        rep     movsd
326
        rep     movsd
327
 
327
 
328
        cmp     edx, -1
328
        cmp     edx, -1
329
        jz      .noirqhook
329
        jz      .noirqhook
330
uglobal
330
uglobal
331
v86_irqhooks    rd      IRQ_RESERVED * 2
331
v86_irqhooks    rd      IRQ_RESERVED * 2
332
endg
332
endg
333
        cmp     [v86_irqhooks+edx*8], 0
333
        cmp     [v86_irqhooks+edx*8], 0
334
        jz      @f
334
        jz      @f
335
        cmp     [v86_irqhooks+edx*8], eax
335
        cmp     [v86_irqhooks+edx*8], eax
336
        jz      @f
336
        jz      @f
337
        mov     esi, v86_irqerr
337
        mov     esi, v86_irqerr
338
        call    sys_msg_board_str
338
        call    sys_msg_board_str
339
        inc     [v86_irqhooks+edx*8+4]
339
        inc     [v86_irqhooks+edx*8+4]
340
        mov     eax, 3
340
        mov     eax, 3
341
        jmp     v86_exc_c.exit
341
        jmp     v86_exc_c.exit
342
@@:
342
@@:
343
        mov     [v86_irqhooks+edx*8], eax
343
        mov     [v86_irqhooks+edx*8], eax
344
        inc     [v86_irqhooks+edx*8+4]
344
        inc     [v86_irqhooks+edx*8+4]
345
.noirqhook:
345
.noirqhook:
346
 
346
 
347
        popad
347
        popad
348
        iretd
348
        iretd
349
 
349
 
350
; It is only possible to leave virtual-8086 mode by faulting to
350
; It is only possible to leave virtual-8086 mode by faulting to
351
; a protected-mode interrupt handler (typically the general-protection
351
; a protected-mode interrupt handler (typically the general-protection
352
; exception handler, which in turn calls the virtual 8086-mode monitor).
352
; exception handler, which in turn calls the virtual 8086-mode monitor).
353
 
353
 
354
iglobal
354
iglobal
355
  v86_exc_str1  db      'V86 : unexpected exception ',0
355
  v86_exc_str1  db      'V86 : unexpected exception ',0
356
  v86_exc_str2  db      ' at ',0
356
  v86_exc_str2  db      ' at ',0
357
  v86_exc_str3  db      ':',0
357
  v86_exc_str3  db      ':',0
358
  v86_exc_str4  db      13,10,'V86 : faulted code:',0
358
  v86_exc_str4  db      13,10,'V86 : faulted code:',0
359
  v86_exc_str5  db      ' (unavailable)',0
359
  v86_exc_str5  db      ' (unavailable)',0
360
  v86_newline   db      13,10,0
360
  v86_newline   db      13,10,0
361
  v86_io_str1   db      'V86 : access to disabled i/o port ',0
361
  v86_io_str1   db      'V86 : access to disabled i/o port ',0
362
  v86_io_byte   db      ' (byte)',13,10,0
362
  v86_io_byte   db      ' (byte)',13,10,0
363
  v86_io_word   db      ' (word)',13,10,0
363
  v86_io_word   db      ' (word)',13,10,0
364
  v86_io_dword  db      ' (dword)',13,10,0
364
  v86_io_dword  db      ' (dword)',13,10,0
365
  v86_irqerr    db      'V86 : IRQ already hooked',13,10,0
365
  v86_irqerr    db      'V86 : IRQ already hooked',13,10,0
366
endg
366
endg
367
 
367
 
368
v86_exc_c:
368
v86_exc_c:
369
; Did we all that we have wanted to do?
369
; Did we all that we have wanted to do?
370
        cmp     bl,1
370
        cmp     bl,1
371
        jne     @f
371
        jne     @f
372
        xor     eax, eax
372
        xor     eax, eax
373
        mov     dr6, eax
373
        mov     dr6, eax
374
  @@:   mov     eax, [esp+v86_regs.size+10h+18h]
374
  @@:   mov     eax, [esp+v86_regs.size+10h+18h]
375
        cmp     word [esp+v86_regs.eip], ax
375
        cmp     word [esp+v86_regs.eip], ax
376
        jnz     @f
376
        jnz     @f
377
        shr     eax, 16
377
        shr     eax, 16
378
        cmp     word [esp+v86_regs.cs], ax
378
        cmp     word [esp+v86_regs.cs], ax
379
        jz      .done
379
        jz      .done
380
@@:
380
@@:
381
; Various system events, which must be handled, result in #GP
381
; Various system events, which must be handled, result in #GP
382
        cmp     bl, 13
382
        cmp     bl, 13
383
        jnz     .nogp
383
        jnz     .nogp
384
; If faulted EIP exceeds 0xFFFF, we have #GP and it is an error
384
; If faulted EIP exceeds 0xFFFF, we have #GP and it is an error
385
        cmp     word [esp+v86_regs.eip+2], 0
385
        cmp     word [esp+v86_regs.eip+2], 0
386
        jnz     .nogp
386
        jnz     .nogp
387
; Otherwise we can safely access byte at CS:IP
387
; Otherwise we can safely access byte at CS:IP
388
; (because it is #GP, not #PF handler)
388
; (because it is #GP, not #PF handler)
389
; …᫨ ¡ë ¬ë ¬®£«¨ áå«®¯®â âì ¨áª«î祭¨¥ ⮫쪮 ¨§-§  ç⥭¨ï ¡ ©â®¢ ª®¤ ,
389
; …᫨ ¡ë ¬ë ¬®£«¨ áå«®¯®â âì ¨áª«î祭¨¥ ⮫쪮 ¨§-§  ç⥭¨ï ¡ ©â®¢ ª®¤ ,
390
; ¬ë ¡ë ¥£® 㦥 áå«®¯®â «¨ ¨ íâ® ¡ë«® ¡ë ­¥ #GP
390
; ¬ë ¡ë ¥£® 㦥 áå«®¯®â «¨ ¨ íâ® ¡ë«® ¡ë ­¥ #GP
391
        movzx   esi, word [esp+v86_regs.cs]
391
        movzx   esi, word [esp+v86_regs.cs]
392
        shl     esi, 4
392
        shl     esi, 4
393
        add     esi, [esp+v86_regs.eip]
393
        add     esi, [esp+v86_regs.eip]
394
        lodsb
394
        lodsb
395
        cmp     al, 0xCD        ; int xx command = CD xx
395
        cmp     al, 0xCD        ; int xx command = CD xx
396
        jz      .handle_int
396
        jz      .handle_int
397
        cmp     al, 0xCF
397
        cmp     al, 0xCF
398
        jz      .handle_iret
398
        jz      .handle_iret
399
        cmp     al, 0xF3
399
        cmp     al, 0xF3
400
        jz      .handle_rep
400
        jz      .handle_rep
401
        cmp     al, 0xEC
401
        cmp     al, 0xEC
402
        jz      .handle_in
402
        jz      .handle_in
403
        cmp     al, 0xED
403
        cmp     al, 0xED
404
        jz      .handle_in_word
404
        jz      .handle_in_word
405
        cmp     al, 0xEE
405
        cmp     al, 0xEE
406
        jz      .handle_out
406
        jz      .handle_out
407
        cmp     al, 0xEF
407
        cmp     al, 0xEF
408
        jz      .handle_out_word
408
        jz      .handle_out_word
409
        cmp     al, 0xE4
409
        cmp     al, 0xE4
410
        jz      .handle_in_imm
410
        jz      .handle_in_imm
411
        cmp     al, 0xE6
411
        cmp     al, 0xE6
412
        jz      .handle_out_imm
412
        jz      .handle_out_imm
413
        cmp     al, 0x9C
413
        cmp     al, 0x9C
414
        jz      .handle_pushf
414
        jz      .handle_pushf
415
        cmp     al, 0x9D
415
        cmp     al, 0x9D
416
        jz      .handle_popf
416
        jz      .handle_popf
417
        cmp     al, 0xFA
417
        cmp     al, 0xFA
418
        jz      .handle_cli
418
        jz      .handle_cli
419
        cmp     al, 0xFB
419
        cmp     al, 0xFB
420
        jz      .handle_sti
420
        jz      .handle_sti
421
        cmp     al, 0x66
421
        cmp     al, 0x66
422
        jz      .handle_66
422
        jz      .handle_66
423
        jmp     .nogp
423
        jmp     .nogp
424
.handle_int:
424
.handle_int:
425
        cmp     word [esp+v86_regs.eip], 0xFFFF
425
        cmp     word [esp+v86_regs.eip], 0xFFFF
426
        jae     .nogp
426
        jae     .nogp
427
        xor     eax, eax
427
        xor     eax, eax
428
        lodsb
428
        lodsb
429
;        call    sys_msg_board_byte
429
;        call    sys_msg_board_byte
430
; simulate INT command
430
; simulate INT command
431
; N.B. It is possible that some checks need to be corrected,
431
; N.B. It is possible that some checks need to be corrected,
432
;      but at least in case of normal execution the code works.
432
;      but at least in case of normal execution the code works.
433
.simulate_int:
433
.simulate_int:
434
        cmp     word [esp+v86_regs.esp], 6
434
        cmp     word [esp+v86_regs.esp], 6
435
        jae     @f
435
        jae     @f
436
        mov     bl, 12          ; #SS exception
436
        mov     bl, 12          ; #SS exception
437
        jmp     .nogp
437
        jmp     .nogp
438
@@:
438
@@:
439
        movzx   edx, word [esp+v86_regs.ss]
439
        movzx   edx, word [esp+v86_regs.ss]
440
        shl     edx, 4
440
        shl     edx, 4
441
        push    eax
441
        push    eax
442
        movzx   eax, word [esp+4+v86_regs.esp]
442
        movzx   eax, word [esp+4+v86_regs.esp]
443
        sub     eax, 6
443
        sub     eax, 6
444
        add     edx, eax
444
        add     edx, eax
445
        mov     eax, edx
445
        mov     eax, edx
446
        mov     esi, [esp+4+v86_regs.size+10h+4]
446
        mov     esi, [esp+4+v86_regs.size+10h+4]
447
        call    v86_get_lin_addr
447
        call    v86_get_lin_addr
448
        cmp     eax, 0x1000
448
        cmp     eax, 0x1000
449
        jae     @f
449
        jae     @f
450
        mov     bl, 14          ; #PF exception
450
        mov     bl, 14          ; #PF exception
451
        jmp     .nogp
451
        jmp     .nogp
452
@@:
452
@@:
453
        lea     eax, [edx+5]
453
        lea     eax, [edx+5]
454
        call    v86_get_lin_addr
454
        call    v86_get_lin_addr
455
        cmp     eax, 0x1000
455
        cmp     eax, 0x1000
456
        jae     @f
456
        jae     @f
457
        mov     bl, 14          ; #PF exception
457
        mov     bl, 14          ; #PF exception
458
        jmp     .nogp
458
        jmp     .nogp
459
@@:
459
@@:
460
        sub     word [esp+4+v86_regs.esp], 6
460
        sub     word [esp+4+v86_regs.esp], 6
461
        mov     eax, [esp+4+v86_regs.eip]
461
        mov     eax, [esp+4+v86_regs.eip]
462
        cmp     byte [esp+1], 0
462
        cmp     byte [esp+1], 0
463
        jnz     @f
463
        jnz     @f
464
        inc     eax
464
        inc     eax
465
        inc     eax
465
        inc     eax
466
@@:
466
@@:
467
        mov     word [edx], ax
467
        mov     word [edx], ax
468
        mov     eax, [esp+4+v86_regs.cs]
468
        mov     eax, [esp+4+v86_regs.cs]
469
        mov     word [edx+2], ax
469
        mov     word [edx+2], ax
470
        mov     eax, [esp+4+v86_regs.eflags]
470
        mov     eax, [esp+4+v86_regs.eflags]
471
        mov     word [edx+4], ax
471
        mov     word [edx+4], ax
472
        pop     eax
472
        pop     eax
473
        mov     ah, 0
473
        mov     ah, 0
474
        mov     cx, [eax*4]
474
        mov     cx, [eax*4]
475
        mov     word [esp+v86_regs.eip], cx
475
        mov     word [esp+v86_regs.eip], cx
476
        mov     cx, [eax*4+2]
476
        mov     cx, [eax*4+2]
477
        mov     word [esp+v86_regs.cs], cx
477
        mov     word [esp+v86_regs.cs], cx
478
; note that interrupts will be disabled globally at IRET
478
; note that interrupts will be disabled globally at IRET
479
        and     byte [esp+v86_regs.eflags+1], not 3 ; clear IF and TF flags
479
        and     byte [esp+v86_regs.eflags+1], not 3 ; clear IF and TF flags
480
; continue V86 execution
480
; continue V86 execution
481
        popad
481
        popad
482
        iretd
482
        iretd
483
.handle_iret:
483
.handle_iret:
484
        cmp     word [esp+v86_regs.esp], 0x10000 - 6
484
        cmp     word [esp+v86_regs.esp], 0x10000 - 6
485
        jbe     @f
485
        jbe     @f
486
        mov     bl, 12
486
        mov     bl, 12
487
        jmp     .nogp
487
        jmp     .nogp
488
@@:
488
@@:
489
        movzx   edx, word [esp+v86_regs.ss]
489
        movzx   edx, word [esp+v86_regs.ss]
490
        shl     edx, 4
490
        shl     edx, 4
491
        movzx   eax, word [esp+v86_regs.esp]
491
        movzx   eax, word [esp+v86_regs.esp]
492
        add     edx, eax
492
        add     edx, eax
493
        mov     eax, edx
493
        mov     eax, edx
494
        mov     esi, [esp+v86_regs.size+10h+4]
494
        mov     esi, [esp+v86_regs.size+10h+4]
495
        call    v86_get_lin_addr
495
        call    v86_get_lin_addr
496
        cmp     eax, 0x1000
496
        cmp     eax, 0x1000
497
        jae     @f
497
        jae     @f
498
        mov     bl, 14
498
        mov     bl, 14
499
        jmp     .nogp
499
        jmp     .nogp
500
@@:
500
@@:
501
        lea     eax, [edx+5]
501
        lea     eax, [edx+5]
502
        call    v86_get_lin_addr
502
        call    v86_get_lin_addr
503
        cmp     eax, 0x1000
503
        cmp     eax, 0x1000
504
        jae     @f
504
        jae     @f
505
        mov     bl, 14
505
        mov     bl, 14
506
        jmp     .nogp
506
        jmp     .nogp
507
@@:
507
@@:
508
        mov     ax, [edx]
508
        mov     ax, [edx]
509
        mov     word [esp+v86_regs.eip], ax
509
        mov     word [esp+v86_regs.eip], ax
510
        mov     ax, [edx+2]
510
        mov     ax, [edx+2]
511
        mov     word [esp+v86_regs.cs], ax
511
        mov     word [esp+v86_regs.cs], ax
512
        mov     ax, [edx+4]
512
        mov     ax, [edx+4]
513
        mov     word [esp+v86_regs.eflags], ax
513
        mov     word [esp+v86_regs.eflags], ax
514
        add     word [esp+v86_regs.esp], 6
514
        add     word [esp+v86_regs.esp], 6
515
        popad
515
        popad
516
        iretd
516
        iretd
517
.handle_pushf:
517
.handle_pushf:
518
        cmp     word [esp+v86_regs.esp], 1
518
        cmp     word [esp+v86_regs.esp], 1
519
        jnz     @f
519
        jnz     @f
520
        mov     bl, 12
520
        mov     bl, 12
521
        jmp     .nogp
521
        jmp     .nogp
522
@@:
522
@@:
523
        movzx   edx, word [esp+v86_regs.ss]
523
        movzx   edx, word [esp+v86_regs.ss]
524
        shl     edx, 4
524
        shl     edx, 4
525
        mov     eax, [esp+v86_regs.esp]
525
        mov     eax, [esp+v86_regs.esp]
526
        sub     eax, 2
526
        sub     eax, 2
527
        movzx   eax, ax
527
        movzx   eax, ax
528
        add     edx, eax
528
        add     edx, eax
529
        mov     eax, edx
529
        mov     eax, edx
530
        mov     esi, [esp+v86_regs.size+10h+4]
530
        mov     esi, [esp+v86_regs.size+10h+4]
531
        call    v86_get_lin_addr
531
        call    v86_get_lin_addr
532
        cmp     eax, 0x1000
532
        cmp     eax, 0x1000
533
        jae     @f
533
        jae     @f
534
        mov     bl, 14          ; #PF exception
534
        mov     bl, 14          ; #PF exception
535
        jmp     .nogp
535
        jmp     .nogp
536
@@:
536
@@:
537
        lea     eax, [edx+1]
537
        lea     eax, [edx+1]
538
        call    v86_get_lin_addr
538
        call    v86_get_lin_addr
539
        cmp     eax, 0x1000
539
        cmp     eax, 0x1000
540
        jae     @f
540
        jae     @f
541
        mov     bl, 14
541
        mov     bl, 14
542
        jmp     .nogp
542
        jmp     .nogp
543
@@:
543
@@:
544
        sub     word [esp+v86_regs.esp], 2
544
        sub     word [esp+v86_regs.esp], 2
545
        mov     eax, [esp+v86_regs.eflags]
545
        mov     eax, [esp+v86_regs.eflags]
546
        mov     [edx], ax
546
        mov     [edx], ax
547
        inc     word [esp+v86_regs.eip]
547
        inc     word [esp+v86_regs.eip]
548
        popad
548
        popad
549
        iretd
549
        iretd
550
.handle_pushfd:
550
.handle_pushfd:
551
        cmp     word [esp+v86_regs.esp], 4
551
        cmp     word [esp+v86_regs.esp], 4
552
        jae     @f
552
        jae     @f
553
        mov     bl, 12          ; #SS exception
553
        mov     bl, 12          ; #SS exception
554
        jmp     .nogp
554
        jmp     .nogp
555
@@:
555
@@:
556
        movzx   edx, word [esp+v86_regs.ss]
556
        movzx   edx, word [esp+v86_regs.ss]
557
        shl     edx, 4
557
        shl     edx, 4
558
        movzx   eax, word [esp+v86_regs.esp]
558
        movzx   eax, word [esp+v86_regs.esp]
559
        sub     eax, 4
559
        sub     eax, 4
560
        add     edx, eax
560
        add     edx, eax
561
        mov     eax, edx
561
        mov     eax, edx
562
        mov     esi, [esp+v86_regs.size+10h+4]
562
        mov     esi, [esp+v86_regs.size+10h+4]
563
        call    v86_get_lin_addr
563
        call    v86_get_lin_addr
564
        cmp     eax, 0x1000
564
        cmp     eax, 0x1000
565
        jae     @f
565
        jae     @f
566
        mov     bl, 14          ; #PF exception
566
        mov     bl, 14          ; #PF exception
567
        jmp     .nogp
567
        jmp     .nogp
568
@@:
568
@@:
569
        lea     eax, [edx+3]
569
        lea     eax, [edx+3]
570
        call    v86_get_lin_addr
570
        call    v86_get_lin_addr
571
        cmp     eax, 0x1000
571
        cmp     eax, 0x1000
572
        jae     @f
572
        jae     @f
573
        mov     bl, 14          ; #PF exception
573
        mov     bl, 14          ; #PF exception
574
        jmp     .nogp
574
        jmp     .nogp
575
@@:
575
@@:
576
        sub     word [esp+v86_regs.esp], 4
576
        sub     word [esp+v86_regs.esp], 4
577
        movzx   eax, word [esp+v86_regs.eflags]
577
        movzx   eax, word [esp+v86_regs.eflags]
578
        mov     [edx], eax
578
        mov     [edx], eax
579
        add     word [esp+v86_regs.eip], 2
579
        add     word [esp+v86_regs.eip], 2
580
        popad
580
        popad
581
        iretd
581
        iretd
582
.handle_popf:
582
.handle_popf:
583
        cmp     word [esp+v86_regs.esp], 0xFFFF
583
        cmp     word [esp+v86_regs.esp], 0xFFFF
584
        jnz     @f
584
        jnz     @f
585
        mov     bl, 12
585
        mov     bl, 12
586
        jmp     .nogp
586
        jmp     .nogp
587
@@:
587
@@:
588
        movzx   edx, word [esp+v86_regs.ss]
588
        movzx   edx, word [esp+v86_regs.ss]
589
        shl     edx, 4
589
        shl     edx, 4
590
        movzx   eax, word [esp+v86_regs.esp]
590
        movzx   eax, word [esp+v86_regs.esp]
591
        add     edx, eax
591
        add     edx, eax
592
        mov     eax, edx
592
        mov     eax, edx
593
        mov     esi, [esp+v86_regs.size+10h+4]
593
        mov     esi, [esp+v86_regs.size+10h+4]
594
        call    v86_get_lin_addr
594
        call    v86_get_lin_addr
595
        cmp     eax, 0x1000
595
        cmp     eax, 0x1000
596
        jae     @f
596
        jae     @f
597
        mov     bl, 14          ; #PF exception
597
        mov     bl, 14          ; #PF exception
598
        jmp     .nogp
598
        jmp     .nogp
599
@@:
599
@@:
600
        lea     eax, [edx+1]
600
        lea     eax, [edx+1]
601
        call    v86_get_lin_addr
601
        call    v86_get_lin_addr
602
        cmp     eax, 0x1000
602
        cmp     eax, 0x1000
603
        jae     @f
603
        jae     @f
604
        mov     bl, 14
604
        mov     bl, 14
605
        jmp     .nogp
605
        jmp     .nogp
606
@@:
606
@@:
607
        mov     ax, [edx]
607
        mov     ax, [edx]
608
        mov     word [esp+v86_regs.eflags], ax
608
        mov     word [esp+v86_regs.eflags], ax
609
        add     word [esp+v86_regs.esp], 2
609
        add     word [esp+v86_regs.esp], 2
610
        inc     word [esp+v86_regs.eip]
610
        inc     word [esp+v86_regs.eip]
611
        popad
611
        popad
612
        iretd
612
        iretd
613
.handle_popfd:
613
.handle_popfd:
614
        cmp     word [esp+v86_regs.esp], 0x10000 - 4
614
        cmp     word [esp+v86_regs.esp], 0x10000 - 4
615
        jbe     @f
615
        jbe     @f
616
        mov     bl, 12
616
        mov     bl, 12
617
        jmp     .nogp
617
        jmp     .nogp
618
@@:
618
@@:
619
        movzx   edx, word [esp+v86_regs.ss]
619
        movzx   edx, word [esp+v86_regs.ss]
620
        shl     edx, 4
620
        shl     edx, 4
621
        movzx   eax, word [esp+v86_regs.esp]
621
        movzx   eax, word [esp+v86_regs.esp]
622
        add     edx, eax
622
        add     edx, eax
623
        mov     eax, edx
623
        mov     eax, edx
624
        mov     esi, [esp+v86_regs.size+10h+4]
624
        mov     esi, [esp+v86_regs.size+10h+4]
625
        call    v86_get_lin_addr
625
        call    v86_get_lin_addr
626
        cmp     eax, 0x1000
626
        cmp     eax, 0x1000
627
        jae     @f
627
        jae     @f
628
        mov     bl, 14
628
        mov     bl, 14
629
        jmp     .nogp
629
        jmp     .nogp
630
@@:
630
@@:
631
        lea     eax, [edx+3]
631
        lea     eax, [edx+3]
632
        call    v86_get_lin_addr
632
        call    v86_get_lin_addr
633
        cmp     eax, 0x1000
633
        cmp     eax, 0x1000
634
        jae     @f
634
        jae     @f
635
        mov     bl, 14
635
        mov     bl, 14
636
        jmp     .nogp
636
        jmp     .nogp
637
@@:
637
@@:
638
        mov     eax, [edx]
638
        mov     eax, [edx]
639
        mov     word [esp+v86_regs.eflags], ax
639
        mov     word [esp+v86_regs.eflags], ax
640
        add     word [esp+v86_regs.esp], 4
640
        add     word [esp+v86_regs.esp], 4
641
        add     word [esp+v86_regs.eip], 2
641
        add     word [esp+v86_regs.eip], 2
642
        popad
642
        popad
643
        iretd
643
        iretd
644
.handle_cli:
644
.handle_cli:
645
        and     byte [esp+v86_regs.eflags+1], not 2
645
        and     byte [esp+v86_regs.eflags+1], not 2
646
        inc     word [esp+v86_regs.eip]
646
        inc     word [esp+v86_regs.eip]
647
        popad
647
        popad
648
        iretd
648
        iretd
649
.handle_sti:
649
.handle_sti:
650
        or      byte [esp+v86_regs.eflags+1], 2
650
        or      byte [esp+v86_regs.eflags+1], 2
651
        inc     word [esp+v86_regs.eip]
651
        inc     word [esp+v86_regs.eip]
652
        popad
652
        popad
653
        iretd
653
        iretd
654
.handle_rep:
654
.handle_rep:
655
        cmp     word [esp+v86_regs.eip], 0xFFFF
655
        cmp     word [esp+v86_regs.eip], 0xFFFF
656
        jae     .nogp
656
        jae     .nogp
657
        lodsb
657
        lodsb
658
        cmp     al, 6Eh
658
        cmp     al, 6Eh
659
        jz      .handle_rep_outsb
659
        jz      .handle_rep_outsb
660
        jmp     .nogp
660
        jmp     .nogp
661
.handle_rep_outsb:
661
.handle_rep_outsb:
662
.handle_in:
662
.handle_in:
663
.handle_out:
663
.handle_out:
664
.invalid_io_byte:
664
.invalid_io_byte:
665
        movzx   ebx, word [esp+v86_regs.edx]
665
        movzx   ebx, word [esp+v86_regs.edx]
666
        mov     ecx, 1
666
        mov     ecx, 1
667
        jmp     .invalid_io
667
        jmp     .invalid_io
668
.handle_in_imm:
668
.handle_in_imm:
669
.handle_out_imm:
669
.handle_out_imm:
670
        cmp     word [esp+v86_regs.eip], 0xFFFF
670
        cmp     word [esp+v86_regs.eip], 0xFFFF
671
        jae     .nogp
671
        jae     .nogp
672
        lodsb
672
        lodsb
673
        movzx   ebx, al
673
        movzx   ebx, al
674
        mov     ecx, 1
674
        mov     ecx, 1
675
        jmp     .invalid_io
675
        jmp     .invalid_io
676
.handle_66:
676
.handle_66:
677
        cmp     word [esp+v86_regs.eip], 0xFFFF
677
        cmp     word [esp+v86_regs.eip], 0xFFFF
678
        jae     .nogp
678
        jae     .nogp
679
        lodsb
679
        lodsb
680
        cmp     al, 0x9C
680
        cmp     al, 0x9C
681
        jz      .handle_pushfd
681
        jz      .handle_pushfd
682
        cmp     al, 0x9D
682
        cmp     al, 0x9D
683
        jz      .handle_popfd
683
        jz      .handle_popfd
684
        cmp     al, 0xEF
684
        cmp     al, 0xEF
685
        jz      .handle_out_dword
685
        jz      .handle_out_dword
686
        cmp     al, 0xED
686
        cmp     al, 0xED
687
        jz      .handle_in_dword
687
        jz      .handle_in_dword
688
        jmp     .nogp
688
        jmp     .nogp
689
.handle_in_word:
689
.handle_in_word:
690
.handle_out_word:
690
.handle_out_word:
691
        movzx   ebx, word [esp+v86_regs.edx]
691
        movzx   ebx, word [esp+v86_regs.edx]
692
        mov     ecx, 2
692
        mov     ecx, 2
693
        jmp     .invalid_io
693
        jmp     .invalid_io
694
.handle_in_dword:
694
.handle_in_dword:
695
.handle_out_dword:
695
.handle_out_dword:
696
.invalid_io_dword:
696
.invalid_io_dword:
697
        movzx   ebx, word [esp+v86_regs.edx]
697
        movzx   ebx, word [esp+v86_regs.edx]
698
        mov     ecx, 4
698
        mov     ecx, 4
699
.invalid_io:
699
.invalid_io:
700
        mov     esi, v86_io_str1
700
        mov     esi, v86_io_str1
701
        call    sys_msg_board_str
701
        call    sys_msg_board_str
702
        mov     eax, ebx
702
        mov     eax, ebx
703
        call    sys_msg_board_dword
703
        call    sys_msg_board_dword
704
        mov     esi, v86_io_byte
704
        mov     esi, v86_io_byte
705
        cmp     ecx, 1
705
        cmp     ecx, 1
706
        jz      @f
706
        jz      @f
707
        mov     esi, v86_io_word
707
        mov     esi, v86_io_word
708
        cmp     ecx, 2
708
        cmp     ecx, 2
709
        jz      @f
709
        jz      @f
710
        mov     esi, v86_io_dword
710
        mov     esi, v86_io_dword
711
@@:
711
@@:
712
        call    sys_msg_board_str
712
        call    sys_msg_board_str
713
if DEBUG_SHOW_IO
713
if DEBUG_SHOW_IO
714
        mov     edx, ebx
714
        mov     edx, ebx
715
        mov     ebx, 200
715
        mov     ebx, 200
716
        call    delay_hs
716
        call    delay_hs
717
        mov     esi, [esp+v86_regs.size+10h+4]
717
        mov     esi, [esp+v86_regs.size+10h+4]
718
        mov     eax, [esi+V86_machine.iopm]
718
        mov     eax, [esi+V86_machine.iopm]
719
@@:
719
@@:
720
        btr     [eax], edx
720
        btr     [eax], edx
721
        inc     edx
721
        inc     edx
722
        loop    @b
722
        loop    @b
723
        popad
723
        popad
724
        iretd
724
        iretd
725
else
725
else
726
        mov     eax, 2
726
        mov     eax, 2
727
        jmp     .exit
727
        jmp     .exit
728
end if
728
end if
729
.nogp:
729
.nogp:
730
 
730
 
731
        mov     esi, v86_exc_str1
731
        mov     esi, v86_exc_str1
732
        call    sys_msg_board_str
732
        call    sys_msg_board_str
733
        mov     al, bl
733
        mov     al, bl
734
        call    sys_msg_board_byte
734
        call    sys_msg_board_byte
735
        mov     esi, v86_exc_str2
735
        mov     esi, v86_exc_str2
736
        call    sys_msg_board_str
736
        call    sys_msg_board_str
737
        mov     ax, [esp+32+4]
737
        mov     ax, [esp+32+4]
738
        call    sys_msg_board_word
738
        call    sys_msg_board_word
739
        mov     esi, v86_exc_str3
739
        mov     esi, v86_exc_str3
740
        call    sys_msg_board_str
740
        call    sys_msg_board_str
741
        mov     ax, [esp+32]
741
        mov     ax, [esp+32]
742
        call    sys_msg_board_word
742
        call    sys_msg_board_word
743
        mov     esi, v86_exc_str4
743
        mov     esi, v86_exc_str4
744
        call    sys_msg_board_str
744
        call    sys_msg_board_str
745
        mov     ecx, 8
745
        mov     ecx, 8
746
        movzx   edx, word [esp+32+4]
746
        movzx   edx, word [esp+32+4]
747
        shl     edx, 4
747
        shl     edx, 4
748
        add     edx, [esp+32]
748
        add     edx, [esp+32]
749
@@:
749
@@:
750
        mov     esi, [esp+v86_regs.size+10h+4]
750
        mov     esi, [esp+v86_regs.size+10h+4]
751
        mov     eax, edx
751
        mov     eax, edx
752
        call    v86_get_lin_addr
752
        call    v86_get_lin_addr
753
        cmp     eax, 0x1000
753
        cmp     eax, 0x1000
754
        jb      .nopage
754
        jb      .nopage
755
        mov     esi, v86_exc_str3-2
755
        mov     esi, v86_exc_str3-2
756
        call    sys_msg_board_str
756
        call    sys_msg_board_str
757
        mov     al, [edx]
757
        mov     al, [edx]
758
        call    sys_msg_board_byte
758
        call    sys_msg_board_byte
759
        inc     edx
759
        inc     edx
760
        loop    @b
760
        loop    @b
761
        jmp     @f
761
        jmp     @f
762
.nopage:
762
.nopage:
763
        mov     esi, v86_exc_str5
763
        mov     esi, v86_exc_str5
764
        call    sys_msg_board_str
764
        call    sys_msg_board_str
765
@@:
765
@@:
766
        mov     esi, v86_newline
766
        mov     esi, v86_newline
767
        call    sys_msg_board_str
767
        call    sys_msg_board_str
768
        mov     eax, 1
768
        mov     eax, 1
769
        jmp     .exit
769
        jmp     .exit
770
 
770
 
771
.done:
771
.done:
772
        xor     eax, eax
772
        xor     eax, eax
773
 
773
 
774
.exit:
774
.exit:
775
        mov     [esp+v86_regs.size+10h+1Ch], eax
775
        mov     [esp+v86_regs.size+10h+1Ch], eax
776
        mov     [esp+v86_regs.size+10h+18h], ebx
776
        mov     [esp+v86_regs.size+10h+18h], ebx
777
 
777
 
778
        mov     edx, [esp+v86_regs.size+10h+14h]
778
        mov     edx, [esp+v86_regs.size+10h+14h]
779
        cmp     edx, -1
779
        cmp     edx, -1
780
        jz      @f
780
        jz      @f
781
        dec     [v86_irqhooks+edx*8+4]
781
        dec     [v86_irqhooks+edx*8+4]
782
        jnz     @f
782
        jnz     @f
783
        and     [v86_irqhooks+edx*8], 0
783
        and     [v86_irqhooks+edx*8], 0
784
@@:
784
@@:
785
 
785
 
786
        mov     esi, esp
786
        mov     esi, esp
787
        mov     edi, [esi+v86_regs.size+10h+10h]
787
        mov     edi, [esi+v86_regs.size+10h+10h]
788
        add     edi, v86_regs.size
788
        add     edi, v86_regs.size
789
        mov     ecx, v86_regs.size/4
789
        mov     ecx, v86_regs.size/4
790
        rep     movsd
790
        rep     movsd
791
        mov     esp, esi
791
        mov     esp, esi
792
 
792
 
793
        cli
793
        cli
794
        mov     ecx, [CURRENT_TASK]
794
        mov     ecx, [CURRENT_TASK]
795
        shl     ecx, 8
795
        shl     ecx, 8
796
        pop     eax
796
        pop     eax
797
        mov     [SLOT_BASE+ecx+APPDATA.saved_esp0], eax
797
        mov     [SLOT_BASE+ecx+APPDATA.saved_esp0], eax
798
        mov     [tss._esp0], eax
798
        mov     [tss._esp0], eax
799
        pop     eax
799
        pop     eax
800
        mov     [SLOT_BASE+ecx+APPDATA.dir_table], eax
800
        mov     [SLOT_BASE+ecx+APPDATA.dir_table], eax
801
        pop     ebx
801
        pop     ebx
802
        mov     dword [SLOT_BASE+ecx+APPDATA.io_map+4], ebx
802
        mov     dword [SLOT_BASE+ecx+APPDATA.io_map+4], ebx
803
        mov     dword [page_tabs + (tss._io_map_1 shr 10)], ebx
803
        mov     dword [page_tabs + (tss._io_map_1 shr 10)], ebx
804
        pop     ebx
804
        pop     ebx
805
        mov     dword [SLOT_BASE+ecx+APPDATA.io_map], ebx
805
        mov     dword [SLOT_BASE+ecx+APPDATA.io_map], ebx
806
        mov     dword [page_tabs + (tss._io_map_0 shr 10)], ebx
806
        mov     dword [page_tabs + (tss._io_map_0 shr 10)], ebx
807
        mov     cr3, eax
807
        mov     cr3, eax
808
;        mov     [irq_tab+5*4], 0
-
 
809
        sti
808
        sti
810
 
809
 
811
        popad
810
        popad
812
        ret
811
        ret
813
 
812
 
814
;my05:
813
;my05:
815
;        mov     dx, 30C2h
814
;        mov     dx, 30C2h
816
;        mov     cx, 4
815
;        mov     cx, 4
817
;.0:
816
;.0:
818
;        in      al, dx
817
;        in      al, dx
819
;        cmp     al, 0FFh
818
;        cmp     al, 0FFh
820
;        jz      @f
819
;        jz      @f
821
;        test    al, 4
820
;        test    al, 4
822
;        jnz     .1
821
;        jnz     .1
823
;@@:
822
;@@:
824
;        add     dx, 8
823
;        add     dx, 8
825
;        in      al, dx
824
;        in      al, dx
826
;        cmp     al, 0FFh
825
;        cmp     al, 0FFh
827
;        jz      @f
826
;        jz      @f
828
;        test    al, 4
827
;        test    al, 4
829
;        jnz     .1
828
;        jnz     .1
830
;@@:
829
;@@:
831
;        loop    .0
830
;        loop    .0
832
;        ret
831
;        ret
833
;.1:
832
;.1:
834
;        or      al, 84h
833
;        or      al, 84h
835
;        out     dx, al
834
;        out     dx, al
836
;.2:
835
;.2:
837
;        mov     dx, 30F7h
836
;        mov     dx, 30F7h
838
;        in      al, dx
837
;        in      al, dx
839
;        mov     byte [BOOT_VAR + 48Eh], 0FFh
838
;        mov     byte [BOOT_VAR + 48Eh], 0FFh
840
;        ret
839
;        ret
841
 
840
 
842
align 4
841
align 4
843
v86_irq:
842
v86_irq:
844
; push irq/pushad/jmp v86_irq
843
; push irq/pushad/jmp v86_irq
845
; ebp = irq
844
; ebp = irq
846
        lea     esi, [esp+1Ch]
845
        lea     esi, [esp+1Ch]
847
        lea     edi, [esi+4]
846
        lea     edi, [esi+4]
848
        mov     ecx, 8
847
        mov     ecx, 8
849
        std
848
        std
850
        rep     movsd
849
        rep     movsd
851
        cld
850
        cld
852
        mov     edi, ebp
851
        mov     edi, ebp
853
        pop     eax
852
        pop     eax
854
v86_irq2:
853
v86_irq2:
855
        mov     esi, [v86_irqhooks+edi*8]       ; get VM handle
854
        mov     esi, [v86_irqhooks+edi*8]       ; get VM handle
856
        mov     eax, [esi+V86_machine.pagedir]
855
        mov     eax, [esi+V86_machine.pagedir]
857
        call    get_pg_addr
856
        call    get_pg_addr
858
        mov     ecx, [CURRENT_TASK]
857
        mov     ecx, [CURRENT_TASK]
859
        shl     ecx, 8
858
        shl     ecx, 8
860
        cmp     [SLOT_BASE+ecx+APPDATA.dir_table], eax
859
        cmp     [SLOT_BASE+ecx+APPDATA.dir_table], eax
861
        jnz     .notcurrent
860
        jnz     .notcurrent
862
        lea     eax, [edi+8]
861
        lea     eax, [edi+8]
863
        cmp     al, 10h
862
        cmp     al, 10h
864
        mov     ah, 1
863
        mov     ah, 1
865
        jb      @f
864
        jb      @f
866
        add     al, 60h
865
        add     al, 60h
867
@@:
866
@@:
868
        jmp     v86_exc_c.simulate_int
867
        jmp     v86_exc_c.simulate_int
869
.notcurrent:
868
.notcurrent:
870
        mov     ebx, SLOT_BASE + 0x100
869
        mov     ebx, SLOT_BASE + 0x100
871
        mov     ecx, [TASK_COUNT]
870
        mov     ecx, [TASK_COUNT]
872
.scan:
871
.scan:
873
        cmp     [ebx+APPDATA.dir_table], eax
872
        cmp     [ebx+APPDATA.dir_table], eax
874
        jnz     .cont
873
        jnz     .cont
875
        push    ecx
874
        push    ecx
876
        mov     ecx, [ebx+APPDATA.saved_esp0]
875
        mov     ecx, [ebx+APPDATA.saved_esp0]
877
        cmp     word [ecx-v86_regs.size+v86_regs.esp], 6
876
        cmp     word [ecx-v86_regs.size+v86_regs.esp], 6
878
        jb      .cont2
877
        jb      .cont2
879
        movzx   edx, word [ecx-v86_regs.size+v86_regs.ss]
878
        movzx   edx, word [ecx-v86_regs.size+v86_regs.ss]
880
        shl     edx, 4
879
        shl     edx, 4
881
        push    eax
880
        push    eax
882
        movzx   eax, word [ecx-v86_regs.size+v86_regs.esp]
881
        movzx   eax, word [ecx-v86_regs.size+v86_regs.esp]
883
        sub     eax, 6
882
        sub     eax, 6
884
        add     edx, eax
883
        add     edx, eax
885
        mov     eax, edx
884
        mov     eax, edx
886
        call    v86_get_lin_addr
885
        call    v86_get_lin_addr
887
        cmp     eax, 0x1000
886
        cmp     eax, 0x1000
888
        jb      .cont3
887
        jb      .cont3
889
        lea     eax, [edx+5]
888
        lea     eax, [edx+5]
890
        call    v86_get_lin_addr
889
        call    v86_get_lin_addr
891
        cmp     eax, 0x1000
890
        cmp     eax, 0x1000
892
        jb      .cont3
891
        jb      .cont3
893
        pop     eax
892
        pop     eax
894
        pop     ecx
893
        pop     ecx
895
        jmp     .found
894
        jmp     .found
896
.cont3:
895
.cont3:
897
        pop     eax
896
        pop     eax
898
.cont2:
897
.cont2:
899
        pop     ecx
898
        pop     ecx
900
.cont:
899
.cont:
901
        loop    .scan
900
        loop    .scan
902
	
901
 
903
	mov	eax, edi
902
	mov	eax, edi
904
	call	IRQ_EOI
903
	call	IRQ_EOI
905
 
904
 
906
        popad
905
        popad
907
        iretd
906
        iretd
908
.found:
907
.found:
909
        mov     cr3, eax
908
        mov     cr3, eax
910
        sub     word [esi-v86_regs.size+v86_regs.esp], 6
909
        sub     word [esi-v86_regs.size+v86_regs.esp], 6
911
        mov     ecx, [esi-v86_regs.size+v86_regs.eip]
910
        mov     ecx, [esi-v86_regs.size+v86_regs.eip]
912
        mov     word [edx], cx
911
        mov     word [edx], cx
913
        mov     ecx, [esi-v86_regs.size+v86_regs.cs]
912
        mov     ecx, [esi-v86_regs.size+v86_regs.cs]
914
        mov     word [edx+2], cx
913
        mov     word [edx+2], cx
915
        mov     ecx, [esi-v86_regs.size+v86_regs.eflags]
914
        mov     ecx, [esi-v86_regs.size+v86_regs.eflags]
916
        mov     word [edx+4], cx
915
        mov     word [edx+4], cx
917
        lea     eax, [edi+8]
916
        lea     eax, [edi+8]
918
        cmp     al, 10h
917
        cmp     al, 10h
919
        jb      @f
918
        jb      @f
920
        add     al, 60h
919
        add     al, 60h
921
@@:
920
@@:
922
        mov     cx, [eax*4]
921
        mov     cx, [eax*4]
923
        mov     word [esi-v86_regs.size+v86_regs.eip], cx
922
        mov     word [esi-v86_regs.size+v86_regs.eip], cx
924
        mov     cx, [eax*4+2]
923
        mov     cx, [eax*4+2]
925
        mov     word [esi-v86_regs.size+v86_regs.cs], cx
924
        mov     word [esi-v86_regs.size+v86_regs.cs], cx
926
        and     byte [esi-v86_regs.size+v86_regs.eflags+1], not 3
925
        and     byte [esi-v86_regs.size+v86_regs.eflags+1], not 3
927
        call    update_counters
926
        call    update_counters
928
        lea     edi, [ebx + 0x100000000 - SLOT_BASE]
927
        lea     edi, [ebx + 0x100000000 - SLOT_BASE]
929
        shr     edi, 3
928
        shr     edi, 3
930
        add     edi, TASK_DATA
929
        add     edi, TASK_DATA
931
        call    find_next_task.found
930
        call    find_next_task.found
932
        call    do_change_task
931
        call    do_change_task
933
        popad
932
        popad
934
        iretd
933
        iretd