hi, qemu develops: recently I am trying to accomplish x86 user interrupt feature in qemu. but I face some problem when accomplish this. the main problem is the interrupt recognize and return form interrupt. my repositories is here https://github.com/Xiang-cd/qemu my accomplishment of recognize interrupt is that: // target/i386/tcg/seg_helper.c static void do_interrupt64(
if(intno==UINTR_UINV ){ if(env->uintr_uif==0){ return; } intprot; CPUState*cs=env_cpu(env); uint64_tupid_phyaddress=get_hphys2(cs, env->uintr_pd, MMU_DATA_LOAD, &prot); uintr_upidupid; cpu_physical_memory_rw(upid_phyaddress, &upid, 16, false); upid.nc.status&= (~1); // clear on if(upid.puir!=0){ env->uintr_rr=upid.puir; upid.puir=0; // clear puir cpu_physical_memory_rw(upid_phyaddress, &upid, 16, true); // write back send=true; } cpu_physical_memory_rw(upid_phyaddress, &upid, 16, true); uint64_tAPICaddress=get_hphys2(cs, APIC_DEFAULT_ADDRESS, MMU_DATA_LOAD, &prot); uint64_tEOI; uint64_tzero=0; cpu_physical_memory_rw(APICaddress+0xb0, &EOI, 8, false); qemu_log("the physical address of APIC 0x%lx the EOI content: 0x%lx\n", APICaddress,EOI); cpu_physical_memory_rw(APICaddress+0xb0, &zero, 4, true); if(send)helper_rrnzero(env); return; } the rr is not zero means there is an interrupt, the rrnzero function accomplished as below voidhelper_rrnzero(CPUX86State*env){ target_ulongtemprsp=env->regs[R_ESP]; if(env->uintr_stackadjust&1){ // adjust[0] = 1 env->regs[R_ESP] =env->uintr_stackadjust; qemu_log("qemu:set statck 0x%lx\n",env->regs[R_ESP]); }else{ env->regs[R_ESP] -=env->uintr_stackadjust; qemu_log("qemu:move statck 0x%lx\n",env->regs[R_ESP]); } env->regs[R_ESP] &=~0xfLL; /* align stack */ target_ulongesp=env->regs[R_ESP]; qemu_log("qemu:after align statck 0x%lx\n",env->regs[R_ESP]); PUSHQ(esp, temprsp); PUSHQ(esp, env->eflags); // PUSHQ(esp, cpu_compute_eflags(env)); PUSHQ(esp, env->eip); PUSHQ(esp, env->uintr_rr&0x3f); // // 64-bit push; upper 58 bits pushed as 0 env->uintr_rr=0; // clear rr env->regs[R_ESP] =esp; env->eflags&=~(TF_MASK|RF_MASK); env->eip=env->uintr_handler; // switch eip to handler function env->uintr_uif=0; } the ret instruction is uiret, which return from handler function case0xec: if (prefixes&PREFIX_REPZ){ qemu_log("\n\n\n--------------\n"); qemu_log("qemu:caught 0xf30f01ec UIRET\n"); // 改 qemu_log("before: pc_start: 0x%lx sc_base:%lx pc: 0x%lx pc.next:0x%lx rip:0x%lx\n",s->pc_start,s->cs_base, s->pc, s->base.pc_next, env->eip); helper_uiret(env); uiret_called=true; qemu_log("pc_start: 0x%lx sc_base:%lx pc: 0x%lx rip:0x%lx\n",s->pc_start,s->cs_base, s->pc, env->eip); set_cc_op(s, CC_OP_EFLAGS); gen_eob(s); qemu_log("-------------\n\n\n"); } the helper fuction modify the eip and restore the context voidhelper_uiret(CPUX86State*env){ target_ulongtemprip, temprfalgs, temprsp, uirrv; target_ulongesp=env->regs[R_ESP]; esp+=0x60; POPQ(esp, uirrv); POPQ(esp, temprip); POPQ(esp, temprfalgs); POPQ(esp, temprsp); env->eip=temprip; env->regs[R_ESP] =temprsp; env->eflags= (env->eflags&~0x254dd5) |(temprfalgs&0x254dd5); env->uintr_uif=1; } the problem is, i could successfully called the handler, but when after uiret, the linux let out segment fault as below [ 6.094367] sample[78]: segfault at 7fe05b897640 ip 00007fe05b897640 sp 00007ffe2be86af8 error 15 I am just wondering why i could just modify eip to jmp to handler, but when i trying to return from handler, it must need gen_eob(s); and why the segment fault occurs, is there any problem with my accomplishment in uiret instruction?(i just refer the same instruction like iret and tried many times. help please ! thank you very very mush~