uint32_t swaddr_read(swaddr_t addr, size_t len, uint8_t sreg) { #ifdef DEBUG assert(len == 1 || len == 2 || len == 4); #endif #ifdef SEGMENTATION if (cpu.cr0.protect_enable) addr = seg_translate(addr, sreg); #endif return lnaddr_read(addr, len); }
void load_sreg(uint32_t sreg) { uint8_t tmp[8]; int i; for(i = 0; i < 8; ++ i) tmp[i] = lnaddr_read(cpu.GDTR.base + cpu.sr[sreg].index * 8 + i, 1); SegDesc *segdesc = (SegDesc*)tmp; Assert(segdesc->present == 1, "Segdesc is not valid! 0x%x", cpu.GDTR.base + cpu.sr[sreg].index * 8); Assert(cpu.sr[sreg].index * 8 < (segdesc->limit_19_16 << 16) + segdesc->limit_15_0, "Segment overflow!"); cpu.sr[sreg].invi = *segdesc; }
lnaddr_t seg_translate(swaddr_t swaddr, uint8_t sreg) { // Log("swaddr = 0x%x", swaddr); Assert(cpu.cr0.protect_enable, "CR0 protect enable bit is not set!"); // Log("segment"); uint32_t segdesc_addr = cpu.gdtr.base + SREG(sreg).index; // Log("addr = 0x%x", segdesc_addr); SegDesc *segdesc = (SegDesc *)malloc(sizeof(SegDesc)); segdesc->val[0] = lnaddr_read(segdesc_addr, 4); segdesc->val[1] = lnaddr_read(segdesc_addr + 4, 4); // int i; // for(i = 0; i < 2; ++i) // Log("segdesc: 0x%08x", segdesc->val[i]); uint32_t lnaddr = swaddr + (segdesc->base_31_24 << 24) + (segdesc->base_23_16 << 16) + segdesc->base_15_0; // Log("lnaddr = 0x%x", lnaddr); // Assert(swaddr == lnaddr, "swaddr == lnaddr"); return lnaddr; }
void raise_intr(uint8_t NO) { /* TODO: Trigger an interrupt/exception with ``NO''. * That is, use ``NO'' to index the IDT. */ push(cpu.EFLAGS.eflags); push(cpu.CS.Selector.val); push(cpu.eip); GateDesc gd; int i; for (i = 0; i < sizeof(GateDesc); i++){ *((uint8_t*)(&gd)+i) = lnaddr_read(cpu.idtr.base+NO*sizeof(GateDesc)+i, 1); } cpu.CS.Selector.val = gd.segment; cpu.CS.valid = false; swaddr_t addr = (gd.offset_31_16<<16) | gd.offset_15_0; cpu.eip = addr; /* Jump back to cpu_exec() */ longjmp(jbuf, 1); }