| version 1.10, 2004/02/06 16:49:51 | version 1.14, 2004/03/02 16:29:16 | 
| Line 33 | Line 33 | 
 |  |  | 
 |  |  | 
 | void | void | 
| load_tr(WORD selector) | load_tr(UINT16 selector) | 
 | { | { | 
 | selector_t task_sel; | selector_t task_sel; | 
 | int rv; | int rv; | 
 |  | UINT16 iobase; | 
 |  |  | 
 | rv = parse_selector(&task_sel, selector); | rv = parse_selector(&task_sel, selector); | 
 | if (rv < 0 || task_sel.ldt || task_sel.desc.s) { | if (rv < 0 || task_sel.ldt || task_sel.desc.s) { | 
| Line 49  load_tr(WORD selector) | Line 50  load_tr(WORD selector) | 
 | if (task_sel.desc.u.seg.limit < 0x2b) { | if (task_sel.desc.u.seg.limit < 0x2b) { | 
 | EXCEPTION(TS_EXCEPTION, task_sel.idx); | EXCEPTION(TS_EXCEPTION, task_sel.idx); | 
 | } | } | 
 |  | iobase = 0; | 
 | break; | break; | 
 |  |  | 
 | case CPU_SYSDESC_TYPE_TSS_32: | case CPU_SYSDESC_TYPE_TSS_32: | 
 | if (task_sel.desc.u.seg.limit < 0x67) { | if (task_sel.desc.u.seg.limit < 0x67) { | 
 | EXCEPTION(TS_EXCEPTION, task_sel.idx); | EXCEPTION(TS_EXCEPTION, task_sel.idx); | 
 | } | } | 
 |  | iobase = cpu_kmemoryread_w(task_sel.desc.u.seg.segbase + 102); | 
 | break; | break; | 
 |  |  | 
 | default: | default: | 
| Line 75  load_tr(WORD selector) | Line 78  load_tr(WORD selector) | 
 | CPU_SET_TASK_BUSY(task_sel.selector, &task_sel.desc); | CPU_SET_TASK_BUSY(task_sel.selector, &task_sel.desc); | 
 | CPU_TR = task_sel.selector; | CPU_TR = task_sel.selector; | 
 | CPU_TR_DESC = task_sel.desc; | CPU_TR_DESC = task_sel.desc; | 
 |  |  | 
 |  | /* I/O deny bitmap */ | 
 |  | if (task_sel.desc.type == CPU_SYSDESC_TYPE_TSS_BUSY_32) { | 
 |  | if (iobase != 0 && iobase < task_sel.desc.u.seg.limit) { | 
 |  | CPU_STAT_IOLIMIT = (UINT16)(task_sel.desc.u.seg.limit - iobase); | 
 |  | CPU_STAT_IOADDR = task_sel.desc.u.seg.segbase + iobase; | 
 |  | } else { | 
 |  | CPU_STAT_IOLIMIT = 0; | 
 |  | } | 
 |  | } else { | 
 |  | CPU_STAT_IOLIMIT = 0; | 
 |  | } | 
 | } | } | 
 |  |  | 
 | void | void | 
| get_stack_from_tss(DWORD pl, WORD *new_ss, DWORD *new_esp) | get_stack_pointer_from_tss(UINT pl, UINT16 *new_ss, UINT32 *new_esp) | 
 | { | { | 
| DWORD tss_stack_addr; | UINT32 tss_stack_addr; | 
 |  |  | 
 | __ASSERT(pl < 3); | __ASSERT(pl < 3); | 
 |  |  | 
| Line 101  get_stack_from_tss(DWORD pl, WORD *new_s | Line 116  get_stack_from_tss(DWORD pl, WORD *new_s | 
 | *new_esp = cpu_kmemoryread_w(tss_stack_addr); | *new_esp = cpu_kmemoryread_w(tss_stack_addr); | 
 | *new_ss = cpu_kmemoryread_w(tss_stack_addr + 2); | *new_ss = cpu_kmemoryread_w(tss_stack_addr + 2); | 
 | } else { | } else { | 
| ia32_panic("get_stack_from_tss: task register is invalid (%d)\n", CPU_TR_DESC.type); | ia32_panic("get_stack_pointer_from_tss: task register is invalid (%d)\n", CPU_TR_DESC.type); | 
 | } | } | 
 |  |  | 
| VERBOSE(("get_stack_from_tss: pl = %d, new_esp = 0x%08x, new_ss = 0x%04x", pl, *new_esp, *new_ss)); | VERBOSE(("get_stack_pointer_from_tss: pl = %d, new_esp = 0x%08x, new_ss = 0x%04x", pl, *new_esp, *new_ss)); | 
 | } | } | 
 |  |  | 
| WORD | UINT16 | 
| get_link_selector_from_tss() | get_backlink_selector_from_tss(void) | 
 | { | { | 
| WORD backlink; | UINT16 backlink; | 
 |  |  | 
 | if (CPU_TR_DESC.type == CPU_SYSDESC_TYPE_TSS_BUSY_32) { | if (CPU_TR_DESC.type == CPU_SYSDESC_TYPE_TSS_BUSY_32) { | 
 | if (4 > CPU_TR_DESC.u.seg.limit) { | if (4 > CPU_TR_DESC.u.seg.limit) { | 
| Line 121  get_link_selector_from_tss() | Line 136  get_link_selector_from_tss() | 
 | EXCEPTION(TS_EXCEPTION, CPU_TR & ~3); | EXCEPTION(TS_EXCEPTION, CPU_TR & ~3); | 
 | } | } | 
 | } else { | } else { | 
| ia32_panic("get_link_selector_from_tss: task register is invalid (%d)\n", CPU_TR_DESC.type); | ia32_panic("get_backlink_selector_from_tss: task register is invalid (%d)\n", CPU_TR_DESC.type); | 
 | } | } | 
 |  |  | 
 | backlink = cpu_kmemoryread_w(CPU_TR_DESC.u.seg.segbase); | backlink = cpu_kmemoryread_w(CPU_TR_DESC.u.seg.segbase); | 
| VERBOSE(("get_link_selector_from_tss: backlink selector = 0x%04x", backlink)); | VERBOSE(("get_backlink_selector_from_tss: backlink selector = 0x%04x", backlink)); | 
 | return backlink; | return backlink; | 
 | } | } | 
 |  |  | 
 | void | void | 
| task_switch(selector_t* task_sel, int type) | task_switch(selector_t *task_sel, task_switch_type_t type) | 
 | { | { | 
| DWORD regs[CPU_REG_NUM]; | UINT32 regs[CPU_REG_NUM]; | 
| DWORD eip; | UINT32 eip; | 
| DWORD new_flags; | UINT32 new_flags; | 
| DWORD mask; | UINT32 mask; | 
| DWORD cr3 = 0; | UINT32 cr3 = 0; | 
| WORD sreg[CPU_SEGREG_NUM]; | UINT16 sreg[CPU_SEGREG_NUM]; | 
| WORD ldtr; | UINT16 ldtr; | 
| WORD t, iobase; | UINT16 t, iobase; | 
 |  |  | 
 | selector_t cs_sel; | selector_t cs_sel; | 
 | int rv; | int rv; | 
 |  |  | 
| DWORD cur_base;         /* current task state */ | UINT32 cur_base;        /* current task state */ | 
| DWORD task_base;        /* new task state */ | UINT32 task_base;       /* new task state */ | 
| DWORD old_flags = REAL_EFLAGREG; | UINT32 old_flags = REAL_EFLAGREG; | 
 | BOOL task16; | BOOL task16; | 
| DWORD nsreg; | UINT nsreg; | 
| DWORD i; | UINT i; | 
 |  |  | 
 | VERBOSE(("task_switch: start")); | VERBOSE(("task_switch: start")); | 
 |  |  | 
| Line 188  task_switch(selector_t* task_sel, int ty | Line 203  task_switch(selector_t* task_sel, int ty | 
 |  |  | 
 | #if defined(MORE_DEBUG) | #if defined(MORE_DEBUG) | 
 | { | { | 
| DWORD v; | UINT32 v; | 
 |  |  | 
 | VERBOSE(("task_switch: new task")); | VERBOSE(("task_switch: new task")); | 
 | for (i = 0; i < task_sel->desc.u.seg.limit; i += 4) { | for (i = 0; i < task_sel->desc.u.seg.limit; i += 4) { | 
| Line 300  task_switch(selector_t* task_sel, int ty | Line 315  task_switch(selector_t* task_sel, int ty | 
 | } | } | 
 | } else { | } else { | 
 | cpu_kmemorywrite_w(cur_base + 14, CPU_IP); | cpu_kmemorywrite_w(cur_base + 14, CPU_IP); | 
| cpu_kmemorywrite_w(cur_base + 16, (WORD)old_flags); | cpu_kmemorywrite_w(cur_base + 16, (UINT16)old_flags); | 
 | for (i = 0; i < CPU_REG_NUM; i++) { | for (i = 0; i < CPU_REG_NUM; i++) { | 
 | cpu_kmemorywrite_w(cur_base + 18 + i * 2, CPU_REGS_WORD(i)); | cpu_kmemorywrite_w(cur_base + 18 + i * 2, CPU_REGS_WORD(i)); | 
 | } | } | 
| Line 311  task_switch(selector_t* task_sel, int ty | Line 326  task_switch(selector_t* task_sel, int ty | 
 |  |  | 
 | #if defined(MORE_DEBUG) | #if defined(MORE_DEBUG) | 
 | { | { | 
| DWORD v; | UINT32 v; | 
 |  |  | 
 | VERBOSE(("task_switch: current task")); | VERBOSE(("task_switch: current task")); | 
 | for (i = 0; i < CPU_TR_DESC.u.seg.limit; i += 4) { | for (i = 0; i < CPU_TR_DESC.u.seg.limit; i += 4) { | 
| Line 355  task_switch(selector_t* task_sel, int ty | Line 370  task_switch(selector_t* task_sel, int ty | 
 | case TASK_SWITCH_IRET: | case TASK_SWITCH_IRET: | 
 | /* check busy flag is active */ | /* check busy flag is active */ | 
 | if (task_sel->desc.valid) { | if (task_sel->desc.valid) { | 
| DWORD h; | UINT32 h; | 
 | h = cpu_kmemoryread_d(task_sel->addr + 4); | h = cpu_kmemoryread_d(task_sel->addr + 4); | 
 | if ((h & CPU_TSS_H_BUSY) == 0) { | if ((h & CPU_TSS_H_BUSY) == 0) { | 
 | ia32_panic("task_switch: new task is not busy"); | ia32_panic("task_switch: new task is not busy"); | 
| Line 394  task_switch(selector_t* task_sel, int ty | Line 409  task_switch(selector_t* task_sel, int ty | 
 |  |  | 
 | /* set new EFLAGS */ | /* set new EFLAGS */ | 
 | mask = I_FLAG|IOPL_FLAG|RF_FLAG|VM_FLAG|VIF_FLAG|VIP_FLAG; | mask = I_FLAG|IOPL_FLAG|RF_FLAG|VM_FLAG|VIF_FLAG|VIP_FLAG; | 
| if (!task16) { | set_eflags(new_flags, mask); | 
| set_eflags(new_flags, mask); |  | 
| } else { |  | 
| set_flags(new_flags, mask); |  | 
| } |  | 
 |  |  | 
 | /* load new LDTR */ | /* load new LDTR */ | 
 | load_ldtr(ldtr, TS_EXCEPTION); | load_ldtr(ldtr, TS_EXCEPTION); | 
| Line 454  task_switch(selector_t* task_sel, int ty | Line 465  task_switch(selector_t* task_sel, int ty | 
 |  |  | 
 | /* I/O deny bitmap */ | /* I/O deny bitmap */ | 
 | if (!task16) { | if (!task16) { | 
| if (task_sel->desc.u.seg.limit > iobase) { | if (iobase != 0 && iobase < task_sel->desc.u.seg.limit) { | 
| CPU_STAT_IOLIMIT = task_sel->desc.u.seg.limit - iobase; | CPU_STAT_IOLIMIT = (UINT16)(task_sel->desc.u.seg.limit - iobase); | 
 | CPU_STAT_IOADDR = task_sel->desc.u.seg.segbase + iobase; | CPU_STAT_IOADDR = task_sel->desc.u.seg.segbase + iobase; | 
 | } else { | } else { | 
 | CPU_STAT_IOLIMIT = 0; | CPU_STAT_IOLIMIT = 0; |