Print this page
13275 bhyve needs richer INIT/SIPI support
Reviewed by: Robert Mustacchi <rm@fingolfin.org>
Approved by: Gordon Ross <gordon.w.ross@gmail.com>


  47 
  48 #include <sys/sdt.h>
  49 #include <x86/segments.h>
  50 
  51 SDT_PROVIDER_DECLARE(vmm);
  52 
  53 struct vm;
  54 struct vm_exception;
  55 struct seg_desc;
  56 struct vm_exit;
  57 struct vie;
  58 struct vm_run;
  59 struct vhpet;
  60 struct vioapic;
  61 struct vlapic;
  62 struct vmspace;
  63 struct vm_object;
  64 struct vm_guest_paging;
  65 struct pmap;
  66 
  67 struct vm_eventinfo {
  68         uint_t  *rptr;          /* runblock cookie */
  69         int     *sptr;          /* suspend cookie */
  70         int     *iptr;          /* reqidle cookie */
  71 };
  72 
  73 typedef int     (*vmm_init_func_t)(int ipinum);
  74 typedef int     (*vmm_cleanup_func_t)(void);
  75 typedef void    (*vmm_resume_func_t)(void);
  76 typedef void *  (*vmi_init_func_t)(struct vm *vm, struct pmap *pmap);
  77 typedef int     (*vmi_run_func_t)(void *vmi, int vcpu, uint64_t rip,
  78     struct pmap *pmap, struct vm_eventinfo *info);
  79 typedef void    (*vmi_cleanup_func_t)(void *vmi);
  80 typedef int     (*vmi_get_register_t)(void *vmi, int vcpu, int num,
  81     uint64_t *retval);
  82 typedef int     (*vmi_set_register_t)(void *vmi, int vcpu, int num,
  83     uint64_t val);
  84 typedef int     (*vmi_get_desc_t)(void *vmi, int vcpu, int num,
  85     struct seg_desc *desc);
  86 typedef int     (*vmi_set_desc_t)(void *vmi, int vcpu, int num,
  87     struct seg_desc *desc);
  88 typedef int     (*vmi_get_cap_t)(void *vmi, int vcpu, int num, int *retval);
  89 typedef int     (*vmi_set_cap_t)(void *vmi, int vcpu, int num, int val);
  90 typedef struct vmspace *(*vmi_vmspace_alloc)(vm_offset_t min, vm_offset_t max);
  91 typedef void    (*vmi_vmspace_free)(struct vmspace *vmspace);
  92 typedef struct vlapic *(*vmi_vlapic_init)(void *vmi, int vcpu);
  93 typedef void    (*vmi_vlapic_cleanup)(void *vmi, struct vlapic *vlapic);
  94 #ifndef __FreeBSD__
  95 typedef void    (*vmi_savectx)(void *vmi, int vcpu);
  96 typedef void    (*vmi_restorectx)(void *vmi, int vcpu);
  97 #endif
  98 
  99 struct vmm_ops {
 100         vmm_init_func_t         init;           /* module wide initialization */
 101         vmm_cleanup_func_t      cleanup;
 102         vmm_resume_func_t       resume;
 103 
 104         vmi_init_func_t         vminit;         /* vm-specific initialization */
 105         vmi_run_func_t          vmrun;
 106         vmi_cleanup_func_t      vmcleanup;
 107         vmi_get_register_t      vmgetreg;


 154 /*
 155  * APIs that inspect the guest memory map require only a *single* vcpu to
 156  * be frozen. This acts like a read lock on the guest memory map since any
 157  * modification requires *all* vcpus to be frozen.
 158  */
 159 int vm_mmap_getnext(struct vm *vm, vm_paddr_t *gpa, int *segid,
 160     vm_ooffset_t *segoff, size_t *len, int *prot, int *flags);
 161 int vm_get_memseg(struct vm *vm, int ident, size_t *len, bool *sysmem,
 162     struct vm_object **objptr);
 163 vm_paddr_t vmm_sysmem_maxaddr(struct vm *vm);
 164 void *vm_gpa_hold(struct vm *, int vcpuid, vm_paddr_t gpa, size_t len,
 165     int prot, void **cookie);
 166 void vm_gpa_release(void *cookie);
 167 bool vm_mem_allocated(struct vm *vm, int vcpuid, vm_paddr_t gpa);
 168 
 169 int vm_get_register(struct vm *vm, int vcpu, int reg, uint64_t *retval);
 170 int vm_set_register(struct vm *vm, int vcpu, int reg, uint64_t val);
 171 int vm_get_seg_desc(struct vm *vm, int vcpu, int reg,
 172                     struct seg_desc *ret_desc);
 173 int vm_set_seg_desc(struct vm *vm, int vcpu, int reg,
 174                     struct seg_desc *desc);




 175 int vm_run(struct vm *vm, int vcpuid, const struct vm_entry *);
 176 int vm_suspend(struct vm *vm, enum vm_suspend_how how);
 177 int vm_inject_nmi(struct vm *vm, int vcpu);
 178 int vm_nmi_pending(struct vm *vm, int vcpuid);
 179 void vm_nmi_clear(struct vm *vm, int vcpuid);
 180 int vm_inject_extint(struct vm *vm, int vcpu);
 181 int vm_extint_pending(struct vm *vm, int vcpuid);
 182 void vm_extint_clear(struct vm *vm, int vcpuid);


 183 struct vlapic *vm_lapic(struct vm *vm, int cpu);
 184 struct vioapic *vm_ioapic(struct vm *vm);
 185 struct vhpet *vm_hpet(struct vm *vm);
 186 int vm_get_capability(struct vm *vm, int vcpu, int type, int *val);
 187 int vm_set_capability(struct vm *vm, int vcpu, int type, int val);
 188 int vm_get_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state *state);
 189 int vm_set_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state state);
 190 int vm_apicid2vcpuid(struct vm *vm, int apicid);
 191 int vm_activate_cpu(struct vm *vm, int vcpu);
 192 int vm_suspend_cpu(struct vm *vm, int vcpu);
 193 int vm_resume_cpu(struct vm *vm, int vcpu);
 194 struct vm_exit *vm_exitinfo(struct vm *vm, int vcpuid);
 195 struct vie *vm_vie_ctx(struct vm *vm, int vcpuid);
 196 void vm_exit_suspended(struct vm *vm, int vcpuid, uint64_t rip);
 197 void vm_exit_debug(struct vm *vm, int vcpuid, uint64_t rip);
 198 void vm_exit_runblock(struct vm *vm, int vcpuid, uint64_t rip);
 199 void vm_exit_astpending(struct vm *vm, int vcpuid, uint64_t rip);
 200 void vm_exit_reqidle(struct vm *vm, int vcpuid, uint64_t rip);

 201 int vm_service_mmio_read(struct vm *vm, int cpuid, uint64_t gpa, uint64_t *rval,
 202     int rsize);
 203 int vm_service_mmio_write(struct vm *vm, int cpuid, uint64_t gpa, uint64_t wval,
 204     int wsize);
 205 void vm_req_spinup_ap(struct vm *vm, int req_vcpuid, uint64_t req_rip);
 206 
 207 #ifdef _SYS__CPUSET_H_
 208 cpuset_t vm_active_cpus(struct vm *vm);
 209 cpuset_t vm_debug_cpus(struct vm *vm);
 210 cpuset_t vm_suspended_cpus(struct vm *vm);
 211 #endif  /* _SYS__CPUSET_H_ */
 212 
 213 static __inline int
 214 vcpu_runblocked(struct vm_eventinfo *info)
 215 {
 216 
 217         return (*info->rptr != 0);
 218 }
 219 
 220 static __inline int
 221 vcpu_suspended(struct vm_eventinfo *info)
 222 {
 223 
 224         return (*info->sptr);
 225 }
 226 
 227 static __inline int
 228 vcpu_reqidle(struct vm_eventinfo *info)
 229 {
 230 
 231         return (*info->iptr);
 232 }
 233 
 234 int vcpu_debugged(struct vm *vm, int vcpuid);
 235 
 236 /*
 237  * Return true if device indicated by bus/slot/func is supposed to be a
 238  * pci passthrough device.
 239  *
 240  * Return false otherwise.
 241  */
 242 bool vmm_is_pptdev(int bus, int slot, int func);
 243 
 244 void *vm_iommu_domain(struct vm *vm);
 245 
 246 enum vcpu_state {
 247         VCPU_IDLE,
 248         VCPU_FROZEN,
 249         VCPU_RUNNING,
 250         VCPU_SLEEPING,
 251 };
 252 
 253 int vcpu_set_state(struct vm *vm, int vcpu, enum vcpu_state state,
 254     bool from_idle);
 255 enum vcpu_state vcpu_get_state(struct vm *vm, int vcpu, int *hostcpu);




  47 
  48 #include <sys/sdt.h>
  49 #include <x86/segments.h>
  50 
  51 SDT_PROVIDER_DECLARE(vmm);
  52 
  53 struct vm;
  54 struct vm_exception;
  55 struct seg_desc;
  56 struct vm_exit;
  57 struct vie;
  58 struct vm_run;
  59 struct vhpet;
  60 struct vioapic;
  61 struct vlapic;
  62 struct vmspace;
  63 struct vm_object;
  64 struct vm_guest_paging;
  65 struct pmap;
  66 






  67 typedef int     (*vmm_init_func_t)(int ipinum);
  68 typedef int     (*vmm_cleanup_func_t)(void);
  69 typedef void    (*vmm_resume_func_t)(void);
  70 typedef void *  (*vmi_init_func_t)(struct vm *vm, struct pmap *pmap);
  71 typedef int     (*vmi_run_func_t)(void *vmi, int vcpu, uint64_t rip,
  72     struct pmap *pmap);
  73 typedef void    (*vmi_cleanup_func_t)(void *vmi);
  74 typedef int     (*vmi_get_register_t)(void *vmi, int vcpu, int num,
  75     uint64_t *retval);
  76 typedef int     (*vmi_set_register_t)(void *vmi, int vcpu, int num,
  77     uint64_t val);
  78 typedef int     (*vmi_get_desc_t)(void *vmi, int vcpu, int num,
  79     struct seg_desc *desc);
  80 typedef int     (*vmi_set_desc_t)(void *vmi, int vcpu, int num,
  81     const struct seg_desc *desc);
  82 typedef int     (*vmi_get_cap_t)(void *vmi, int vcpu, int num, int *retval);
  83 typedef int     (*vmi_set_cap_t)(void *vmi, int vcpu, int num, int val);
  84 typedef struct vmspace *(*vmi_vmspace_alloc)(vm_offset_t min, vm_offset_t max);
  85 typedef void    (*vmi_vmspace_free)(struct vmspace *vmspace);
  86 typedef struct vlapic *(*vmi_vlapic_init)(void *vmi, int vcpu);
  87 typedef void    (*vmi_vlapic_cleanup)(void *vmi, struct vlapic *vlapic);
  88 #ifndef __FreeBSD__
  89 typedef void    (*vmi_savectx)(void *vmi, int vcpu);
  90 typedef void    (*vmi_restorectx)(void *vmi, int vcpu);
  91 #endif
  92 
  93 struct vmm_ops {
  94         vmm_init_func_t         init;           /* module wide initialization */
  95         vmm_cleanup_func_t      cleanup;
  96         vmm_resume_func_t       resume;
  97 
  98         vmi_init_func_t         vminit;         /* vm-specific initialization */
  99         vmi_run_func_t          vmrun;
 100         vmi_cleanup_func_t      vmcleanup;
 101         vmi_get_register_t      vmgetreg;


 148 /*
 149  * APIs that inspect the guest memory map require only a *single* vcpu to
 150  * be frozen. This acts like a read lock on the guest memory map since any
 151  * modification requires *all* vcpus to be frozen.
 152  */
 153 int vm_mmap_getnext(struct vm *vm, vm_paddr_t *gpa, int *segid,
 154     vm_ooffset_t *segoff, size_t *len, int *prot, int *flags);
 155 int vm_get_memseg(struct vm *vm, int ident, size_t *len, bool *sysmem,
 156     struct vm_object **objptr);
 157 vm_paddr_t vmm_sysmem_maxaddr(struct vm *vm);
 158 void *vm_gpa_hold(struct vm *, int vcpuid, vm_paddr_t gpa, size_t len,
 159     int prot, void **cookie);
 160 void vm_gpa_release(void *cookie);
 161 bool vm_mem_allocated(struct vm *vm, int vcpuid, vm_paddr_t gpa);
 162 
 163 int vm_get_register(struct vm *vm, int vcpu, int reg, uint64_t *retval);
 164 int vm_set_register(struct vm *vm, int vcpu, int reg, uint64_t val);
 165 int vm_get_seg_desc(struct vm *vm, int vcpu, int reg,
 166     struct seg_desc *ret_desc);
 167 int vm_set_seg_desc(struct vm *vm, int vcpu, int reg,
 168     const struct seg_desc *desc);
 169 int vm_get_run_state(struct vm *vm, int vcpuid, uint32_t *state,
 170     uint8_t *sipi_vec);
 171 int vm_set_run_state(struct vm *vm, int vcpuid, uint32_t state,
 172     uint8_t sipi_vec);
 173 int vm_run(struct vm *vm, int vcpuid, const struct vm_entry *);
 174 int vm_suspend(struct vm *vm, enum vm_suspend_how how);
 175 int vm_inject_nmi(struct vm *vm, int vcpu);
 176 int vm_nmi_pending(struct vm *vm, int vcpuid);
 177 void vm_nmi_clear(struct vm *vm, int vcpuid);
 178 int vm_inject_extint(struct vm *vm, int vcpu);
 179 int vm_extint_pending(struct vm *vm, int vcpuid);
 180 void vm_extint_clear(struct vm *vm, int vcpuid);
 181 int vm_inject_init(struct vm *vm, int vcpuid);
 182 int vm_inject_sipi(struct vm *vm, int vcpuid, uint8_t vec);
 183 struct vlapic *vm_lapic(struct vm *vm, int cpu);
 184 struct vioapic *vm_ioapic(struct vm *vm);
 185 struct vhpet *vm_hpet(struct vm *vm);
 186 int vm_get_capability(struct vm *vm, int vcpu, int type, int *val);
 187 int vm_set_capability(struct vm *vm, int vcpu, int type, int val);
 188 int vm_get_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state *state);
 189 int vm_set_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state state);
 190 int vm_apicid2vcpuid(struct vm *vm, int apicid);
 191 int vm_activate_cpu(struct vm *vm, int vcpu);
 192 int vm_suspend_cpu(struct vm *vm, int vcpu);
 193 int vm_resume_cpu(struct vm *vm, int vcpu);
 194 struct vm_exit *vm_exitinfo(struct vm *vm, int vcpuid);
 195 struct vie *vm_vie_ctx(struct vm *vm, int vcpuid);
 196 void vm_exit_suspended(struct vm *vm, int vcpuid, uint64_t rip);
 197 void vm_exit_debug(struct vm *vm, int vcpuid, uint64_t rip);

 198 void vm_exit_astpending(struct vm *vm, int vcpuid, uint64_t rip);
 199 void vm_exit_reqidle(struct vm *vm, int vcpuid, uint64_t rip);
 200 void vm_exit_run_state(struct vm *vm, int vcpuid, uint64_t rip);
 201 int vm_service_mmio_read(struct vm *vm, int cpuid, uint64_t gpa, uint64_t *rval,
 202     int rsize);
 203 int vm_service_mmio_write(struct vm *vm, int cpuid, uint64_t gpa, uint64_t wval,
 204     int wsize);

 205 
 206 #ifdef _SYS__CPUSET_H_
 207 cpuset_t vm_active_cpus(struct vm *vm);
 208 cpuset_t vm_debug_cpus(struct vm *vm);
 209 cpuset_t vm_suspended_cpus(struct vm *vm);
 210 #endif  /* _SYS__CPUSET_H_ */
 211 
 212 bool vcpu_entry_bailout_checks(struct vm *vm, int vcpuid, uint64_t rip);
 213 bool vcpu_run_state_pending(struct vm *vm, int vcpuid);
 214 int vcpu_arch_reset(struct vm *vm, int vcpuid, bool init_only);
 215 



















 216 /*
 217  * Return true if device indicated by bus/slot/func is supposed to be a
 218  * pci passthrough device.
 219  *
 220  * Return false otherwise.
 221  */
 222 bool vmm_is_pptdev(int bus, int slot, int func);
 223 
 224 void *vm_iommu_domain(struct vm *vm);
 225 
 226 enum vcpu_state {
 227         VCPU_IDLE,
 228         VCPU_FROZEN,
 229         VCPU_RUNNING,
 230         VCPU_SLEEPING,
 231 };
 232 
 233 int vcpu_set_state(struct vm *vm, int vcpu, enum vcpu_state state,
 234     bool from_idle);
 235 enum vcpu_state vcpu_get_state(struct vm *vm, int vcpu, int *hostcpu);