Revision 61382a50 target-i386/helper.c
b/target-i386/helper.c | ||
---|---|---|
153 | 153 |
if (index + (4 << shift) - 1 > env->tr.limit) |
154 | 154 |
raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc); |
155 | 155 |
if (shift == 0) { |
156 |
*esp_ptr = lduw(env->tr.base + index); |
|
157 |
*ss_ptr = lduw(env->tr.base + index + 2); |
|
156 |
*esp_ptr = lduw_kernel(env->tr.base + index);
|
|
157 |
*ss_ptr = lduw_kernel(env->tr.base + index + 2);
|
|
158 | 158 |
} else { |
159 |
*esp_ptr = ldl(env->tr.base + index); |
|
160 |
*ss_ptr = lduw(env->tr.base + index + 4); |
|
159 |
*esp_ptr = ldl_kernel(env->tr.base + index);
|
|
160 |
*ss_ptr = lduw_kernel(env->tr.base + index + 4);
|
|
161 | 161 |
} |
162 | 162 |
} |
163 | 163 |
|
... | ... | |
177 | 177 |
if ((index + 7) > dt->limit) |
178 | 178 |
return -1; |
179 | 179 |
ptr = dt->base + index; |
180 |
*e1_ptr = ldl(ptr); |
|
181 |
*e2_ptr = ldl(ptr + 4); |
|
180 |
*e1_ptr = ldl_kernel(ptr);
|
|
181 |
*e2_ptr = ldl_kernel(ptr + 4);
|
|
182 | 182 |
return 0; |
183 | 183 |
} |
184 | 184 |
|
... | ... | |
226 | 226 |
if (intno * 8 + 7 > dt->limit) |
227 | 227 |
raise_exception_err(EXCP0D_GPF, intno * 8 + 2); |
228 | 228 |
ptr = dt->base + intno * 8; |
229 |
e1 = ldl(ptr); |
|
230 |
e2 = ldl(ptr + 4); |
|
229 |
e1 = ldl_kernel(ptr);
|
|
230 |
e2 = ldl_kernel(ptr + 4);
|
|
231 | 231 |
/* check gate type */ |
232 | 232 |
type = (e2 >> DESC_TYPE_SHIFT) & 0x1f; |
233 | 233 |
switch(type) { |
... | ... | |
344 | 344 |
int old_eflags; |
345 | 345 |
if (env->eflags & VM_MASK) { |
346 | 346 |
ssp -= 4; |
347 |
stl(ssp, env->segs[R_GS].selector); |
|
347 |
stl_kernel(ssp, env->segs[R_GS].selector);
|
|
348 | 348 |
ssp -= 4; |
349 |
stl(ssp, env->segs[R_FS].selector); |
|
349 |
stl_kernel(ssp, env->segs[R_FS].selector);
|
|
350 | 350 |
ssp -= 4; |
351 |
stl(ssp, env->segs[R_DS].selector); |
|
351 |
stl_kernel(ssp, env->segs[R_DS].selector);
|
|
352 | 352 |
ssp -= 4; |
353 |
stl(ssp, env->segs[R_ES].selector); |
|
353 |
stl_kernel(ssp, env->segs[R_ES].selector);
|
|
354 | 354 |
} |
355 | 355 |
if (new_stack) { |
356 | 356 |
ssp -= 4; |
357 |
stl(ssp, old_ss); |
|
357 |
stl_kernel(ssp, old_ss);
|
|
358 | 358 |
ssp -= 4; |
359 |
stl(ssp, old_esp); |
|
359 |
stl_kernel(ssp, old_esp);
|
|
360 | 360 |
} |
361 | 361 |
ssp -= 4; |
362 | 362 |
old_eflags = compute_eflags(); |
363 |
stl(ssp, old_eflags); |
|
363 |
stl_kernel(ssp, old_eflags);
|
|
364 | 364 |
ssp -= 4; |
365 |
stl(ssp, old_cs); |
|
365 |
stl_kernel(ssp, old_cs);
|
|
366 | 366 |
ssp -= 4; |
367 |
stl(ssp, old_eip); |
|
367 |
stl_kernel(ssp, old_eip);
|
|
368 | 368 |
if (has_error_code) { |
369 | 369 |
ssp -= 4; |
370 |
stl(ssp, error_code); |
|
370 |
stl_kernel(ssp, error_code);
|
|
371 | 371 |
} |
372 | 372 |
} else { |
373 | 373 |
if (new_stack) { |
374 | 374 |
ssp -= 2; |
375 |
stw(ssp, old_ss); |
|
375 |
stw_kernel(ssp, old_ss);
|
|
376 | 376 |
ssp -= 2; |
377 |
stw(ssp, old_esp); |
|
377 |
stw_kernel(ssp, old_esp);
|
|
378 | 378 |
} |
379 | 379 |
ssp -= 2; |
380 |
stw(ssp, compute_eflags()); |
|
380 |
stw_kernel(ssp, compute_eflags());
|
|
381 | 381 |
ssp -= 2; |
382 |
stw(ssp, old_cs); |
|
382 |
stw_kernel(ssp, old_cs);
|
|
383 | 383 |
ssp -= 2; |
384 |
stw(ssp, old_eip); |
|
384 |
stw_kernel(ssp, old_eip);
|
|
385 | 385 |
if (has_error_code) { |
386 | 386 |
ssp -= 2; |
387 |
stw(ssp, error_code); |
|
387 |
stw_kernel(ssp, error_code);
|
|
388 | 388 |
} |
389 | 389 |
} |
390 | 390 |
|
... | ... | |
410 | 410 |
if (intno * 4 + 3 > dt->limit) |
411 | 411 |
raise_exception_err(EXCP0D_GPF, intno * 8 + 2); |
412 | 412 |
ptr = dt->base + intno * 4; |
413 |
offset = lduw(ptr); |
|
414 |
selector = lduw(ptr + 2); |
|
413 |
offset = lduw_kernel(ptr);
|
|
414 |
selector = lduw_kernel(ptr + 2);
|
|
415 | 415 |
esp = ESP; |
416 | 416 |
ssp = env->segs[R_SS].base; |
417 | 417 |
if (is_int) |
... | ... | |
420 | 420 |
old_eip = env->eip; |
421 | 421 |
old_cs = env->segs[R_CS].selector; |
422 | 422 |
esp -= 2; |
423 |
stw(ssp + (esp & 0xffff), compute_eflags()); |
|
423 |
stw_kernel(ssp + (esp & 0xffff), compute_eflags());
|
|
424 | 424 |
esp -= 2; |
425 |
stw(ssp + (esp & 0xffff), old_cs); |
|
425 |
stw_kernel(ssp + (esp & 0xffff), old_cs);
|
|
426 | 426 |
esp -= 2; |
427 |
stw(ssp + (esp & 0xffff), old_eip); |
|
427 |
stw_kernel(ssp + (esp & 0xffff), old_eip);
|
|
428 | 428 |
|
429 | 429 |
/* update processor state */ |
430 | 430 |
ESP = (ESP & ~0xffff) | (esp & 0xffff); |
... | ... | |
445 | 445 |
|
446 | 446 |
dt = &env->idt; |
447 | 447 |
ptr = dt->base + (intno * 8); |
448 |
e2 = ldl(ptr + 4); |
|
448 |
e2 = ldl_kernel(ptr + 4);
|
|
449 | 449 |
|
450 | 450 |
dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
451 | 451 |
cpl = env->hflags & HF_CPL_MASK; |
... | ... | |
651 | 651 |
if ((index + 7) > dt->limit) |
652 | 652 |
raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
653 | 653 |
ptr = dt->base + index; |
654 |
e1 = ldl(ptr); |
|
655 |
e2 = ldl(ptr + 4); |
|
654 |
e1 = ldl_kernel(ptr);
|
|
655 |
e2 = ldl_kernel(ptr + 4);
|
|
656 | 656 |
if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2) |
657 | 657 |
raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
658 | 658 |
if (!(e2 & DESC_P_MASK)) |
... | ... | |
684 | 684 |
if ((index + 7) > dt->limit) |
685 | 685 |
raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
686 | 686 |
ptr = dt->base + index; |
687 |
e1 = ldl(ptr); |
|
688 |
e2 = ldl(ptr + 4); |
|
687 |
e1 = ldl_kernel(ptr);
|
|
688 |
e2 = ldl_kernel(ptr + 4);
|
|
689 | 689 |
type = (e2 >> DESC_TYPE_SHIFT) & 0xf; |
690 | 690 |
if ((e2 & DESC_S_MASK) || |
691 | 691 |
(type != 2 && type != 9)) |
... | ... | |
694 | 694 |
raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); |
695 | 695 |
load_seg_cache_raw_dt(&env->tr, e1, e2); |
696 | 696 |
e2 |= 0x00000200; /* set the busy bit */ |
697 |
stl(ptr + 4, e2); |
|
697 |
stl_kernel(ptr + 4, e2);
|
|
698 | 698 |
} |
699 | 699 |
env->tr.selector = selector; |
700 | 700 |
} |
... | ... | |
813 | 813 |
ssp = env->segs[R_SS].base; |
814 | 814 |
if (shift) { |
815 | 815 |
esp -= 4; |
816 |
stl(ssp + (esp & esp_mask), env->segs[R_CS].selector); |
|
816 |
stl_kernel(ssp + (esp & esp_mask), env->segs[R_CS].selector);
|
|
817 | 817 |
esp -= 4; |
818 |
stl(ssp + (esp & esp_mask), next_eip); |
|
818 |
stl_kernel(ssp + (esp & esp_mask), next_eip);
|
|
819 | 819 |
} else { |
820 | 820 |
esp -= 2; |
821 |
stw(ssp + (esp & esp_mask), env->segs[R_CS].selector); |
|
821 |
stw_kernel(ssp + (esp & esp_mask), env->segs[R_CS].selector);
|
|
822 | 822 |
esp -= 2; |
823 |
stw(ssp + (esp & esp_mask), next_eip); |
|
823 |
stw_kernel(ssp + (esp & esp_mask), next_eip);
|
|
824 | 824 |
} |
825 | 825 |
|
826 | 826 |
if (!(env->segs[R_SS].flags & DESC_B_MASK)) |
... | ... | |
873 | 873 |
ssp = env->segs[R_SS].base + sp; |
874 | 874 |
if (shift) { |
875 | 875 |
ssp -= 4; |
876 |
stl(ssp, env->segs[R_CS].selector); |
|
876 |
stl_kernel(ssp, env->segs[R_CS].selector);
|
|
877 | 877 |
ssp -= 4; |
878 |
stl(ssp, next_eip); |
|
878 |
stl_kernel(ssp, next_eip);
|
|
879 | 879 |
} else { |
880 | 880 |
ssp -= 2; |
881 |
stw(ssp, env->segs[R_CS].selector); |
|
881 |
stw_kernel(ssp, env->segs[R_CS].selector);
|
|
882 | 882 |
ssp -= 2; |
883 |
stw(ssp, next_eip); |
|
883 |
stw_kernel(ssp, next_eip);
|
|
884 | 884 |
} |
885 | 885 |
sp -= (4 << shift); |
886 | 886 |
|
... | ... | |
975 | 975 |
ssp = env->segs[R_SS].base + sp; |
976 | 976 |
if (shift) { |
977 | 977 |
ssp -= 4; |
978 |
stl(ssp, old_ss); |
|
978 |
stl_kernel(ssp, old_ss);
|
|
979 | 979 |
ssp -= 4; |
980 |
stl(ssp, old_esp); |
|
980 |
stl_kernel(ssp, old_esp);
|
|
981 | 981 |
ssp -= 4 * param_count; |
982 | 982 |
for(i = 0; i < param_count; i++) { |
983 |
val = ldl(old_ssp + i * 4); |
|
984 |
stl(ssp + i * 4, val); |
|
983 |
val = ldl_kernel(old_ssp + i * 4);
|
|
984 |
stl_kernel(ssp + i * 4, val);
|
|
985 | 985 |
} |
986 | 986 |
} else { |
987 | 987 |
ssp -= 2; |
988 |
stw(ssp, old_ss); |
|
988 |
stw_kernel(ssp, old_ss);
|
|
989 | 989 |
ssp -= 2; |
990 |
stw(ssp, old_esp); |
|
990 |
stw_kernel(ssp, old_esp);
|
|
991 | 991 |
ssp -= 2 * param_count; |
992 | 992 |
for(i = 0; i < param_count; i++) { |
993 |
val = lduw(old_ssp + i * 2); |
|
994 |
stw(ssp + i * 2, val); |
|
993 |
val = lduw_kernel(old_ssp + i * 2);
|
|
994 |
stw_kernel(ssp + i * 2, val);
|
|
995 | 995 |
} |
996 | 996 |
} |
997 | 997 |
} else { |
... | ... | |
1004 | 1004 |
|
1005 | 1005 |
if (shift) { |
1006 | 1006 |
ssp -= 4; |
1007 |
stl(ssp, env->segs[R_CS].selector); |
|
1007 |
stl_kernel(ssp, env->segs[R_CS].selector);
|
|
1008 | 1008 |
ssp -= 4; |
1009 |
stl(ssp, next_eip); |
|
1009 |
stl_kernel(ssp, next_eip);
|
|
1010 | 1010 |
} else { |
1011 | 1011 |
ssp -= 2; |
1012 |
stw(ssp, env->segs[R_CS].selector); |
|
1012 |
stw_kernel(ssp, env->segs[R_CS].selector);
|
|
1013 | 1013 |
ssp -= 2; |
1014 |
stw(ssp, next_eip); |
|
1014 |
stw_kernel(ssp, next_eip);
|
|
1015 | 1015 |
} |
1016 | 1016 |
|
1017 | 1017 |
sp -= push_size; |
... | ... | |
1042 | 1042 |
ssp = env->segs[R_SS].base + sp; |
1043 | 1043 |
if (shift == 1) { |
1044 | 1044 |
/* 32 bits */ |
1045 |
new_eflags = ldl(ssp + 8); |
|
1046 |
new_cs = ldl(ssp + 4) & 0xffff; |
|
1047 |
new_eip = ldl(ssp) & 0xffff; |
|
1045 |
new_eflags = ldl_kernel(ssp + 8);
|
|
1046 |
new_cs = ldl_kernel(ssp + 4) & 0xffff;
|
|
1047 |
new_eip = ldl_kernel(ssp) & 0xffff;
|
|
1048 | 1048 |
} else { |
1049 | 1049 |
/* 16 bits */ |
1050 |
new_eflags = lduw(ssp + 4); |
|
1051 |
new_cs = lduw(ssp + 2); |
|
1052 |
new_eip = lduw(ssp); |
|
1050 |
new_eflags = lduw_kernel(ssp + 4);
|
|
1051 |
new_cs = lduw_kernel(ssp + 2);
|
|
1052 |
new_eip = lduw_kernel(ssp);
|
|
1053 | 1053 |
} |
1054 | 1054 |
new_esp = sp + (6 << shift); |
1055 | 1055 |
ESP = (ESP & 0xffff0000) | |
... | ... | |
1078 | 1078 |
if (shift == 1) { |
1079 | 1079 |
/* 32 bits */ |
1080 | 1080 |
if (is_iret) |
1081 |
new_eflags = ldl(ssp + 8); |
|
1082 |
new_cs = ldl(ssp + 4) & 0xffff; |
|
1083 |
new_eip = ldl(ssp); |
|
1081 |
new_eflags = ldl_kernel(ssp + 8);
|
|
1082 |
new_cs = ldl_kernel(ssp + 4) & 0xffff;
|
|
1083 |
new_eip = ldl_kernel(ssp);
|
|
1084 | 1084 |
if (is_iret && (new_eflags & VM_MASK)) |
1085 | 1085 |
goto return_to_vm86; |
1086 | 1086 |
} else { |
1087 | 1087 |
/* 16 bits */ |
1088 | 1088 |
if (is_iret) |
1089 |
new_eflags = lduw(ssp + 4); |
|
1090 |
new_cs = lduw(ssp + 2); |
|
1091 |
new_eip = lduw(ssp); |
|
1089 |
new_eflags = lduw_kernel(ssp + 4);
|
|
1090 |
new_cs = lduw_kernel(ssp + 2);
|
|
1091 |
new_eip = lduw_kernel(ssp);
|
|
1092 | 1092 |
} |
1093 | 1093 |
if ((new_cs & 0xfffc) == 0) |
1094 | 1094 |
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc); |
... | ... | |
1124 | 1124 |
ssp += (4 << shift) + ((2 * is_iret) << shift) + addend; |
1125 | 1125 |
if (shift == 1) { |
1126 | 1126 |
/* 32 bits */ |
1127 |
new_esp = ldl(ssp); |
|
1128 |
new_ss = ldl(ssp + 4) & 0xffff; |
|
1127 |
new_esp = ldl_kernel(ssp);
|
|
1128 |
new_ss = ldl_kernel(ssp + 4) & 0xffff;
|
|
1129 | 1129 |
} else { |
1130 | 1130 |
/* 16 bits */ |
1131 |
new_esp = lduw(ssp); |
|
1132 |
new_ss = lduw(ssp + 2); |
|
1131 |
new_esp = lduw_kernel(ssp);
|
|
1132 |
new_ss = lduw_kernel(ssp + 2);
|
|
1133 | 1133 |
} |
1134 | 1134 |
|
1135 | 1135 |
if ((new_ss & 3) != rpl) |
... | ... | |
1175 | 1175 |
return; |
1176 | 1176 |
|
1177 | 1177 |
return_to_vm86: |
1178 |
new_esp = ldl(ssp + 12); |
|
1179 |
new_ss = ldl(ssp + 16); |
|
1180 |
new_es = ldl(ssp + 20); |
|
1181 |
new_ds = ldl(ssp + 24); |
|
1182 |
new_fs = ldl(ssp + 28); |
|
1183 |
new_gs = ldl(ssp + 32); |
|
1178 |
new_esp = ldl_kernel(ssp + 12);
|
|
1179 |
new_ss = ldl_kernel(ssp + 16);
|
|
1180 |
new_es = ldl_kernel(ssp + 20);
|
|
1181 |
new_ds = ldl_kernel(ssp + 24);
|
|
1182 |
new_fs = ldl_kernel(ssp + 28);
|
|
1183 |
new_gs = ldl_kernel(ssp + 32);
|
|
1184 | 1184 |
|
1185 | 1185 |
/* modify processor state */ |
1186 | 1186 |
load_eflags(new_eflags, FL_UPDATE_CPL0_MASK | VM_MASK | VIF_MASK | VIP_MASK); |
... | ... | |
1770 | 1770 |
} |
1771 | 1771 |
} |
1772 | 1772 |
|
1773 |
#if !defined(CONFIG_USER_ONLY) |
|
1774 |
|
|
1775 |
#define MMUSUFFIX _mmu |
|
1776 |
#define GETPC() (__builtin_return_address(0)) |
|
1777 |
|
|
1773 | 1778 |
#define SHIFT 0 |
1774 | 1779 |
#include "softmmu_template.h" |
1775 | 1780 |
|
... | ... | |
1782 | 1787 |
#define SHIFT 3 |
1783 | 1788 |
#include "softmmu_template.h" |
1784 | 1789 |
|
1785 |
/* try to fill the TLB and return an exception if error */ |
|
1786 |
void tlb_fill(unsigned long addr, int is_write, void *retaddr) |
|
1790 |
#endif |
|
1791 |
|
|
1792 |
/* try to fill the TLB and return an exception if error. If retaddr is |
|
1793 |
NULL, it means that the function was called in C code (i.e. not |
|
1794 |
from generated code or from helper.c) */ |
|
1795 |
/* XXX: fix it to restore all registers */ |
|
1796 |
void tlb_fill(unsigned long addr, int is_write, int is_user, void *retaddr) |
|
1787 | 1797 |
{ |
1788 | 1798 |
TranslationBlock *tb; |
1789 | 1799 |
int ret; |
1790 | 1800 |
unsigned long pc; |
1791 |
ret = cpu_x86_handle_mmu_fault(env, addr, is_write); |
|
1801 |
CPUX86State *saved_env; |
|
1802 |
|
|
1803 |
/* XXX: hack to restore env in all cases, even if not called from |
|
1804 |
generated code */ |
|
1805 |
saved_env = env; |
|
1806 |
env = cpu_single_env; |
|
1807 |
if (is_write && page_unprotect(addr)) { |
|
1808 |
/* nothing more to do: the page was write protected because |
|
1809 |
there was code in it. page_unprotect() flushed the code. */ |
|
1810 |
} |
|
1811 |
|
|
1812 |
ret = cpu_x86_handle_mmu_fault(env, addr, is_write, is_user, 1); |
|
1792 | 1813 |
if (ret) { |
1793 |
/* now we have a real cpu fault */ |
|
1794 |
pc = (unsigned long)retaddr; |
|
1795 |
tb = tb_find_pc(pc); |
|
1796 |
if (tb) { |
|
1797 |
/* the PC is inside the translated code. It means that we have |
|
1798 |
a virtual CPU fault */ |
|
1799 |
cpu_restore_state(tb, env, pc); |
|
1814 |
if (retaddr) { |
|
1815 |
/* now we have a real cpu fault */ |
|
1816 |
pc = (unsigned long)retaddr; |
|
1817 |
tb = tb_find_pc(pc); |
|
1818 |
if (tb) { |
|
1819 |
/* the PC is inside the translated code. It means that we have |
|
1820 |
a virtual CPU fault */ |
|
1821 |
cpu_restore_state(tb, env, pc); |
|
1822 |
} |
|
1800 | 1823 |
} |
1801 | 1824 |
raise_exception_err(EXCP0E_PAGE, env->error_code); |
1802 | 1825 |
} |
1826 |
env = saved_env; |
|
1803 | 1827 |
} |
Also available in: Unified diff