Martins3 / loongson-dune

:zap: Process virtualization based on KVM. More useable, stable and practical than Stanford Dune.
20 stars 3 forks source link

debug: fork and posix_pthread #13

Closed Martins3 closed 3 years ago

Martins3 commented 3 years ago
Martins3 commented 3 years ago
Martins3 commented 3 years ago
Martins3 commented 3 years ago
Martins3 commented 3 years ago

CLONE_FILES (since Linux 2.0)

          If CLONE_FILES is set, the calling process and the child
          process share the same file descriptor table.  Any file
          descriptor created by the calling process or by the child
          process is also valid in the other process.  Similarly, if
          one of the processes closes a file descriptor, or changes
          its associated flags (using the fcntl(2) F_SETFD
          operation), the other process is also affected.  If a
          process sharing a file descriptor table calls execve(2),
          its file descriptor table is duplicated (unshared).

          If CLONE_FILES is not set, the child process inherits a
          copy of all file descriptors opened in the calling process
          at the time of the clone call.  Subsequent operations that
          open or close file descriptors, or change file descriptor
          flags, performed by either the calling process or the
          child process do not affect the other process.  Note,
          however, that the duplicated file descriptors in the child
          refer to the same open file descriptions as the
          corresponding file descriptors in the calling process, and
          thus share file offsets and file status flags (see
          open(2)).
Martins3 commented 3 years ago
Martins3 commented 3 years ago
Martins3 commented 3 years ago
Martins3 commented 3 years ago
Martins3 commented 3 years ago

/home/maritns3/core/loongson-dune/cross/arch/mips/kernel/scall64-64.S

syscall_common:
    dsubu   t2, v0, __NR_64_Linux
    sltiu   t0, t2, __NR_64_Linux_syscalls + 1
    beqz    t0, illegal_syscall

    dsll    t0, t2, 3       # offset into table
    dla t2, sys_call_table
    daddu   t0, t2, t0
    ld  t2, (t0)        # syscall routine
    beqz    t2, illegal_syscall

    jalr    t2          # Do The Real Thing (TM)

    li  t0, -EMAXERRNO - 1  # error?
       # #define EMAXERRNO  1133
    sltu    t0, t0, v0  
       # To record the result of an unsigned less-than comparison.
       # Description: GPR[rd] <- (GPR[rs] < GPR[rt])
    sd  t0, PT_R7(sp)       # set error flag
    beqz    t0, 1f

    ld  t1, PT_R2(sp)       # syscall number
    dnegu   v0          # error
    sd  t1, PT_R0(sp)       # save it for syscall restarting
1:  sd  v0, PT_R2(sp)       # result

n64_syscall_exit:
    j   syscall_exit_partial
Martins3 commented 3 years ago
Martins3 commented 3 years ago
Martins3 commented 3 years ago
Martins3 commented 3 years ago
 History:        #0
 Commit:         6d4e4c4fca5be806b888d606894d914847e82d78
 Author:         Avi Kivity <avi@qumranet.com>
 Author Date:    Wed 21 Nov 2007 10:41:05 PM CST
 Committer Date: Wed 30 Jan 2008 11:53:13 PM CST

 KVM: Disallow fork() and similar games when using a VM

 We don't want the meaning of guest userspace changing under our feet.

 Signed-off-by: Avi Kivity <avi@qumranet.com>

 diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
 index aec6b67cfebb..0efd759e585f 100644
 --- a/drivers/kvm/kvm_main.c
 +++ b/drivers/kvm/kvm_main.c
 @@ -165,6 +165,8 @@ static struct kvm *kvm_create_vm(void)
    if (IS_ERR(kvm))
        goto out;

 +  kvm->mm = current->mm;
 +  atomic_inc(&kvm->mm->mm_count);
    kvm_io_bus_init(&kvm->pio_bus);
    mutex_init(&kvm->lock);
    kvm_io_bus_init(&kvm->mmio_bus);
Martins3 commented 3 years ago

the child should be exactly same, it points to the next instruction of syscall

>>> disass 0x120009098 (<----------- this is parent epc)
Dump of assembler code for function __clone:
   0x0000000120009070 <+0>:     li      at,-16
   0x0000000120009074 <+4>:     and     a1,a1,at
   0x0000000120009078 <+8>:     daddiu  a1,a1,-16
   0x000000012000907c <+12>:    sd      a0,0(a1)
   0x0000000120009080 <+16>:    sd      a3,8(a1)
   0x0000000120009084 <+20>:    move    a0,a2
   0x0000000120009088 <+24>:    move    a2,a4
   0x000000012000908c <+28>:    move    a3,a5
   0x0000000120009090 <+32>:    move    a4,a6
   0x0000000120009094 <+36>:    li      v0,5055
   0x0000000120009098 <+40>:    syscall
   0x000000012000909c <+44>:    beqz    a3,0x1200090ac <__clone+60>
   0x00000001200090a0 <+48>:    nop
   0x00000001200090a4 <+52>:    jr      ra
   0x00000001200090a8 <+56>:    dnegu   v0,v0
   0x00000001200090ac <+60>:    beqz    v0,0x1200090bc <__clone+76>
   0x00000001200090b0 <+64>:    nop
   0x00000001200090b4 <+68>:    jr      ra
   0x00000001200090b8 <+72>:    nop
   0x00000001200090bc <+76>:    ld      t9,0(sp)
   0x00000001200090c0 <+80>:    ld      a0,8(sp)
   0x00000001200090c4 <+84>:    jalr    t9
   0x00000001200090c8 <+88>:    nop
   0x00000001200090cc <+92>:    move    a0,v0
   0x00000001200090d0 <+96>:    li      v0,5058
   0x00000001200090d4 <+100>:   syscall
   0x00000001200090d8 <+104>:   nop
   0x00000001200090dc <+108>:   nop
End of assembler dump.
Martins3 commented 3 years ago
Martins3 commented 3 years ago

What does EXCCODE_INT in kvm_mips_handle_exit ?

here is my assumption:

Martins3 commented 3 years ago

My ideas for the bug: maybe it's caused by remote TLB shoot:

No, remote TLB shoot, which will call kvm_vz_local_flush_roottlb_all_guests

            for_each_possible_cpu(i)
                vcpu->arch.vzguestid[i] = 0;
Martins3 commented 3 years ago

Bug Found 1

[99132.196899] kvm [739]: kvm_mips_handle_exit: cause: 0x10800008, PC: 120008f4c, kvm_run: 000000001d0d7069, kvm_vcpu: 000000006df3ba79 cause=40008008
[99132.196902] kvm [739]: TLB LD fault: cause 0x10800008, PC: 000000008da9c0d9, BadVaddr: 0xfffbcf30b0
[99132.196912] kvm [739]: kvm_vz_host_tlb_inv: Invalidated root entryhi 0xfffbcf2000 @ idx 2014
[99132.196914] kvm [739]: kvm_mips_handle_exit : cause register = 40008008 exit_reason=0
[99132.196918] kvm [739]: kvm_mips_handle_exit: cause: 0x10800008, PC: fffbcf30f0, kvm_run: 000000001d0d7069, kvm_vcpu: 000000006df3ba79 cause=40008008
[99132.196921] kvm [739]: TLB LD fault: cause 0x10800008, PC: 000000008daf6e2f, BadVaddr: 0x0
[99132.196923] kvm [739]: Failed to find VMA for hva 0x0
Reading symbols from clone01...done.
>>> disass 0x120008f4c
Dump of assembler code for function __clone:
   0x0000000120008f00 <+0>:     li      at,-16
   0x0000000120008f04 <+4>:     and     a1,a1,at
   0x0000000120008f08 <+8>:     daddiu  a1,a1,-16
   0x0000000120008f0c <+12>:    sd      a0,0(a1)
   0x0000000120008f10 <+16>:    sd      a3,8(a1)
   0x0000000120008f14 <+20>:    move    a0,a2
   0x0000000120008f18 <+24>:    move    a2,a4
   0x0000000120008f1c <+28>:    move    a3,a5
   0x0000000120008f20 <+32>:    move    a4,a6
   0x0000000120008f24 <+36>:    li      v0,5055
   0x0000000120008f28 <+40>:    syscall
   0x0000000120008f2c <+44>:    beqz    a3,0x120008f3c <__clone+60>
   0x0000000120008f30 <+48>:    nop
   0x0000000120008f34 <+52>:    jr      ra
   0x0000000120008f38 <+56>:    dnegu   v0,v0
   0x0000000120008f3c <+60>:    beqz    v0,0x120008f4c <__clone+76>
   0x0000000120008f40 <+64>:    nop
   0x0000000120008f44 <+68>:    jr      ra
   0x0000000120008f48 <+72>:    nop
   0x0000000120008f4c <+76>:    ld      t9,0(sp) ##### SP doesn't set correctly, PC goes to somewhere randomly ###
   0x0000000120008f50 <+80>:    ld      a0,8(sp)
   0x0000000120008f54 <+84>:    jalr    t9
   0x0000000120008f58 <+88>:    nop
   0x0000000120008f5c <+92>:    move    a0,v0
   0x0000000120008f60 <+96>:    li      v0,5058
   0x0000000120008f64 <+100>:   syscall
   0x0000000120008f68 <+104>:   nop
   0x0000000120008f6c <+108>:   nop

Child's sp will set to parameter __child_stack of function clone, but our syscall simulation just copies the parent process's regs.

Martins3 commented 3 years ago

When I change host_loop to the original way, I get into trouble again.

Martins3 commented 3 years ago
Martins3 commented 3 years ago
    /* save KScratch registers if enabled in guest */
    if (cpu_guest_has_conf4) {
        if (cpu_guest_has_kscr(2))
            kvm_save_gc0_kscratch1(cop0);
        if (cpu_guest_has_kscr(3))
            kvm_save_gc0_kscratch2(cop0);
        if (cpu_guest_has_kscr(4))
            kvm_save_gc0_kscratch3(cop0);
        if (cpu_guest_has_kscr(5))
            kvm_save_gc0_kscratch4(cop0);
        if (cpu_guest_has_kscr(6))
            kvm_save_gc0_kscratch5(cop0);
        if (cpu_guest_has_kscr(7))
            kvm_save_gc0_kscratch6(cop0);
    }