Rev 2167 | Rev 2384 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2167 | Rev 2288 | ||
---|---|---|---|
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: 2167 $ |
8 | $Revision: 2288 $ |
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 | @@: |
|
374 | @@: mov eax, [esp+v86_regs.size+10h+18h] |
375 | mov eax, [esp+v86_regs.size+10h+18h] |
375 | cmp word [esp+v86_regs.eip], ax |
376 | cmp word [esp+v86_regs.eip], ax |
376 | jnz @f |
377 | jnz @f |
377 | shr eax, 16 |
378 | shr eax, 16 |
378 | cmp word [esp+v86_regs.cs], ax |
379 | cmp word [esp+v86_regs.cs], ax |
379 | jz .done |
380 | jz .done |
380 | @@: |
381 | @@: |
381 | ; Various system events, which must be handled, result in #GP |
382 | ; Various system events, which must be handled, result in #GP |
382 | cmp bl, 13 |
383 | cmp bl, 13 |
383 | jnz .nogp |
384 | jnz .nogp |
384 | ; If faulted EIP exceeds 0xFFFF, we have #GP and it is an error |
385 | ; If faulted EIP exceeds 0xFFFF, we have #GP and it is an error |
385 | cmp word [esp+v86_regs.eip+2], 0 |
386 | cmp word [esp+v86_regs.eip+2], 0 |
386 | jnz .nogp |
387 | jnz .nogp |
387 | ; Otherwise we can safely access byte at CS:IP |
388 | ; Otherwise we can safely access byte at CS:IP |
388 | ; (because it is #GP, not #PF handler) |
389 | ; (because it is #GP, not #PF handler) |
389 | ; ᫨ ¡ë ¬ë ¬®£«¨ áå«®¯®â âì ¨áª«î票¥ ⮫쪮 ¨§-§ çâ¥¨ï ¡ ©â®¢ ª®¤ , |
390 | ; ᫨ ¡ë ¬ë ¬®£«¨ áå«®¯®â âì ¨áª«î票¥ ⮫쪮 ¨§-§ çâ¥¨ï ¡ ©â®¢ ª®¤ , |
390 | ; ¬ë ¡ë ¥£® 㦥 áå«®¯®â «¨ ¨ íâ® ¡ë«® ¡ë ¥ #GP |
391 | ; ¬ë ¡ë ¥£® 㦥 áå«®¯®â «¨ ¨ íâ® ¡ë«® ¡ë ¥ #GP |
391 | movzx esi, word [esp+v86_regs.cs] |
392 | movzx esi, word [esp+v86_regs.cs] |
392 | shl esi, 4 |
393 | shl esi, 4 |
393 | add esi, [esp+v86_regs.eip] |
394 | add esi, [esp+v86_regs.eip] |
394 | lodsb |
395 | lodsb |
395 | cmp al, 0xCD ; int xx command = CD xx |
396 | cmp al, 0xCD ; int xx command = CD xx |
396 | jz .handle_int |
397 | jz .handle_int |
397 | cmp al, 0xCF |
398 | cmp al, 0xCF |
398 | jz .handle_iret |
399 | jz .handle_iret |
399 | cmp al, 0xF3 |
400 | cmp al, 0xF3 |
400 | jz .handle_rep |
401 | jz .handle_rep |
401 | cmp al, 0xEC |
402 | cmp al, 0xEC |
402 | jz .handle_in |
403 | jz .handle_in |
403 | cmp al, 0xED |
404 | cmp al, 0xED |
404 | jz .handle_in_word |
405 | jz .handle_in_word |
405 | cmp al, 0xEE |
406 | cmp al, 0xEE |
406 | jz .handle_out |
407 | jz .handle_out |
407 | cmp al, 0xEF |
408 | cmp al, 0xEF |
408 | jz .handle_out_word |
409 | jz .handle_out_word |
409 | cmp al, 0xE4 |
410 | cmp al, 0xE4 |
410 | jz .handle_in_imm |
411 | jz .handle_in_imm |
411 | cmp al, 0xE6 |
412 | cmp al, 0xE6 |
412 | jz .handle_out_imm |
413 | jz .handle_out_imm |
413 | cmp al, 0x9C |
414 | cmp al, 0x9C |
414 | jz .handle_pushf |
415 | jz .handle_pushf |
415 | cmp al, 0x9D |
416 | cmp al, 0x9D |
416 | jz .handle_popf |
417 | jz .handle_popf |
417 | cmp al, 0xFA |
418 | cmp al, 0xFA |
418 | jz .handle_cli |
419 | jz .handle_cli |
419 | cmp al, 0xFB |
420 | cmp al, 0xFB |
420 | jz .handle_sti |
421 | jz .handle_sti |
421 | cmp al, 0x66 |
422 | cmp al, 0x66 |
422 | jz .handle_66 |
423 | jz .handle_66 |
423 | jmp .nogp |
424 | jmp .nogp |
424 | .handle_int: |
425 | .handle_int: |
425 | cmp word [esp+v86_regs.eip], 0xFFFF |
426 | cmp word [esp+v86_regs.eip], 0xFFFF |
426 | jae .nogp |
427 | jae .nogp |
427 | xor eax, eax |
428 | xor eax, eax |
428 | lodsb |
429 | lodsb |
429 | ; call sys_msg_board_byte |
430 | ; call sys_msg_board_byte |
430 | ; simulate INT command |
431 | ; simulate INT command |
431 | ; N.B. It is possible that some checks need to be corrected, |
432 | ; N.B. It is possible that some checks need to be corrected, |
432 | ; but at least in case of normal execution the code works. |
433 | ; but at least in case of normal execution the code works. |
433 | .simulate_int: |
434 | .simulate_int: |
434 | cmp word [esp+v86_regs.esp], 6 |
435 | cmp word [esp+v86_regs.esp], 6 |
435 | jae @f |
436 | jae @f |
436 | mov bl, 12 ; #SS exception |
437 | mov bl, 12 ; #SS exception |
437 | jmp .nogp |
438 | jmp .nogp |
438 | @@: |
439 | @@: |
439 | movzx edx, word [esp+v86_regs.ss] |
440 | movzx edx, word [esp+v86_regs.ss] |
440 | shl edx, 4 |
441 | shl edx, 4 |
441 | push eax |
442 | push eax |
442 | movzx eax, word [esp+4+v86_regs.esp] |
443 | movzx eax, word [esp+4+v86_regs.esp] |
443 | sub eax, 6 |
444 | sub eax, 6 |
444 | add edx, eax |
445 | add edx, eax |
445 | mov eax, edx |
446 | mov eax, edx |
446 | mov esi, [esp+4+v86_regs.size+10h+4] |
447 | mov esi, [esp+4+v86_regs.size+10h+4] |
447 | call v86_get_lin_addr |
448 | call v86_get_lin_addr |
448 | cmp eax, 0x1000 |
449 | cmp eax, 0x1000 |
449 | jae @f |
450 | jae @f |
450 | mov bl, 14 ; #PF exception |
451 | mov bl, 14 ; #PF exception |
451 | jmp .nogp |
452 | jmp .nogp |
452 | @@: |
453 | @@: |
453 | lea eax, [edx+5] |
454 | lea eax, [edx+5] |
454 | call v86_get_lin_addr |
455 | call v86_get_lin_addr |
455 | cmp eax, 0x1000 |
456 | cmp eax, 0x1000 |
456 | jae @f |
457 | jae @f |
457 | mov bl, 14 ; #PF exception |
458 | mov bl, 14 ; #PF exception |
458 | jmp .nogp |
459 | jmp .nogp |
459 | @@: |
460 | @@: |
460 | sub word [esp+4+v86_regs.esp], 6 |
461 | sub word [esp+4+v86_regs.esp], 6 |
461 | mov eax, [esp+4+v86_regs.eip] |
462 | mov eax, [esp+4+v86_regs.eip] |
462 | cmp byte [esp+1], 0 |
463 | cmp byte [esp+1], 0 |
463 | jnz @f |
464 | jnz @f |
464 | inc eax |
465 | inc eax |
465 | inc eax |
466 | inc eax |
466 | @@: |
467 | @@: |
467 | mov word [edx], ax |
468 | mov word [edx], ax |
468 | mov eax, [esp+4+v86_regs.cs] |
469 | mov eax, [esp+4+v86_regs.cs] |
469 | mov word [edx+2], ax |
470 | mov word [edx+2], ax |
470 | mov eax, [esp+4+v86_regs.eflags] |
471 | mov eax, [esp+4+v86_regs.eflags] |
471 | mov word [edx+4], ax |
472 | mov word [edx+4], ax |
472 | pop eax |
473 | pop eax |
473 | mov ah, 0 |
474 | mov ah, 0 |
474 | mov cx, [eax*4] |
475 | mov cx, [eax*4] |
475 | mov word [esp+v86_regs.eip], cx |
476 | mov word [esp+v86_regs.eip], cx |
476 | mov cx, [eax*4+2] |
477 | mov cx, [eax*4+2] |
477 | mov word [esp+v86_regs.cs], cx |
478 | mov word [esp+v86_regs.cs], cx |
478 | ; note that interrupts will be disabled globally at IRET |
479 | ; note that interrupts will be disabled globally at IRET |
479 | and byte [esp+v86_regs.eflags+1], not 3 ; clear IF and TF flags |
480 | and byte [esp+v86_regs.eflags+1], not 3 ; clear IF and TF flags |
480 | ; continue V86 execution |
481 | ; continue V86 execution |
481 | popad |
482 | popad |
482 | iretd |
483 | iretd |
483 | .handle_iret: |
484 | .handle_iret: |
484 | cmp word [esp+v86_regs.esp], 0x10000 - 6 |
485 | cmp word [esp+v86_regs.esp], 0x10000 - 6 |
485 | jbe @f |
486 | jbe @f |
486 | mov bl, 12 |
487 | mov bl, 12 |
487 | jmp .nogp |
488 | jmp .nogp |
488 | @@: |
489 | @@: |
489 | movzx edx, word [esp+v86_regs.ss] |
490 | movzx edx, word [esp+v86_regs.ss] |
490 | shl edx, 4 |
491 | shl edx, 4 |
491 | movzx eax, word [esp+v86_regs.esp] |
492 | movzx eax, word [esp+v86_regs.esp] |
492 | add edx, eax |
493 | add edx, eax |
493 | mov eax, edx |
494 | mov eax, edx |
494 | mov esi, [esp+v86_regs.size+10h+4] |
495 | mov esi, [esp+v86_regs.size+10h+4] |
495 | call v86_get_lin_addr |
496 | call v86_get_lin_addr |
496 | cmp eax, 0x1000 |
497 | cmp eax, 0x1000 |
497 | jae @f |
498 | jae @f |
498 | mov bl, 14 |
499 | mov bl, 14 |
499 | jmp .nogp |
500 | jmp .nogp |
500 | @@: |
501 | @@: |
501 | lea eax, [edx+5] |
502 | lea eax, [edx+5] |
502 | call v86_get_lin_addr |
503 | call v86_get_lin_addr |
503 | cmp eax, 0x1000 |
504 | cmp eax, 0x1000 |
504 | jae @f |
505 | jae @f |
505 | mov bl, 14 |
506 | mov bl, 14 |
506 | jmp .nogp |
507 | jmp .nogp |
507 | @@: |
508 | @@: |
508 | mov ax, [edx] |
509 | mov ax, [edx] |
509 | mov word [esp+v86_regs.eip], ax |
510 | mov word [esp+v86_regs.eip], ax |
510 | mov ax, [edx+2] |
511 | mov ax, [edx+2] |
511 | mov word [esp+v86_regs.cs], ax |
512 | mov word [esp+v86_regs.cs], ax |
512 | mov ax, [edx+4] |
513 | mov ax, [edx+4] |
513 | mov word [esp+v86_regs.eflags], ax |
514 | mov word [esp+v86_regs.eflags], ax |
514 | add word [esp+v86_regs.esp], 6 |
515 | add word [esp+v86_regs.esp], 6 |
515 | popad |
516 | popad |
516 | iretd |
517 | iretd |
517 | .handle_pushf: |
518 | .handle_pushf: |
518 | cmp word [esp+v86_regs.esp], 1 |
519 | cmp word [esp+v86_regs.esp], 1 |
519 | jnz @f |
520 | jnz @f |
520 | mov bl, 12 |
521 | mov bl, 12 |
521 | jmp .nogp |
522 | jmp .nogp |
522 | @@: |
523 | @@: |
523 | movzx edx, word [esp+v86_regs.ss] |
524 | movzx edx, word [esp+v86_regs.ss] |
524 | shl edx, 4 |
525 | shl edx, 4 |
525 | mov eax, [esp+v86_regs.esp] |
526 | mov eax, [esp+v86_regs.esp] |
526 | sub eax, 2 |
527 | sub eax, 2 |
527 | movzx eax, ax |
528 | movzx eax, ax |
528 | add edx, eax |
529 | add edx, eax |
529 | mov eax, edx |
530 | mov eax, edx |
530 | mov esi, [esp+v86_regs.size+10h+4] |
531 | mov esi, [esp+v86_regs.size+10h+4] |
531 | call v86_get_lin_addr |
532 | call v86_get_lin_addr |
532 | cmp eax, 0x1000 |
533 | cmp eax, 0x1000 |
533 | jae @f |
534 | jae @f |
534 | mov bl, 14 ; #PF exception |
535 | mov bl, 14 ; #PF exception |
535 | jmp .nogp |
536 | jmp .nogp |
536 | @@: |
537 | @@: |
537 | lea eax, [edx+1] |
538 | lea eax, [edx+1] |
538 | call v86_get_lin_addr |
539 | call v86_get_lin_addr |
539 | cmp eax, 0x1000 |
540 | cmp eax, 0x1000 |
540 | jae @f |
541 | jae @f |
541 | mov bl, 14 |
542 | mov bl, 14 |
542 | jmp .nogp |
543 | jmp .nogp |
543 | @@: |
544 | @@: |
544 | sub word [esp+v86_regs.esp], 2 |
545 | sub word [esp+v86_regs.esp], 2 |
545 | mov eax, [esp+v86_regs.eflags] |
546 | mov eax, [esp+v86_regs.eflags] |
546 | mov [edx], ax |
547 | mov [edx], ax |
547 | inc word [esp+v86_regs.eip] |
548 | inc word [esp+v86_regs.eip] |
548 | popad |
549 | popad |
549 | iretd |
550 | iretd |
550 | .handle_pushfd: |
551 | .handle_pushfd: |
551 | cmp word [esp+v86_regs.esp], 4 |
552 | cmp word [esp+v86_regs.esp], 4 |
552 | jae @f |
553 | jae @f |
553 | mov bl, 12 ; #SS exception |
554 | mov bl, 12 ; #SS exception |
554 | jmp .nogp |
555 | jmp .nogp |
555 | @@: |
556 | @@: |
556 | movzx edx, word [esp+v86_regs.ss] |
557 | movzx edx, word [esp+v86_regs.ss] |
557 | shl edx, 4 |
558 | shl edx, 4 |
558 | movzx eax, word [esp+v86_regs.esp] |
559 | movzx eax, word [esp+v86_regs.esp] |
559 | sub eax, 4 |
560 | sub eax, 4 |
560 | add edx, eax |
561 | add edx, eax |
561 | mov eax, edx |
562 | mov eax, edx |
562 | mov esi, [esp+v86_regs.size+10h+4] |
563 | mov esi, [esp+v86_regs.size+10h+4] |
563 | call v86_get_lin_addr |
564 | call v86_get_lin_addr |
564 | cmp eax, 0x1000 |
565 | cmp eax, 0x1000 |
565 | jae @f |
566 | jae @f |
566 | mov bl, 14 ; #PF exception |
567 | mov bl, 14 ; #PF exception |
567 | jmp .nogp |
568 | jmp .nogp |
568 | @@: |
569 | @@: |
569 | lea eax, [edx+3] |
570 | lea eax, [edx+3] |
570 | call v86_get_lin_addr |
571 | call v86_get_lin_addr |
571 | cmp eax, 0x1000 |
572 | cmp eax, 0x1000 |
572 | jae @f |
573 | jae @f |
573 | mov bl, 14 ; #PF exception |
574 | mov bl, 14 ; #PF exception |
574 | jmp .nogp |
575 | jmp .nogp |
575 | @@: |
576 | @@: |
576 | sub word [esp+v86_regs.esp], 4 |
577 | sub word [esp+v86_regs.esp], 4 |
577 | movzx eax, word [esp+v86_regs.eflags] |
578 | movzx eax, word [esp+v86_regs.eflags] |
578 | mov [edx], eax |
579 | mov [edx], eax |
579 | add word [esp+v86_regs.eip], 2 |
580 | add word [esp+v86_regs.eip], 2 |
580 | popad |
581 | popad |
581 | iretd |
582 | iretd |
582 | .handle_popf: |
583 | .handle_popf: |
583 | cmp word [esp+v86_regs.esp], 0xFFFF |
584 | cmp word [esp+v86_regs.esp], 0xFFFF |
584 | jnz @f |
585 | jnz @f |
585 | mov bl, 12 |
586 | mov bl, 12 |
586 | jmp .nogp |
587 | jmp .nogp |
587 | @@: |
588 | @@: |
588 | movzx edx, word [esp+v86_regs.ss] |
589 | movzx edx, word [esp+v86_regs.ss] |
589 | shl edx, 4 |
590 | shl edx, 4 |
590 | movzx eax, word [esp+v86_regs.esp] |
591 | movzx eax, word [esp+v86_regs.esp] |
591 | add edx, eax |
592 | add edx, eax |
592 | mov eax, edx |
593 | mov eax, edx |
593 | mov esi, [esp+v86_regs.size+10h+4] |
594 | mov esi, [esp+v86_regs.size+10h+4] |
594 | call v86_get_lin_addr |
595 | call v86_get_lin_addr |
595 | cmp eax, 0x1000 |
596 | cmp eax, 0x1000 |
596 | jae @f |
597 | jae @f |
597 | mov bl, 14 ; #PF exception |
598 | mov bl, 14 ; #PF exception |
598 | jmp .nogp |
599 | jmp .nogp |
599 | @@: |
600 | @@: |
600 | lea eax, [edx+1] |
601 | lea eax, [edx+1] |
601 | call v86_get_lin_addr |
602 | call v86_get_lin_addr |
602 | cmp eax, 0x1000 |
603 | cmp eax, 0x1000 |
603 | jae @f |
604 | jae @f |
604 | mov bl, 14 |
605 | mov bl, 14 |
605 | jmp .nogp |
606 | jmp .nogp |
606 | @@: |
607 | @@: |
607 | mov ax, [edx] |
608 | mov ax, [edx] |
608 | mov word [esp+v86_regs.eflags], ax |
609 | mov word [esp+v86_regs.eflags], ax |
609 | add word [esp+v86_regs.esp], 2 |
610 | add word [esp+v86_regs.esp], 2 |
610 | inc word [esp+v86_regs.eip] |
611 | inc word [esp+v86_regs.eip] |
611 | popad |
612 | popad |
612 | iretd |
613 | iretd |
613 | .handle_popfd: |
614 | .handle_popfd: |
614 | cmp word [esp+v86_regs.esp], 0x10000 - 4 |
615 | cmp word [esp+v86_regs.esp], 0x10000 - 4 |
615 | jbe @f |
616 | jbe @f |
616 | mov bl, 12 |
617 | mov bl, 12 |
617 | jmp .nogp |
618 | jmp .nogp |
618 | @@: |
619 | @@: |
619 | movzx edx, word [esp+v86_regs.ss] |
620 | movzx edx, word [esp+v86_regs.ss] |
620 | shl edx, 4 |
621 | shl edx, 4 |
621 | movzx eax, word [esp+v86_regs.esp] |
622 | movzx eax, word [esp+v86_regs.esp] |
622 | add edx, eax |
623 | add edx, eax |
623 | mov eax, edx |
624 | mov eax, edx |
624 | mov esi, [esp+v86_regs.size+10h+4] |
625 | mov esi, [esp+v86_regs.size+10h+4] |
625 | call v86_get_lin_addr |
626 | call v86_get_lin_addr |
626 | cmp eax, 0x1000 |
627 | cmp eax, 0x1000 |
627 | jae @f |
628 | jae @f |
628 | mov bl, 14 |
629 | mov bl, 14 |
629 | jmp .nogp |
630 | jmp .nogp |
630 | @@: |
631 | @@: |
631 | lea eax, [edx+3] |
632 | lea eax, [edx+3] |
632 | call v86_get_lin_addr |
633 | call v86_get_lin_addr |
633 | cmp eax, 0x1000 |
634 | cmp eax, 0x1000 |
634 | jae @f |
635 | jae @f |
635 | mov bl, 14 |
636 | mov bl, 14 |
636 | jmp .nogp |
637 | jmp .nogp |
637 | @@: |
638 | @@: |
638 | mov eax, [edx] |
639 | mov eax, [edx] |
639 | mov word [esp+v86_regs.eflags], ax |
640 | mov word [esp+v86_regs.eflags], ax |
640 | add word [esp+v86_regs.esp], 4 |
641 | add word [esp+v86_regs.esp], 4 |
641 | add word [esp+v86_regs.eip], 2 |
642 | add word [esp+v86_regs.eip], 2 |
642 | popad |
643 | popad |
643 | iretd |
644 | iretd |
644 | .handle_cli: |
645 | .handle_cli: |
645 | and byte [esp+v86_regs.eflags+1], not 2 |
646 | and byte [esp+v86_regs.eflags+1], not 2 |
646 | inc word [esp+v86_regs.eip] |
647 | inc word [esp+v86_regs.eip] |
647 | popad |
648 | popad |
648 | iretd |
649 | iretd |
649 | .handle_sti: |
650 | .handle_sti: |
650 | or byte [esp+v86_regs.eflags+1], 2 |
651 | or byte [esp+v86_regs.eflags+1], 2 |
651 | inc word [esp+v86_regs.eip] |
652 | inc word [esp+v86_regs.eip] |
652 | popad |
653 | popad |
653 | iretd |
654 | iretd |
654 | .handle_rep: |
655 | .handle_rep: |
655 | cmp word [esp+v86_regs.eip], 0xFFFF |
656 | cmp word [esp+v86_regs.eip], 0xFFFF |
656 | jae .nogp |
657 | jae .nogp |
657 | lodsb |
658 | lodsb |
658 | cmp al, 6Eh |
659 | cmp al, 6Eh |
659 | jz .handle_rep_outsb |
660 | jz .handle_rep_outsb |
660 | jmp .nogp |
661 | jmp .nogp |
661 | .handle_rep_outsb: |
662 | .handle_rep_outsb: |
662 | .handle_in: |
663 | .handle_in: |
663 | .handle_out: |
664 | .handle_out: |
664 | .invalid_io_byte: |
665 | .invalid_io_byte: |
665 | movzx ebx, word [esp+v86_regs.edx] |
666 | movzx ebx, word [esp+v86_regs.edx] |
666 | mov ecx, 1 |
667 | mov ecx, 1 |
667 | jmp .invalid_io |
668 | jmp .invalid_io |
668 | .handle_in_imm: |
669 | .handle_in_imm: |
669 | .handle_out_imm: |
670 | .handle_out_imm: |
670 | cmp word [esp+v86_regs.eip], 0xFFFF |
671 | cmp word [esp+v86_regs.eip], 0xFFFF |
671 | jae .nogp |
672 | jae .nogp |
672 | lodsb |
673 | lodsb |
673 | movzx ebx, al |
674 | movzx ebx, al |
674 | mov ecx, 1 |
675 | mov ecx, 1 |
675 | jmp .invalid_io |
676 | jmp .invalid_io |
676 | .handle_66: |
677 | .handle_66: |
677 | cmp word [esp+v86_regs.eip], 0xFFFF |
678 | cmp word [esp+v86_regs.eip], 0xFFFF |
678 | jae .nogp |
679 | jae .nogp |
679 | lodsb |
680 | lodsb |
680 | cmp al, 0x9C |
681 | cmp al, 0x9C |
681 | jz .handle_pushfd |
682 | jz .handle_pushfd |
682 | cmp al, 0x9D |
683 | cmp al, 0x9D |
683 | jz .handle_popfd |
684 | jz .handle_popfd |
684 | cmp al, 0xEF |
685 | cmp al, 0xEF |
685 | jz .handle_out_dword |
686 | jz .handle_out_dword |
686 | cmp al, 0xED |
687 | cmp al, 0xED |
687 | jz .handle_in_dword |
688 | jz .handle_in_dword |
688 | jmp .nogp |
689 | jmp .nogp |
689 | .handle_in_word: |
690 | .handle_in_word: |
690 | .handle_out_word: |
691 | .handle_out_word: |
691 | movzx ebx, word [esp+v86_regs.edx] |
692 | movzx ebx, word [esp+v86_regs.edx] |
692 | mov ecx, 2 |
693 | mov ecx, 2 |
693 | jmp .invalid_io |
694 | jmp .invalid_io |
694 | .handle_in_dword: |
695 | .handle_in_dword: |
695 | .handle_out_dword: |
696 | .handle_out_dword: |
696 | .invalid_io_dword: |
697 | .invalid_io_dword: |
697 | movzx ebx, word [esp+v86_regs.edx] |
698 | movzx ebx, word [esp+v86_regs.edx] |
698 | mov ecx, 4 |
699 | mov ecx, 4 |
699 | .invalid_io: |
700 | .invalid_io: |
700 | mov esi, v86_io_str1 |
701 | mov esi, v86_io_str1 |
701 | call sys_msg_board_str |
702 | call sys_msg_board_str |
702 | mov eax, ebx |
703 | mov eax, ebx |
703 | call sys_msg_board_dword |
704 | call sys_msg_board_dword |
704 | mov esi, v86_io_byte |
705 | mov esi, v86_io_byte |
705 | cmp ecx, 1 |
706 | cmp ecx, 1 |
706 | jz @f |
707 | jz @f |
707 | mov esi, v86_io_word |
708 | mov esi, v86_io_word |
708 | cmp ecx, 2 |
709 | cmp ecx, 2 |
709 | jz @f |
710 | jz @f |
710 | mov esi, v86_io_dword |
711 | mov esi, v86_io_dword |
711 | @@: |
712 | @@: |
712 | call sys_msg_board_str |
713 | call sys_msg_board_str |
713 | if DEBUG_SHOW_IO |
714 | if DEBUG_SHOW_IO |
714 | mov edx, ebx |
715 | mov edx, ebx |
715 | mov ebx, 200 |
716 | mov ebx, 200 |
716 | call delay_hs |
717 | call delay_hs |
717 | mov esi, [esp+v86_regs.size+10h+4] |
718 | mov esi, [esp+v86_regs.size+10h+4] |
718 | mov eax, [esi+V86_machine.iopm] |
719 | mov eax, [esi+V86_machine.iopm] |
719 | @@: |
720 | @@: |
720 | btr [eax], edx |
721 | btr [eax], edx |
721 | inc edx |
722 | inc edx |
722 | loop @b |
723 | loop @b |
723 | popad |
724 | popad |
724 | iretd |
725 | iretd |
725 | else |
726 | else |
726 | mov eax, 2 |
727 | mov eax, 2 |
727 | jmp .exit |
728 | jmp .exit |
728 | end if |
729 | end if |
729 | .nogp: |
730 | .nogp: |
730 | 731 | ||
731 | mov esi, v86_exc_str1 |
732 | mov esi, v86_exc_str1 |
732 | call sys_msg_board_str |
733 | call sys_msg_board_str |
733 | mov al, bl |
734 | mov al, bl |
734 | call sys_msg_board_byte |
735 | call sys_msg_board_byte |
735 | mov esi, v86_exc_str2 |
736 | mov esi, v86_exc_str2 |
736 | call sys_msg_board_str |
737 | call sys_msg_board_str |
737 | mov ax, [esp+32+4] |
738 | mov ax, [esp+32+4] |
738 | call sys_msg_board_word |
739 | call sys_msg_board_word |
739 | mov esi, v86_exc_str3 |
740 | mov esi, v86_exc_str3 |
740 | call sys_msg_board_str |
741 | call sys_msg_board_str |
741 | mov ax, [esp+32] |
742 | mov ax, [esp+32] |
742 | call sys_msg_board_word |
743 | call sys_msg_board_word |
743 | mov esi, v86_exc_str4 |
744 | mov esi, v86_exc_str4 |
744 | call sys_msg_board_str |
745 | call sys_msg_board_str |
745 | mov ecx, 8 |
746 | mov ecx, 8 |
746 | movzx edx, word [esp+32+4] |
747 | movzx edx, word [esp+32+4] |
747 | shl edx, 4 |
748 | shl edx, 4 |
748 | add edx, [esp+32] |
749 | add edx, [esp+32] |
749 | @@: |
750 | @@: |
750 | mov esi, [esp+v86_regs.size+10h+4] |
751 | mov esi, [esp+v86_regs.size+10h+4] |
751 | mov eax, edx |
752 | mov eax, edx |
752 | call v86_get_lin_addr |
753 | call v86_get_lin_addr |
753 | cmp eax, 0x1000 |
754 | cmp eax, 0x1000 |
754 | jb .nopage |
755 | jb .nopage |
755 | mov esi, v86_exc_str3-2 |
756 | mov esi, v86_exc_str3-2 |
756 | call sys_msg_board_str |
757 | call sys_msg_board_str |
757 | mov al, [edx] |
758 | mov al, [edx] |
758 | call sys_msg_board_byte |
759 | call sys_msg_board_byte |
759 | inc edx |
760 | inc edx |
760 | loop @b |
761 | loop @b |
761 | jmp @f |
762 | jmp @f |
762 | .nopage: |
763 | .nopage: |
763 | mov esi, v86_exc_str5 |
764 | mov esi, v86_exc_str5 |
764 | call sys_msg_board_str |
765 | call sys_msg_board_str |
765 | @@: |
766 | @@: |
766 | mov esi, v86_newline |
767 | mov esi, v86_newline |
767 | call sys_msg_board_str |
768 | call sys_msg_board_str |
768 | mov eax, 1 |
769 | mov eax, 1 |
769 | jmp .exit |
770 | jmp .exit |
770 | 771 | ||
771 | .done: |
772 | .done: |
772 | xor eax, eax |
773 | xor eax, eax |
773 | 774 | ||
774 | .exit: |
775 | .exit: |
775 | mov [esp+v86_regs.size+10h+1Ch], eax |
776 | mov [esp+v86_regs.size+10h+1Ch], eax |
776 | mov [esp+v86_regs.size+10h+18h], ebx |
777 | mov [esp+v86_regs.size+10h+18h], ebx |
777 | 778 | ||
778 | mov edx, [esp+v86_regs.size+10h+14h] |
779 | mov edx, [esp+v86_regs.size+10h+14h] |
779 | cmp edx, -1 |
780 | cmp edx, -1 |
780 | jz @f |
781 | jz @f |
781 | dec [v86_irqhooks+edx*8+4] |
782 | dec [v86_irqhooks+edx*8+4] |
782 | jnz @f |
783 | jnz @f |
783 | and [v86_irqhooks+edx*8], 0 |
784 | and [v86_irqhooks+edx*8], 0 |
784 | @@: |
785 | @@: |
785 | 786 | ||
786 | mov esi, esp |
787 | mov esi, esp |
787 | mov edi, [esi+v86_regs.size+10h+10h] |
788 | mov edi, [esi+v86_regs.size+10h+10h] |
788 | add edi, v86_regs.size |
789 | add edi, v86_regs.size |
789 | mov ecx, v86_regs.size/4 |
790 | mov ecx, v86_regs.size/4 |
790 | rep movsd |
791 | rep movsd |
791 | mov esp, esi |
792 | mov esp, esi |
792 | 793 | ||
793 | cli |
794 | cli |
794 | mov ecx, [CURRENT_TASK] |
795 | mov ecx, [CURRENT_TASK] |
795 | shl ecx, 8 |
796 | shl ecx, 8 |
796 | pop eax |
797 | pop eax |
797 | mov [SLOT_BASE+ecx+APPDATA.saved_esp0], eax |
798 | mov [SLOT_BASE+ecx+APPDATA.saved_esp0], eax |
798 | mov [tss._esp0], eax |
799 | mov [tss._esp0], eax |
799 | pop eax |
800 | pop eax |
800 | mov [SLOT_BASE+ecx+APPDATA.dir_table], eax |
801 | mov [SLOT_BASE+ecx+APPDATA.dir_table], eax |
801 | pop ebx |
802 | pop ebx |
802 | mov dword [SLOT_BASE+ecx+APPDATA.io_map+4], ebx |
803 | mov dword [SLOT_BASE+ecx+APPDATA.io_map+4], ebx |
803 | mov dword [page_tabs + (tss._io_map_1 shr 10)], ebx |
804 | mov dword [page_tabs + (tss._io_map_1 shr 10)], ebx |
804 | pop ebx |
805 | pop ebx |
805 | mov dword [SLOT_BASE+ecx+APPDATA.io_map], ebx |
806 | mov dword [SLOT_BASE+ecx+APPDATA.io_map], ebx |
806 | mov dword [page_tabs + (tss._io_map_0 shr 10)], ebx |
807 | mov dword [page_tabs + (tss._io_map_0 shr 10)], ebx |
807 | mov cr3, eax |
808 | mov cr3, eax |
808 | sti |
809 | sti |
809 | 810 | ||
810 | popad |
811 | popad |
811 | ret |
812 | ret |
812 | 813 | ||
813 | ;my05: |
814 | ;my05: |
814 | ; mov dx, 30C2h |
815 | ; mov dx, 30C2h |
815 | ; mov cx, 4 |
816 | ; mov cx, 4 |
816 | ;.0: |
817 | ;.0: |
817 | ; in al, dx |
818 | ; in al, dx |
818 | ; cmp al, 0FFh |
819 | ; cmp al, 0FFh |
819 | ; jz @f |
820 | ; jz @f |
820 | ; test al, 4 |
821 | ; test al, 4 |
821 | ; jnz .1 |
822 | ; jnz .1 |
822 | ;@@: |
823 | ;@@: |
823 | ; add dx, 8 |
824 | ; add dx, 8 |
824 | ; in al, dx |
825 | ; in al, dx |
825 | ; cmp al, 0FFh |
826 | ; cmp al, 0FFh |
826 | ; jz @f |
827 | ; jz @f |
827 | ; test al, 4 |
828 | ; test al, 4 |
828 | ; jnz .1 |
829 | ; jnz .1 |
829 | ;@@: |
830 | ;@@: |
830 | ; loop .0 |
831 | ; loop .0 |
831 | ; ret |
832 | ; ret |
832 | ;.1: |
833 | ;.1: |
833 | ; or al, 84h |
834 | ; or al, 84h |
834 | ; out dx, al |
835 | ; out dx, al |
835 | ;.2: |
836 | ;.2: |
836 | ; mov dx, 30F7h |
837 | ; mov dx, 30F7h |
837 | ; in al, dx |
838 | ; in al, dx |
838 | ; mov byte [BOOT_VAR + 48Eh], 0FFh |
839 | ; mov byte [BOOT_VAR + 48Eh], 0FFh |
839 | ; ret |
840 | ; ret |
840 | 841 | ||
841 | align 4 |
842 | align 4 |
842 | v86_irq: |
843 | v86_irq: |
843 | ; push irq/pushad/jmp v86_irq |
844 | ; push irq/pushad/jmp v86_irq |
844 | ; ebp = irq |
845 | ; ebp = irq |
845 | lea esi, [esp+1Ch] |
846 | lea esi, [esp+1Ch] |
846 | lea edi, [esi+4] |
847 | lea edi, [esi+4] |
847 | mov ecx, 8 |
848 | mov ecx, 8 |
848 | std |
849 | std |
849 | rep movsd |
850 | rep movsd |
850 | cld |
851 | cld |
851 | mov edi, ebp |
852 | mov edi, ebp |
852 | pop eax |
853 | pop eax |
853 | v86_irq2: |
854 | v86_irq2: |
854 | mov esi, [v86_irqhooks+edi*8] ; get VM handle |
855 | mov esi, [v86_irqhooks+edi*8] ; get VM handle |
855 | mov eax, [esi+V86_machine.pagedir] |
856 | mov eax, [esi+V86_machine.pagedir] |
856 | call get_pg_addr |
857 | call get_pg_addr |
857 | mov ecx, [CURRENT_TASK] |
858 | mov ecx, [CURRENT_TASK] |
858 | shl ecx, 8 |
859 | shl ecx, 8 |
859 | cmp [SLOT_BASE+ecx+APPDATA.dir_table], eax |
860 | cmp [SLOT_BASE+ecx+APPDATA.dir_table], eax |
860 | jnz .notcurrent |
861 | jnz .notcurrent |
861 | lea eax, [edi+8] |
862 | lea eax, [edi+8] |
862 | cmp al, 10h |
863 | cmp al, 10h |
863 | mov ah, 1 |
864 | mov ah, 1 |
864 | jb @f |
865 | jb @f |
865 | add al, 60h |
866 | add al, 60h |
866 | @@: |
867 | @@: |
867 | jmp v86_exc_c.simulate_int |
868 | jmp v86_exc_c.simulate_int |
868 | .notcurrent: |
869 | .notcurrent: |
869 | mov ebx, SLOT_BASE + 0x100 |
870 | mov ebx, SLOT_BASE + 0x100 |
870 | mov ecx, [TASK_COUNT] |
871 | mov ecx, [TASK_COUNT] |
871 | .scan: |
872 | .scan: |
872 | cmp [ebx+APPDATA.dir_table], eax |
873 | cmp [ebx+APPDATA.dir_table], eax |
873 | jnz .cont |
874 | jnz .cont |
874 | push ecx |
875 | push ecx |
875 | mov ecx, [ebx+APPDATA.saved_esp0] |
876 | mov ecx, [ebx+APPDATA.saved_esp0] |
876 | cmp word [ecx-v86_regs.size+v86_regs.esp], 6 |
877 | cmp word [ecx-v86_regs.size+v86_regs.esp], 6 |
877 | jb .cont2 |
878 | jb .cont2 |
878 | movzx edx, word [ecx-v86_regs.size+v86_regs.ss] |
879 | movzx edx, word [ecx-v86_regs.size+v86_regs.ss] |
879 | shl edx, 4 |
880 | shl edx, 4 |
880 | push eax |
881 | push eax |
881 | movzx eax, word [ecx-v86_regs.size+v86_regs.esp] |
882 | movzx eax, word [ecx-v86_regs.size+v86_regs.esp] |
882 | sub eax, 6 |
883 | sub eax, 6 |
883 | add edx, eax |
884 | add edx, eax |
884 | mov eax, edx |
885 | mov eax, edx |
885 | call v86_get_lin_addr |
886 | call v86_get_lin_addr |
886 | cmp eax, 0x1000 |
887 | cmp eax, 0x1000 |
887 | jb .cont3 |
888 | jb .cont3 |
888 | lea eax, [edx+5] |
889 | lea eax, [edx+5] |
889 | call v86_get_lin_addr |
890 | call v86_get_lin_addr |
890 | cmp eax, 0x1000 |
891 | cmp eax, 0x1000 |
891 | jb .cont3 |
892 | jb .cont3 |
892 | pop eax |
893 | pop eax |
893 | pop ecx |
894 | pop ecx |
894 | jmp .found |
895 | jmp .found |
895 | .cont3: |
896 | .cont3: |
896 | pop eax |
897 | pop eax |
897 | .cont2: |
898 | .cont2: |
898 | pop ecx |
899 | pop ecx |
899 | .cont: |
900 | .cont: |
900 | loop .scan |
901 | loop .scan |
901 | mov ecx, edi |
902 | mov ecx, edi |
902 | call irq_eoi |
903 | call irq_eoi |
903 | popad |
904 | popad |
904 | iretd |
905 | iretd |
905 | .found: |
906 | .found: |
906 | mov cr3, eax |
907 | mov cr3, eax |
907 | sub word [esi-v86_regs.size+v86_regs.esp], 6 |
908 | sub word [esi-v86_regs.size+v86_regs.esp], 6 |
908 | mov ecx, [esi-v86_regs.size+v86_regs.eip] |
909 | mov ecx, [esi-v86_regs.size+v86_regs.eip] |
909 | mov word [edx], cx |
910 | mov word [edx], cx |
910 | mov ecx, [esi-v86_regs.size+v86_regs.cs] |
911 | mov ecx, [esi-v86_regs.size+v86_regs.cs] |
911 | mov word [edx+2], cx |
912 | mov word [edx+2], cx |
912 | mov ecx, [esi-v86_regs.size+v86_regs.eflags] |
913 | mov ecx, [esi-v86_regs.size+v86_regs.eflags] |
913 | mov word [edx+4], cx |
914 | mov word [edx+4], cx |
914 | lea eax, [edi+8] |
915 | lea eax, [edi+8] |
915 | cmp al, 10h |
916 | cmp al, 10h |
916 | jb @f |
917 | jb @f |
917 | add al, 60h |
918 | add al, 60h |
918 | @@: |
919 | @@: |
919 | mov cx, [eax*4] |
920 | mov cx, [eax*4] |
920 | mov word [esi-v86_regs.size+v86_regs.eip], cx |
921 | mov word [esi-v86_regs.size+v86_regs.eip], cx |
921 | mov cx, [eax*4+2] |
922 | mov cx, [eax*4+2] |
922 | mov word [esi-v86_regs.size+v86_regs.cs], cx |
923 | mov word [esi-v86_regs.size+v86_regs.cs], cx |
923 | and byte [esi-v86_regs.size+v86_regs.eflags+1], not 3 |
924 | and byte [esi-v86_regs.size+v86_regs.eflags+1], not 3 |
924 | call update_counters |
925 | call update_counters |
925 | lea edi, [ebx + 0x100000000 - SLOT_BASE] |
926 | lea edi, [ebx + 0x100000000 - SLOT_BASE] |
926 | shr edi, 3 |
927 | shr edi, 3 |
927 | add edi, TASK_DATA |
928 | add edi, TASK_DATA |
928 | call find_next_task.found |
929 | call find_next_task.found |
929 | call do_change_task |
930 | call do_change_task |
930 | popad |
931 | popad |
931 | iretd |
932 | iretd |