Revision 3ab493de target-i386/helper.c
b/target-i386/helper.c | ||
---|---|---|
1037 | 1037 |
env->tr.selector = selector; |
1038 | 1038 |
} |
1039 | 1039 |
|
1040 |
/* only works if protected mode and not VM86. Calling load_seg with |
|
1041 |
seg_reg == R_CS is discouraged */ |
|
1042 |
/* XXX: add ring level checks */ |
|
1040 |
/* only works if protected mode and not VM86. seg_reg must be != R_CS */ |
|
1043 | 1041 |
void load_seg(int seg_reg, int selector, unsigned int cur_eip) |
1044 | 1042 |
{ |
1045 | 1043 |
uint32_t e1, e2; |
1046 |
|
|
1044 |
int cpl, dpl, rpl; |
|
1045 |
SegmentCache *dt; |
|
1046 |
int index; |
|
1047 |
uint8_t *ptr; |
|
1048 |
|
|
1047 | 1049 |
if ((selector & 0xfffc) == 0) { |
1048 | 1050 |
/* null selector case */ |
1049 | 1051 |
if (seg_reg == R_SS) { |
... | ... | |
1053 | 1055 |
cpu_x86_load_seg_cache(env, seg_reg, selector, NULL, 0, 0); |
1054 | 1056 |
} |
1055 | 1057 |
} else { |
1056 |
if (load_segment(&e1, &e2, selector) != 0) { |
|
1058 |
|
|
1059 |
if (selector & 0x4) |
|
1060 |
dt = &env->ldt; |
|
1061 |
else |
|
1062 |
dt = &env->gdt; |
|
1063 |
index = selector & ~7; |
|
1064 |
if ((index + 7) > dt->limit) { |
|
1057 | 1065 |
EIP = cur_eip; |
1058 | 1066 |
raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
1059 | 1067 |
} |
1060 |
if (!(e2 & DESC_S_MASK) || |
|
1061 |
(e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK) { |
|
1068 |
ptr = dt->base + index; |
|
1069 |
e1 = ldl_kernel(ptr); |
|
1070 |
e2 = ldl_kernel(ptr + 4); |
|
1071 |
|
|
1072 |
if (!(e2 & DESC_S_MASK)) { |
|
1062 | 1073 |
EIP = cur_eip; |
1063 | 1074 |
raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
1064 | 1075 |
} |
1065 |
|
|
1076 |
rpl = selector & 3; |
|
1077 |
dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
|
1078 |
cpl = env->hflags & HF_CPL_MASK; |
|
1066 | 1079 |
if (seg_reg == R_SS) { |
1080 |
/* must be writable segment */ |
|
1067 | 1081 |
if ((e2 & DESC_CS_MASK) || !(e2 & DESC_W_MASK)) { |
1068 | 1082 |
EIP = cur_eip; |
1069 | 1083 |
raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
1070 | 1084 |
} |
1085 |
if (rpl != cpl || dpl != cpl) { |
|
1086 |
EIP = cur_eip; |
|
1087 |
raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
|
1088 |
} |
|
1071 | 1089 |
} else { |
1090 |
/* must be readable segment */ |
|
1072 | 1091 |
if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK) { |
1073 | 1092 |
EIP = cur_eip; |
1074 | 1093 |
raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
1075 | 1094 |
} |
1095 |
|
|
1096 |
if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) { |
|
1097 |
/* if not conforming code, test rights */ |
|
1098 |
if (dpl < cpl || dpl < rpl) { |
|
1099 |
EIP = cur_eip; |
|
1100 |
raise_exception_err(EXCP0D_GPF, selector & 0xfffc); |
|
1101 |
} |
|
1102 |
} |
|
1076 | 1103 |
} |
1077 | 1104 |
|
1078 | 1105 |
if (!(e2 & DESC_P_MASK)) { |
... | ... | |
1082 | 1109 |
else |
1083 | 1110 |
raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc); |
1084 | 1111 |
} |
1112 |
|
|
1113 |
/* set the access bit if not already set */ |
|
1114 |
if (!(e2 & DESC_A_MASK)) { |
|
1115 |
e2 |= DESC_A_MASK; |
|
1116 |
stl_kernel(ptr + 4, e2); |
|
1117 |
} |
|
1118 |
|
|
1085 | 1119 |
cpu_x86_load_seg_cache(env, seg_reg, selector, |
1086 | 1120 |
get_seg_base(e1, e2), |
1087 | 1121 |
get_seg_limit(e1, e2), |
... | ... | |
1696 | 1730 |
{ |
1697 | 1731 |
unsigned int selector, limit; |
1698 | 1732 |
uint32_t e1, e2; |
1733 |
int rpl, dpl, cpl, type; |
|
1699 | 1734 |
|
1700 | 1735 |
CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z; |
1701 | 1736 |
selector = T0 & 0xffff; |
1702 | 1737 |
if (load_segment(&e1, &e2, selector) != 0) |
1703 | 1738 |
return; |
1704 |
limit = (e1 & 0xffff) | (e2 & 0x000f0000); |
|
1705 |
if (e2 & (1 << 23)) |
|
1706 |
limit = (limit << 12) | 0xfff; |
|
1739 |
rpl = selector & 3; |
|
1740 |
dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
|
1741 |
cpl = env->hflags & HF_CPL_MASK; |
|
1742 |
if (e2 & DESC_S_MASK) { |
|
1743 |
if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) { |
|
1744 |
/* conforming */ |
|
1745 |
} else { |
|
1746 |
if (dpl < cpl || dpl < rpl) |
|
1747 |
return; |
|
1748 |
} |
|
1749 |
} else { |
|
1750 |
type = (e2 >> DESC_TYPE_SHIFT) & 0xf; |
|
1751 |
switch(type) { |
|
1752 |
case 1: |
|
1753 |
case 2: |
|
1754 |
case 3: |
|
1755 |
case 9: |
|
1756 |
case 11: |
|
1757 |
break; |
|
1758 |
default: |
|
1759 |
return; |
|
1760 |
} |
|
1761 |
if (dpl < cpl || dpl < rpl) |
|
1762 |
return; |
|
1763 |
} |
|
1764 |
limit = get_seg_limit(e1, e2); |
|
1707 | 1765 |
T1 = limit; |
1708 | 1766 |
CC_SRC |= CC_Z; |
1709 | 1767 |
} |
... | ... | |
1712 | 1770 |
{ |
1713 | 1771 |
unsigned int selector; |
1714 | 1772 |
uint32_t e1, e2; |
1773 |
int rpl, dpl, cpl, type; |
|
1715 | 1774 |
|
1716 | 1775 |
CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z; |
1717 | 1776 |
selector = T0 & 0xffff; |
1777 |
if ((selector & 0xfffc) == 0) |
|
1778 |
return; |
|
1718 | 1779 |
if (load_segment(&e1, &e2, selector) != 0) |
1719 | 1780 |
return; |
1781 |
rpl = selector & 3; |
|
1782 |
dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
|
1783 |
cpl = env->hflags & HF_CPL_MASK; |
|
1784 |
if (e2 & DESC_S_MASK) { |
|
1785 |
if ((e2 & DESC_CS_MASK) && (e2 & DESC_C_MASK)) { |
|
1786 |
/* conforming */ |
|
1787 |
} else { |
|
1788 |
if (dpl < cpl || dpl < rpl) |
|
1789 |
return; |
|
1790 |
} |
|
1791 |
} else { |
|
1792 |
type = (e2 >> DESC_TYPE_SHIFT) & 0xf; |
|
1793 |
switch(type) { |
|
1794 |
case 1: |
|
1795 |
case 2: |
|
1796 |
case 3: |
|
1797 |
case 4: |
|
1798 |
case 5: |
|
1799 |
case 9: |
|
1800 |
case 11: |
|
1801 |
case 12: |
|
1802 |
break; |
|
1803 |
default: |
|
1804 |
return; |
|
1805 |
} |
|
1806 |
if (dpl < cpl || dpl < rpl) |
|
1807 |
return; |
|
1808 |
} |
|
1720 | 1809 |
T1 = e2 & 0x00f0ff00; |
1721 | 1810 |
CC_SRC |= CC_Z; |
1722 | 1811 |
} |
1723 | 1812 |
|
1813 |
void helper_verr(void) |
|
1814 |
{ |
|
1815 |
unsigned int selector; |
|
1816 |
uint32_t e1, e2; |
|
1817 |
int rpl, dpl, cpl; |
|
1818 |
|
|
1819 |
CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z; |
|
1820 |
selector = T0 & 0xffff; |
|
1821 |
if ((selector & 0xfffc) == 0) |
|
1822 |
return; |
|
1823 |
if (load_segment(&e1, &e2, selector) != 0) |
|
1824 |
return; |
|
1825 |
if (!(e2 & DESC_S_MASK)) |
|
1826 |
return; |
|
1827 |
rpl = selector & 3; |
|
1828 |
dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
|
1829 |
cpl = env->hflags & HF_CPL_MASK; |
|
1830 |
if (e2 & DESC_CS_MASK) { |
|
1831 |
if (!(e2 & DESC_R_MASK)) |
|
1832 |
return; |
|
1833 |
if (!(e2 & DESC_C_MASK)) { |
|
1834 |
if (dpl < cpl || dpl < rpl) |
|
1835 |
return; |
|
1836 |
} |
|
1837 |
} else { |
|
1838 |
if (dpl < cpl || dpl < rpl) |
|
1839 |
return; |
|
1840 |
} |
|
1841 |
/* ok */ |
|
1842 |
} |
|
1843 |
|
|
1844 |
void helper_verw(void) |
|
1845 |
{ |
|
1846 |
unsigned int selector; |
|
1847 |
uint32_t e1, e2; |
|
1848 |
int rpl, dpl, cpl; |
|
1849 |
|
|
1850 |
CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z; |
|
1851 |
selector = T0 & 0xffff; |
|
1852 |
if ((selector & 0xfffc) == 0) |
|
1853 |
return; |
|
1854 |
if (load_segment(&e1, &e2, selector) != 0) |
|
1855 |
return; |
|
1856 |
if (!(e2 & DESC_S_MASK)) |
|
1857 |
return; |
|
1858 |
rpl = selector & 3; |
|
1859 |
dpl = (e2 >> DESC_DPL_SHIFT) & 3; |
|
1860 |
cpl = env->hflags & HF_CPL_MASK; |
|
1861 |
if (e2 & DESC_CS_MASK) { |
|
1862 |
return; |
|
1863 |
} else { |
|
1864 |
if (dpl < cpl || dpl < rpl) |
|
1865 |
return; |
|
1866 |
if (!(e2 & DESC_W_MASK)) |
|
1867 |
return; |
|
1868 |
} |
|
1869 |
/* ok */ |
|
1870 |
} |
|
1871 |
|
|
1724 | 1872 |
/* FPU helpers */ |
1725 | 1873 |
|
1726 | 1874 |
void helper_fldt_ST0_A0(void) |
Also available in: Unified diff