如果userret中没有数据段,extern char userret[]代表什么?

问题描述

xv6 os中的一些代码我有两个问题:

  1. userret 中没有数据段(汇编中),'extern char userret[]'(C 中)代表什么?
  2. 对于C代码,如果去掉[],只有userret,是不是表示程序加载后程序集中userret的虚拟地址?

汇编代码

.globl userret
userret:
        # userret(TRAPFRAME,pagetable)
        # switch from kernel to user.
        # usertrapret() calls here.
        # a0: TRAPFRAME,in user page table.
        # a1: user page table,for satp.

        # switch to the user page table.
        csrw satp,a1
        sfence.vma zero,zero

        # put the saved user a0 in sscratch,so we
        # can swap it with our a0 (TRAPFRAME) in the last step.
        ld t0,112(a0)
        csrw sscratch,t0

        # restore all but a0 from TRAPFRAME
        ld ra,40(a0)
        ld sp,48(a0)
        ld gp,56(a0)
        ld tp,64(a0)
        ld t0,72(a0)
        ld t1,80(a0)
        ld t2,88(a0)
        ld s0,96(a0)
        ld s1,104(a0)
        ld a1,120(a0)
        ld a2,128(a0)
        ld a3,136(a0)
        ld a4,144(a0)
        ld a5,152(a0)
        ld a6,160(a0)
        ld a7,168(a0)
        ld s2,176(a0)
        ld s3,184(a0)
        ld s4,192(a0)
        ld s5,200(a0)
        ld s6,208(a0)
        ld s7,216(a0)
        ld s8,224(a0)
        ld s9,232(a0)
        ld s10,240(a0)
        ld s11,248(a0)
        ld t3,256(a0)
        ld t4,264(a0)
        ld t5,272(a0)
        ld t6,280(a0)

    # restore user a0,and save TRAPFRAME in sscratch
        csrrw a0,sscratch,a0
        
        # return to user mode and user pc.
        # usertrapret() set up sstatus and sepc.
        sret

C 代码

#include "types.h"
#include "param.h"
#include "memlayout.h"
#include "riscv.h"
#include "spinlock.h"
#include "proc.h"
#include "defs.h"

struct spinlock tickslock;
uint ticks;

extern char trampoline[],uservec[],userret[];

// in kernelvec.S,calls kerneltrap().
void kernelvec();

extern int devintr();

static const char *
scause_desc(uint64 stval);

void
trapinit(void)
{
  initlock(&tickslock,"time");
}

// set up to take exceptions and traps while in the kernel.
void
trapinithart(void)
{
  w_stvec((uint64)kernelvec);
}

//
// handle an interrupt,exception,or system call from user space.
// called from trampoline.S
//
void
usertrap(void)
{
  int which_dev = 0;

  if((r_sstatus() & sstATUS_SPP) != 0)
    panic("usertrap: not from user mode");

  // send interrupts and exceptions to kerneltrap(),// since we're Now in the kernel.
  w_stvec((uint64)kernelvec);

  struct proc *p = myproc();
  
  // save user program counter.
  p->tf->epc = r_sepc();
  
  if(r_scause() == 8){
    // system call

    if(p->killed)
      exit(-1);

    // sepc points to the ecall instruction,// but we want to return to the next instruction.
    p->tf->epc += 4;

    // an interrupt will change sstatus &c registers,// so don't enable until done with those registers.
    intr_on();

    syscall();
  } else if((which_dev = devintr()) != 0){
    // ok
  } else {
    printf("usertrap(): unexpected scause %p (%s) pid=%d\n",r_scause(),scause_desc(r_scause()),p->pid);
    printf("            sepc=%p stval=%p\n",r_sepc(),r_stval());
    p->killed = 1;
  }

  if(p->killed)
    exit(-1);

  // give up the cpu if this is a timer interrupt.
  if(which_dev == 2)
    yield();

  usertrapret();
}

//
// return to user space
//
void
usertrapret(void)
{
  struct proc *p = myproc();

  // turn off interrupts,since we're switching
  // Now from kerneltrap() to usertrap().
  intr_off();

  // send syscalls,interrupts,and exceptions to trampoline.S
  w_stvec(TRAMPOLINE + (uservec - trampoline));

  // set up trapframe values that uservec will need when
  // the process next re-enters the kernel.
  p->tf->kernel_satp = r_satp();         // kernel page table
  p->tf->kernel_sp = p->kstack + PGSIZE; // process's kernel stack
  p->tf->kernel_trap = (uint64)usertrap;
  p->tf->kernel_hartid = r_tp();         // hartid for cpuid()

  // set up the registers that trampoline.S's sret will use
  // to get to user space.
  
  // set S PrevIoUs Privilege mode to User.
  unsigned long x = r_sstatus();
  x &= ~sstATUS_SPP; // clear SPP to 0 for user mode
  x |= sstATUS_SPIE; // enable interrupts in user mode
  w_sstatus(x);

  // set S Exception Program Counter to the saved user pc.
  w_sepc(p->tf->epc);

  // tell trampoline.S the user page table to switch to.
  uint64 satp = MAKE_SATP(p->pagetable);

  // jump to trampoline.S at the top of memory,which 
  // switches to the user page table,restores user registers,// and switches to user mode with sret.
  uint64 fn = TRAMPOLINE + (userret - trampoline);
  ((void (*)(uint64,uint64))fn)(TRAPFRAME,satp);
}

// interrupts and exceptions from kernel code go here via kernelvec,// on whatever the current kernel stack is.
void 
kerneltrap()
{
  int which_dev = 0;
  uint64 sepc = r_sepc();
  uint64 sstatus = r_sstatus();
  uint64 scause = r_scause();
  
  if((sstatus & sstATUS_SPP) == 0)
    panic("kerneltrap: not from supervisor mode");
  if(intr_get() != 0)
    panic("kerneltrap: interrupts enabled");

  if((which_dev = devintr()) == 0){
    printf("scause %p (%s)\n",scause,scause_desc(scause));
    printf("sepc=%p stval=%p\n",r_stval());
    panic("kerneltrap");
  }

  // give up the cpu if this is a timer interrupt.
  if(which_dev == 2 && myproc() != 0 && myproc()->state == RUNNING)
    yield();

  // the yield() may have caused some traps to occur,// so restore trap registers for use by kernelvec.S's sepc instruction.
  w_sepc(sepc);
  w_sstatus(sstatus);
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...