设为首页 收藏本站
查看: 1744|回复: 0

[经验分享] KVM源代码解读:linux-3.17.4\include\linux\kvm_host.h

[复制链接]

尚未签到

发表于 2015-4-10 17:50:02 | 显示全部楼层 |阅读模式
  #ifndef __KVM_HOST_H
  #define __KVM_HOST_H
  
  /*
  * This work is licensed under the terms of the GNU GPL, version 2.  See
  * the COPYING file in the top-level directory.
  */
  
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  #include
  
  #include
  #include
  
  #include
  
  #include
  
  #ifndef KVM_MMIO_SIZE
  #define KVM_MMIO_SIZE 8
  #endif
  
  /*
  * The bit 16 ~ bit 31 of kvm_memory_region::flags are internally used
  * in kvm, other bits are visible for userspace which are defined in
  * include/linux/kvm_h.
  */
  #define KVM_MEMSLOT_INVALID     (1UL = memslot->base_gfn &&
  gfn < memslot->base_gfn + memslot->npages)
  return memslot;
  
  return NULL;
  }
  //函数作用筒search_memslots()
  static inline struct kvm_memory_slot *
  __gfn_to_memslot(struct kvm_memslots *slots, gfn_t gfn)
  {
  return search_memslots(slots, gfn);
  }
  //gfn到hva内存槽
  static inline unsigned long
  __gfn_to_hva_memslot(struct kvm_memory_slot *slot, gfn_t gfn)
  {
  return slot->userspace_addr + (gfn - slot->base_gfn) * PAGE_SIZE;
  }
  //获得内存槽的id
  static inline int memslot_id(struct kvm *kvm, gfn_t gfn)
  {
  return gfn_to_memslot(kvm, gfn)->id;
  }
//根据定义的页的大小,比如4KB,取定PAGE_SHIFT的值,其值即是页框号和地址的左移或者右移的位数
  static inline gfn_t
  hva_to_gfn_memslot(unsigned long hva, struct kvm_memory_slot *slot)
  {
  gfn_t gfn_offset = (hva - slot->userspace_addr) >> PAGE_SHIFT;
  
  return slot->base_gfn + gfn_offset;
  }
  
  static inline gpa_t gfn_to_gpa(gfn_t gfn)
  {
  return (gpa_t)gfn > PAGE_SHIFT);
  }
  
  static inline hpa_t pfn_to_hpa(pfn_t pfn)
  {
  return (hpa_t)pfn requests);
  }
  //kvm的两种状态,VM和VCPU
  enum kvm_stat_kind {
  KVM_STAT_VM,
  KVM_STAT_VCPU,
  };
  
  struct kvm_stats_debugfs_item {
  const char *name;
  int offset;
  enum kvm_stat_kind kind;
  struct dentry *dentry;
  };
  extern struct kvm_stats_debugfs_item debugfs_entries[];
  extern struct dentry *kvm_debugfs_dir;
  
  #if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER)
  static inline int mmu_notifier_retry(struct kvm *kvm, unsigned long mmu_seq)
  {
  if (unlikely(kvm->mmu_notifier_count))
  return 1;
  /*
  * Ensure the read of mmu_notifier_count happens before the read
  * of mmu_notifier_seq.  This interacts with the smp_wmb() in
  * mmu_notifier_invalidate_range_end to make sure that the caller
  * either sees the old (non-zero) value of mmu_notifier_count or
  * the new (incremented) value of mmu_notifier_seq.
  * PowerPC Book3s HV KVM calls this under a per-page lock
  * rather than under kvm->mmu_lock, for scalability, so
  * can't rely on kvm->mmu_lock to keep things ordered.
  */
  smp_rmb();
  if (kvm->mmu_notifier_seq != mmu_seq)
  return 1;
  return 0;
  }
  #endif
  
  #ifdef CONFIG_HAVE_KVM_IRQ_ROUTING
  
  #ifdef CONFIG_S390
  #define KVM_MAX_IRQ_ROUTES 4096 //FIXME: we can have more than that...
  #else
  #define KVM_MAX_IRQ_ROUTES 1024
  #endif
  
  int kvm_setup_default_irq_routing(struct kvm *kvm);
  int kvm_set_irq_routing(struct kvm *kvm,
  const struct kvm_irq_routing_entry *entries,
  unsigned nr,
  unsigned flags);
  int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e,
  const struct kvm_irq_routing_entry *ue);
  void kvm_free_irq_routing(struct kvm *kvm);
  
  #else
  
  static inline void kvm_free_irq_routing(struct kvm *kvm) {}
  
  #endif
  
  int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi);
  
  #ifdef CONFIG_HAVE_KVM_EVENTFD
  
  void kvm_eventfd_init(struct kvm *kvm);
  int kvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args);
  
  #ifdef CONFIG_HAVE_KVM_IRQFD
  int kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args);
  void kvm_irqfd_release(struct kvm *kvm);
  void kvm_irq_routing_update(struct kvm *);
  #else
  static inline int kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args)
  {
  return -EINVAL;
  }
  
  static inline void kvm_irqfd_release(struct kvm *kvm) {}
  #endif
  
  #else
  
  static inline void kvm_eventfd_init(struct kvm *kvm) {}
  
  static inline int kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args)
  {
  return -EINVAL;
  }
  
  static inline void kvm_irqfd_release(struct kvm *kvm) {}
  
  #ifdef CONFIG_HAVE_KVM_IRQCHIP
  static inline void kvm_irq_routing_update(struct kvm *kvm)
  {
  }
  #endif
  
  static inline int kvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args)
  {
  return -ENOSYS;
  }
  
  #endif /* CONFIG_HAVE_KVM_EVENTFD */
  
  #ifdef CONFIG_KVM_APIC_ARCHITECTURE
  static inline bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu)
  {
  return vcpu->kvm->bsp_vcpu_id == vcpu->vcpu_id;
  }
  
  bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu);
  
  #else
  
  static inline bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu) { return true; }
  
  #endif
  
  #ifdef CONFIG_KVM_DEVICE_ASSIGNMENT
  
  long kvm_vm_ioctl_assigned_device(struct kvm *kvm, unsigned ioctl,
  unsigned long arg);
  
  void kvm_free_all_assigned_devices(struct kvm *kvm);
  
  #else
  
  static inline long kvm_vm_ioctl_assigned_device(struct kvm *kvm, unsigned ioctl,
  unsigned long arg)
  {
  return -ENOTTY;
  }
  
  static inline void kvm_free_all_assigned_devices(struct kvm *kvm) {}
  
  #endif
  
  static inline void kvm_make_request(int req, struct kvm_vcpu *vcpu)
  {
  set_bit(req, &vcpu->requests);
  }
  
  static inline bool kvm_check_request(int req, struct kvm_vcpu *vcpu)
  {
  if (test_bit(req, &vcpu->requests)) {
  clear_bit(req, &vcpu->requests);
  return true;
  } else {
  return false;
  }
  }
  
  extern bool kvm_rebooting;
  
  struct kvm_device_ops;
//kvm设备操作结构体
  struct kvm_device {
  struct kvm_device_ops *ops;//kvm设备操作符
  struct kvm *kvm;
  void *private;
  struct list_head vm_node;//设备的双向链表
  };
  
  /* create, destroy, and name are mandatory 强制性的*/
//设备操作符数据结构
  struct kvm_device_ops {
  const char *name;
  int (*create)(struct kvm_device *dev, u32 type);
  
  /*
  * Destroy is responsible for freeing dev.
  *
  * Destroy may be called before or after destructors are called
  * on emulated I/O regions, depending on whether a reference is
  * held by a vcpu or other kvm component that gets destroyed
  * after the emulated I/O.
  */
  void (*destroy)(struct kvm_device *dev);
  
  int (*set_attr)(struct kvm_device *dev, struct kvm_device_attr *attr);
  int (*get_attr)(struct kvm_device *dev, struct kvm_device_attr *attr);
  int (*has_attr)(struct kvm_device *dev, struct kvm_device_attr *attr);
  long (*ioctl)(struct kvm_device *dev, unsigned int ioctl,
  unsigned long arg);
  };
  
  void kvm_device_get(struct kvm_device *dev);
  void kvm_device_put(struct kvm_device *dev);
  struct kvm_device *kvm_device_from_filp(struct file *filp);
  
  extern struct kvm_device_ops kvm_mpic_ops;
  extern struct kvm_device_ops kvm_xics_ops;
  extern struct kvm_device_ops kvm_vfio_ops;
  extern struct kvm_device_ops kvm_arm_vgic_v2_ops;
  extern struct kvm_device_ops kvm_flic_ops;
  
  #ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT
  
  static inline void kvm_vcpu_set_in_spin_loop(struct kvm_vcpu *vcpu, bool val)
  {
  vcpu->spin_loop.in_spin_loop = val;
  }
  static inline void kvm_vcpu_set_dy_eligible(struct kvm_vcpu *vcpu, bool val)
  {
  vcpu->spin_loop.dy_eligible = val;
  }
  
  #else /* !CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT */
  
  static inline void kvm_vcpu_set_in_spin_loop(struct kvm_vcpu *vcpu, bool val)
  {
  }
  
  static inline void kvm_vcpu_set_dy_eligible(struct kvm_vcpu *vcpu, bool val)
  {
  }
  #endif /* CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT */
  #endif
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-55798-1-1.html 上篇帖子: KVM虚拟化技术实战与原理解析笔记 下篇帖子: KVM SCSI格式硬盘无法启动
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表