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~
 



Reply via email to