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>


  39  *
  40  * Copyright 2020 Oxide Computer Company
  41  */
  42 
  43 #include <sys/cdefs.h>
  44 __FBSDID("$FreeBSD$");
  45 
  46 #include <sys/param.h>
  47 #include <sys/types.h>
  48 
  49 #include <machine/vmm.h>
  50 #include <vmmapi.h>
  51 
  52 #include <stdio.h>
  53 #include <stdlib.h>
  54 #include <assert.h>
  55 
  56 #include "bhyverun.h"
  57 #include "spinup_ap.h"
  58 

  59 static void
  60 spinup_ap_realmode(struct vmctx *ctx, int newcpu, uint64_t *rip)
  61 {
  62         int vector, error;
  63         uint16_t cs;
  64         uint64_t desc_base;
  65         uint32_t desc_limit, desc_access;
  66 
  67         vector = *rip >> PAGE_SHIFT;
  68         *rip = 0;
  69 
  70         /*
  71          * Update the %cs and %rip of the guest so that it starts
  72          * executing real mode code at at 'vector << 12'.
  73          */
  74         error = vm_set_register(ctx, newcpu, VM_REG_GUEST_RIP, *rip);
  75         assert(error == 0);
  76 
  77         error = vm_get_desc(ctx, newcpu, VM_REG_GUEST_CS, &desc_base,
  78                             &desc_limit, &desc_access);


  84         assert(error == 0);
  85 
  86         cs = (vector << PAGE_SHIFT) >> 4;
  87         error = vm_set_register(ctx, newcpu, VM_REG_GUEST_CS, cs);
  88         assert(error == 0);
  89 }
  90 
  91 int
  92 spinup_ap(struct vmctx *ctx, int vcpu, int newcpu, uint64_t rip)
  93 {
  94         int error;
  95 
  96         assert(newcpu != 0);
  97         assert(newcpu < guest_ncpus);
  98 
  99         error = vcpu_reset(ctx, newcpu);
 100         assert(error == 0);
 101 
 102         fbsdrun_set_capabilities(ctx, newcpu);
 103 
 104 #ifdef __FreeBSD__
 105         /*
 106          * Enable the 'unrestricted guest' mode for 'newcpu'.
 107          *
 108          * Set up the processor state in power-on 16-bit mode, with the CS:IP
 109          * init'd to the specified low-mem 4K page.
 110          */
 111         error = vm_set_capability(ctx, newcpu, VM_CAP_UNRESTRICTED_GUEST, 1);
 112         assert(error == 0);
 113 #else
 114         /* Unrestricted Guest is always enabled on illumos */
 115 #endif
 116 
 117         spinup_ap_realmode(ctx, newcpu, &rip);
 118 
 119 #ifdef __FreeBSD__
 120         fbsdrun_addcpu(ctx, vcpu, newcpu, rip);
 121 #else
 122         fbsdrun_addcpu(ctx, vcpu, newcpu, rip, false);
 123 #endif
 124 
 125         return (newcpu);
 126 }






















  39  *
  40  * Copyright 2020 Oxide Computer Company
  41  */
  42 
  43 #include <sys/cdefs.h>
  44 __FBSDID("$FreeBSD$");
  45 
  46 #include <sys/param.h>
  47 #include <sys/types.h>
  48 
  49 #include <machine/vmm.h>
  50 #include <vmmapi.h>
  51 
  52 #include <stdio.h>
  53 #include <stdlib.h>
  54 #include <assert.h>
  55 
  56 #include "bhyverun.h"
  57 #include "spinup_ap.h"
  58 
  59 #ifdef __FreeBSD__
  60 static void
  61 spinup_ap_realmode(struct vmctx *ctx, int newcpu, uint64_t *rip)
  62 {
  63         int vector, error;
  64         uint16_t cs;
  65         uint64_t desc_base;
  66         uint32_t desc_limit, desc_access;
  67 
  68         vector = *rip >> PAGE_SHIFT;
  69         *rip = 0;
  70 
  71         /*
  72          * Update the %cs and %rip of the guest so that it starts
  73          * executing real mode code at at 'vector << 12'.
  74          */
  75         error = vm_set_register(ctx, newcpu, VM_REG_GUEST_RIP, *rip);
  76         assert(error == 0);
  77 
  78         error = vm_get_desc(ctx, newcpu, VM_REG_GUEST_CS, &desc_base,
  79                             &desc_limit, &desc_access);


  85         assert(error == 0);
  86 
  87         cs = (vector << PAGE_SHIFT) >> 4;
  88         error = vm_set_register(ctx, newcpu, VM_REG_GUEST_CS, cs);
  89         assert(error == 0);
  90 }
  91 
  92 int
  93 spinup_ap(struct vmctx *ctx, int vcpu, int newcpu, uint64_t rip)
  94 {
  95         int error;
  96 
  97         assert(newcpu != 0);
  98         assert(newcpu < guest_ncpus);
  99 
 100         error = vcpu_reset(ctx, newcpu);
 101         assert(error == 0);
 102 
 103         fbsdrun_set_capabilities(ctx, newcpu);
 104 

 105         /*
 106          * Enable the 'unrestricted guest' mode for 'newcpu'.
 107          *
 108          * Set up the processor state in power-on 16-bit mode, with the CS:IP
 109          * init'd to the specified low-mem 4K page.
 110          */
 111         error = vm_set_capability(ctx, newcpu, VM_CAP_UNRESTRICTED_GUEST, 1);
 112         assert(error == 0);



 113 
 114         spinup_ap_realmode(ctx, newcpu, &rip);
 115 

 116         fbsdrun_addcpu(ctx, vcpu, newcpu, rip);



 117 
 118         return (newcpu);
 119 }
 120 #else /* __FreeBSD__ */
 121 void
 122 spinup_halted_ap(struct vmctx *ctx, int newcpu)
 123 {
 124         int error;
 125 
 126         assert(newcpu != 0);
 127         assert(newcpu < guest_ncpus);
 128 
 129         error = vcpu_reset(ctx, newcpu);
 130         assert(error == 0);
 131 
 132         fbsdrun_set_capabilities(ctx, newcpu);
 133 
 134         error = vm_set_run_state(ctx, newcpu, VRS_HALT, 0);
 135         assert(error == 0);
 136 
 137         fbsdrun_addcpu(ctx, newcpu, 0, false);
 138 }
 139 #endif /* __FreeBSD__ */