Ds_handler类和Direct_mmio_handler类分析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gaojy19881225/article/details/82053621

Ds_handler类

class Ds_handler : public Vmm::Mmio_device

{

  l4::Cap<L4Re::Dataspace> _ds;

  l4_addr_t _offset;

 

  bool _mergable(cxx::Ref_ptr<Mmio_device> other, 

                 l4_addr_t start_other, l4_addr_t start_this) override  //相同数据块引用可合并,是不是供KSM功能使用的?

  {

    // same device type and same underlying dataspace?

    auto dsh = dynamic_cast<Ds_handler *>(other.get());

    if (!dsh || (_ds != dsh->_ds))  //dah不为空则是相同的设备类型;还需要相同的数据空间才行

      return false;

 

    // reference the same part of the data space?

    return (_offset + (start_other - start_this)) == dsh->_offset;  //更进一步,相同的数据空间,还得偏移相同才是可mergable的

  }

 

  int access(l4_addr_t pfa, l4_addr_t offset, Vmm::Vcpu_ptr vcpu,

             l4::Cap<l4::Task> vm_task, l4_addr_t min, l4_addr_t max)

  {

    long res;

#ifdef MAP_OTHER

    res = _ds->map(offset + _offset,

                   vcpu.pf_write() ? L4Re::Dataspace::Map_rw : 0,

                   pfa, min, max, vm_task);

#else

    unsigned char ps = get_page_shift(pfa, min, max, offset, _local_start);  //获取PAGESHIFT

 

    // TODO Need to make sure that memory is locally mapped.

    res = L4Re::chksys(vm_task->map(L4Re::This_task,

                                 l4_fpage(l4_trunc_size(_local_start + offset, ps),

                                 ps,

                                 vcpu.pf_write() ? l4_FPAGE_RWX : l4_FPAGE_RX),

                                 l4_trunc_size(pfa, ps)));  //映射

#endif

 

    if (res < 0)

      {

        Err().printf("cannot handle VM memory access @ %lx ip=%lx r=%ld\n",

                     pfa, vcpu->r.ip, res);

        return res;

      }

 

    return Vmm::Retry;

  }

 

  char const *dev_info(char *buf, size_t size) override  //设备信息保存在buff中

  {

#ifndef MAP_OTHER

    snprintf(buf, size, "mmio ds: [%lx - ?] -> [%lx:%lx - ?]",

             _local_start, _ds.cap(), _offset);

#else

    snprintf(buf, size, "mmio ds: [? - ?] -> [%lx:%lx - ?]",

             _ds.cap(), _offset);

#endif

    return buf;

  }

 

  l4_addr_t _local_start;

 

public:

  explicit Ds_handler(l4::Cap<L4Re::Dataspace> ds,

                      l4_addr_t local_start,

                      l4_size_t size,

                      l4_addr_t offset = 0)

    : _ds(ds), _offset(offset), _local_start(local_start)

  {

    assert(size);

#ifndef MAP_OTHER

if (local_start == 0)

  //即时映射dataspace到_local_start

      L4Re::chksys(L4Re::Env::env()->rm()->attach(&_local_start, size,

                                                  L4Re::Rm::Search_addr

                                                  | L4Re::Rm::Eager_map,

                                                  l4::Ipc::make_cap_rw(ds),

                                                  offset, l4_SUPERPAGESHIFT));

 

    l4_addr_t page_offs = offset & ~l4_PAGEMASK;

    if (page_offs)  //加上偏移

      {

        auto tmp = l4_trunc_page(_local_start) + page_offs;

        Dbg(Dbg::Mmio, Dbg::Warn)

          .printf("Region not page aligned, adjusting local_start: %lx -> %lx\n",

                  _local_start, tmp);

        _local_start = tmp;

      }

#endif

  }

 

  l4_addr_t local_start() const { return _local_start; }

}

 

Direct_mmio_handler类

class Direct_mmio_handler : public Vmm::Mmio_device

{

  l4::Cap<L4Re::Dataspace> _ds;

  l4_addr_t _local_start;

 

public:

  explicit Direct_mmio_handler(l4::Cap<L4Re::Dataspace> ds,

                      l4_addr_t local_start,

                      l4_size_t size,

                      l4_addr_t offset)

    : _ds(ds), _local_start(local_start)

  {

    assert(size);

    //映射

    L4Re::chksys(L4Re::Env::env()->rm()->attach(&_local_start, size,

                                                  L4Re::Rm::Search_addr

                                                  | L4Re::Rm::Eager_map | L4Re::Rm::Cache_uncached,

                                                  l4::Ipc::make_cap_rw(ds),

                                                  offset));

 

    l4_addr_t page_offs = offset & ~l4_PAGEMASK;

    if (page_offs)  //加上偏移

      {

        auto tmp = l4_trunc_page(_local_start) + page_offs;

        Dbg(Dbg::Mmio, Dbg::Warn)

          .printf("Region not page aligned, adjusting local_start: %lx -> %lx\n",

                  _local_start, tmp);

        _local_start = tmp;

      }

  }

 

 

  int access(l4_addr_t pfa, l4_addr_t offset, Vmm::Vcpu_ptr vcpu,

             l4::Cap<l4::Task>, l4_addr_t, l4_addr_t)

  {

    auto insn = vcpu.decode_mmio(pfa);  //vcpu解码,返回存储类型(store、load、other)

 

    if (insn.access == Vmm::Mem_access::Other)  //解码失败

      {

        Err().printf("cannot decode , try direct map\n");

 

        Dbg(Dbg::Mmio, Dbg::Warn, "mmio").

          printf("MMIO access @ 0x%lx: unknown instruction. Ignored.\n",pfa);

        return -l4_ENXIO;

      }

 

    Dbg(Dbg::Mmio, Dbg::Trace, "mmio")

      .printf("MMIO access @ 0x%lx (0x%lx) %s, width: %u\n", pfa, offset,

      insn.access == Vmm::Mem_access::Load ? "LOAD" : "STORE",

      (unsigned) insn.width);

 

 

    do

    {

      auto val_bak = insn.value;

 

      vcpu.rep_start(insn);  //x86的repeat类指令设置

      if ((insn.access == Vmm::Mem_access::Store) || (insn.access == Vmm::Mem_access::Repeat_Store)){

        if(insn.width == Vmm::Mem_access::Wd128){

          write128(offset, (unsigned char *)&insn.xmm_value);

        }

        else{

          write(offset, insn.width, insn.value, vcpu.get_vcpu_id());

        }

      }

      else{

        if(insn.width == Vmm::Mem_access::Wd128){

          read128(offset, (unsigned char *)&insn.xmm_value);

        }

        else

          insn.value = read(offset, insn.width, vcpu.get_vcpu_id());

 

        vcpu.writeback_mmio(insn);

      }

      insn.value = val_bak;

      vcpu.rep_commit(insn, offset);

    }while(vcpu.get_rep_cnt(insn) > 0);

 

    return Vmm::Jump_instr;

  }

 

  l4_uint64_t read(unsigned offset, char width, unsigned cpuid)

  {

    (void) cpuid; // must be ignored by this implementation because

                  // we have no CPU-local mappings of our dataspace.

    if (0)

      printf("MMIO/RO/DS read: offset=%x (%u) [0x%lx] = %x\n", offset,

        (unsigned)width, _local_start + offset,

        *((l4_uint32_t*)(_local_start) + offset));

 

    return Vmm::Mem_access::read_width(_local_start + offset, width);  //调用内存读指令

  }

 

  l4_uint64_t write(unsigned offset, char width, l4_uint64_t value, unsigned cpuid)

  {

    (void) cpuid; // must be ignored by this implementation because

                  // we have no CPU-local mappings of our dataspace.

    if (0)

      printf("MMIO/RO/DS read: offset=%x (%u) [0x%lx] = %x\n", offset,

        (unsigned)width, _local_start + offset,

        *((l4_uint32_t*)(_local_start + offset)));

 

    return Vmm::Mem_access::write_width(_local_start + offset, value, width);  //内存写指令

  }

 

  void read128(unsigned offset, unsigned char *value)

  {

    memcpy(value, (unsigned char *)(_local_start + offset), 16);

  }

 

  void write128(unsigned offset, unsigned char *value)

  {

    memcpy((unsigned char *)(_local_start + offset), value, 16);

  }

 

}

 

猜你喜欢

转载自blog.csdn.net/gaojy19881225/article/details/82053621