qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

x86 uintr feature problem in qemu


From: 项晨东
Subject: x86 uintr feature problem in qemu
Date: Tue, 10 May 2022 17:46:12 +0800 (GMT+08:00)

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;
}
int prot;
CPUState *cs = env_cpu(env);
uint64_t upid_phyaddress = get_hphys2(cs, env->uintr_pd, MMU_DATA_LOAD, &prot);
uintr_upid upid;
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_t APICaddress = get_hphys2(cs, APIC_DEFAULT_ADDRESS, MMU_DATA_LOAD, &prot);
uint64_t EOI;
uint64_t zero = 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
void helper_rrnzero(CPUX86State *env){
target_ulong temprsp = 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_ulong esp = 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
case 0xec:
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
void helper_uiret(CPUX86State *env){
target_ulong temprip, temprfalgs, temprsp, uirrv;
target_ulong esp = 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

[Prev in Thread] Current Thread [Next in Thread]