📄 mmio.c
字号:
rc = __vmx_identity_mapping_load(d, XEN_IA64_OPTF_IDENT_MAP_REG4, &im_load.im_reg4); if (rc) return rc; rc = __vmx_identity_mapping_load(d, XEN_IA64_OPTF_IDENT_MAP_REG5, &im_load.im_reg5); if (rc) return rc; rc = __vmx_identity_mapping_load(d, XEN_IA64_OPTF_IDENT_MAP_REG7, &im_load.im_reg7); return rc;}HVM_REGISTER_SAVE_RESTORE(OPT_FEATURE_IDENTITY_MAPPINGS, vmx_identity_mappings_save, vmx_identity_mappings_load, 1, HVMSR_PER_DOM);static void legacy_io_access(VCPU *vcpu, u64 pa, u64 *val, size_t s, int dir){ struct vcpu *v = current; vcpu_iodata_t *vio; ioreq_t *p; vio = get_vio(v); if (!vio) panic_domain(NULL, "bad shared page\n"); p = &vio->vp_ioreq; p->addr = TO_LEGACY_IO(pa & 0x3ffffffUL); p->size = s; p->count = 1; p->dir = dir; if (dir == IOREQ_WRITE) p->data = *val; else p->data = 0; p->data_is_ptr = 0; p->type = 0; p->df = 0; p->io_count++; if (vmx_ide_pio_intercept(p, val)) return; if (IS_ACPI_ADDR(p->addr) && vacpi_intercept(p, val)) return; vmx_send_assist_req(v); if (dir == IOREQ_READ) { // read *val=p->data; }#ifdef DEBUG_PCI if (dir == IOREQ_WRITE) if (p->addr == 0xcf8UL) printk("Write 0xcf8, with val [0x%lx]\n", p->data); else if (p->addr == 0xcfcUL) printk("Read 0xcfc, with val [0x%lx]\n", p->data);#endif //DEBUG_PCI return;}static void mmio_access(VCPU *vcpu, u64 src_pa, u64 *dest, size_t s, int ma, int dir, u64 iot){ perfc_incra(vmx_mmio_access, iot & 0x7); switch (iot) { case GPFN_PIB: if (ma != 4) panic_domain(NULL, "Access PIB not with UC attribute\n"); if (!dir) vlsapic_write(vcpu, src_pa, s, *dest); else *dest = vlsapic_read(vcpu, src_pa, s); break; case GPFN_IOSAPIC: if (!dir) viosapic_write(vcpu, src_pa, s, *dest); else *dest = viosapic_read(vcpu, src_pa, s); break; case GPFN_FRAME_BUFFER: case GPFN_LOW_MMIO: low_mmio_access(vcpu, src_pa, dest, s, dir); break; case GPFN_LEGACY_IO: legacy_io_access(vcpu, src_pa, dest, s, dir); break; default: panic_domain(NULL,"Bad I/O access\n"); break; } return;}enum inst_type_en { SL_INTEGER, SL_FLOATING, SL_FLOATING_FP8 };/* dir 1: read 0:write */void emulate_io_inst(VCPU *vcpu, u64 padr, u64 ma, u64 iot){ REGS *regs; IA64_BUNDLE bundle; int slot, dir=0; enum inst_type_en inst_type; size_t size; u64 data, data1, temp, update_reg; s32 imm; INST64 inst; unsigned long update_word; regs = vcpu_regs(vcpu); if (IA64_RETRY == __vmx_get_domain_bundle(regs->cr_iip, &bundle)) { /* if fetch code fail, return and try again */ return; } slot = ((struct ia64_psr *)&(regs->cr_ipsr))->ri; if (!slot) inst.inst = bundle.slot0; else if (slot == 1) { u64 slot1b = bundle.slot1b; inst.inst = bundle.slot1a + (slot1b << 18); } else if (slot == 2) inst.inst = bundle.slot2; // Integer Load/Store if (inst.M1.major == 4 && inst.M1.m == 0 && inst.M1.x == 0) { inst_type = SL_INTEGER; size = (inst.M1.x6 & 0x3); if ((inst.M1.x6 >> 2) > 0xb) { dir = IOREQ_WRITE; vcpu_get_gr_nat(vcpu, inst.M4.r2, &data); } else if ((inst.M1.x6 >> 2) < 0xb) { dir = IOREQ_READ; } } // Integer Load + Reg update else if (inst.M2.major == 4 && inst.M2.m == 1 && inst.M2.x == 0) { inst_type = SL_INTEGER; dir = IOREQ_READ; size = (inst.M2.x6 & 0x3); vcpu_get_gr_nat(vcpu, inst.M2.r3, &temp); vcpu_get_gr_nat(vcpu, inst.M2.r2, &update_reg); temp += update_reg; vcpu_set_gr(vcpu, inst.M2.r3, temp, 0); } // Integer Load/Store + Imm update else if (inst.M3.major == 5) { inst_type = SL_INTEGER; size = (inst.M3.x6 & 0x3); if ((inst.M5.x6 >> 2) > 0xb) { dir = IOREQ_WRITE; vcpu_get_gr_nat(vcpu, inst.M5.r2, &data); vcpu_get_gr_nat(vcpu, inst.M5.r3, &temp); imm = (inst.M5.s << 31) | (inst.M5.i << 30) | (inst.M5.imm7 << 23); temp += imm >> 23; vcpu_set_gr(vcpu, inst.M5.r3, temp, 0); } else if ((inst.M3.x6 >> 2) < 0xb) { dir = IOREQ_READ; vcpu_get_gr_nat(vcpu, inst.M3.r3, &temp); imm = (inst.M3.s << 31) | (inst.M3.i << 30) | (inst.M3.imm7 << 23); temp += imm >> 23; vcpu_set_gr(vcpu, inst.M3.r3, temp, 0); } } // Floating-point spill else if (inst.M9.major == 6 && inst.M9.x6 == 0x3B && inst.M9.m == 0 && inst.M9.x == 0) { struct ia64_fpreg v; inst_type = SL_FLOATING; dir = IOREQ_WRITE; vcpu_get_fpreg(vcpu, inst.M9.f2, &v); data1 = v.u.bits[1] & 0x3ffff; data = v.u.bits[0]; size = 4; } // Floating-point spill + Imm update else if (inst.M10.major == 7 && inst.M10.x6 == 0x3B) { struct ia64_fpreg v; inst_type = SL_FLOATING; dir = IOREQ_WRITE; vcpu_get_fpreg(vcpu, inst.M10.f2, &v); vcpu_get_gr_nat(vcpu, inst.M10.r3, &temp); imm = (inst.M10.s << 31) | (inst.M10.i << 30) | (inst.M10.imm7 << 23); temp += imm >> 23; vcpu_set_gr(vcpu, inst.M10.r3, temp, 0); data1 = v.u.bits[1] & 0x3ffff; data = v.u.bits[0]; size = 4; } // Floating-point stf8 + Imm update else if (inst.M10.major == 7 && inst.M10.x6 == 0x31) { struct ia64_fpreg v; inst_type = SL_FLOATING; dir = IOREQ_WRITE; size = 3; vcpu_get_fpreg(vcpu, inst.M10.f2, &v); data = v.u.bits[0]; /* Significand. */ vcpu_get_gr_nat(vcpu, inst.M10.r3, &temp); imm = (inst.M10.s << 31) | (inst.M10.i << 30) | (inst.M10.imm7 << 23); temp += imm >> 23; vcpu_set_gr(vcpu, inst.M10.r3, temp, 0); } // lfetch - do not perform accesses. else if (inst.M15.major== 7 && inst.M15.x6 >=0x2c && inst.M15.x6 <= 0x2f) { vcpu_get_gr_nat(vcpu, inst.M15.r3, &temp); imm = (inst.M15.s << 31) | (inst.M15.i << 30) | (inst.M15.imm7 << 23); temp += imm >> 23; vcpu_set_gr(vcpu, inst.M15.r3, temp, 0); vcpu_increment_iip(vcpu); return; } // Floating-point Load Pair + Imm ldfp8 M12 else if (inst.M12.major == 6 && inst.M12.m == 1 && inst.M12.x == 1 && inst.M12.x6 == 1) { inst_type = SL_FLOATING_FP8; dir = IOREQ_READ; size = 4; //ldfd vcpu_set_gr(vcpu,inst.M12.r3,padr + 16, 0); } else { panic_domain (NULL, "This memory access instr can't be emulated: %lx pc=%lx\n", inst.inst, regs->cr_iip); } update_word = size | (dir << 7) | (ma << 8) | (inst_type << 12); if (dir == IOREQ_READ) { if (inst_type == SL_INTEGER) update_word |= (inst.M1.r1 << 16); else if (inst_type == SL_FLOATING_FP8) update_word |= (inst.M12.f1 << 16) | (inst.M12.f2 << 24); } if (vcpu->domain->arch.is_sioemu) { if (iot != GPFN_PIB && iot != GPFN_IOSAPIC) { sioemu_io_emulate(padr, data, data1, update_word); return; } } if (size == 4) { mmio_access(vcpu, padr + 8, &data1, 1 << 3, ma, dir, iot); size = 3; } mmio_access(vcpu, padr, &data, 1 << size, ma, dir, iot); emulate_io_update(vcpu, update_word, data, data1);}voidemulate_io_update(VCPU *vcpu, u64 word, u64 data, u64 data1){ int dir = (word >> 7) & 1; if (dir == IOREQ_READ) { int r1 = (word >> 16) & 0xff; int r2 = (word >> 24) & 0xff; enum inst_type_en inst_type = (word >> 12) & 0x0f; if (inst_type == SL_INTEGER) { vcpu_set_gr(vcpu, r1, data, 0); } else if (inst_type == SL_FLOATING_FP8) { struct ia64_fpreg v; v.u.bits[0] = data; v.u.bits[1] = 0x1003E; vcpu_set_fpreg(vcpu, r1, &v); v.u.bits[0] = data1; v.u.bits[1] = 0x1003E; vcpu_set_fpreg(vcpu, r2, &v); } else { panic_domain(NULL, "Don't support ldfd now !"); } } vcpu_increment_iip(vcpu);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -