微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决如果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.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?