On Mon, May 02, 2022 at 04:09:19PM -0400, Dave Voutila wrote:
>
> Dave Voutila <d...@sisu.io> writes:
>
> > tech@,
> >
> > tl;dr: standardize vmd/vmm/vmctl on counting memory in bytes at all
> > times instead of a mix of MiB and bytes.
> >
> > There's some design friction between vmd(8)/vmctl(8) and vmm(4).
> >
> > For instance, the user-facing code deals in MiB, but internally a vm's
> > memory ranges are defined in terms of bytes...but only after being
> > converted at vm launch.
> >
> > Consequently, at different points in vmd's lifecycle, the same struct
> > member for storing a vm's requested memory size contains a value in
> > bytes OR in MiB meaning any code accessing the value needs to be
> > contextually aware of if/when the value must be scaled.
> >
> > Given we dropped vmm(4) on i386 awhile ago, let's make use of 64-bit
> > values! Plus this helps my other queued up changes simpler as they can
> > avoid confusing scaling at points.
> >
> > There *is* some existing code duplication between vmd/vmctl related to
> > parsing user provided memory values via scan_scaled(3), but I'm not
> > looking to consolidate that now.
> >
> > If you're going to test, you'll need to build the kernel and either copy
> > or link the patched vmmvar.h into /usr/include/machine/ before building
> > vmd(8)/vmctl(8). (Don't forget to actually boot the kernel.)
> >
> > Otherwise, looking for ok's so I can continue squashing a few bugs in
> > vmd that will be easier/cleaner to fix once this goes in.
> >
> > While the diff looks long-ish, it shouldn't require deep vmm/vmd
> > knowledge to help review ;)
> >
>
> Updated with a fix (printing wrong limit value) and a tweak (checking a
> size_t == 0 vs < 1). No functional changes so if by chance you already
> applied the previous, please feel free to continue to test.
>
> -dv
>

Thanks. ok mlarkin@

-ml

>
> diff refs/heads/master refs/heads/vmd-bytes
> blob - 765fc19bca559dbfd83cd14c48dee94f86c4b3cc
> blob + 699798c1bbffafe7074fea43755ef7e20f073a90
> --- sys/arch/amd64/amd64/vmm.c
> +++ sys/arch/amd64/amd64/vmm.c
> @@ -1575,7 +1575,7 @@ vm_create_check_mem_ranges(struct vm_create_params *vc
>  {
>       size_t i, memsize = 0;
>       struct vm_mem_range *vmr, *pvmr;
> -     const paddr_t maxgpa = (uint64_t)VMM_MAX_VM_MEM_SIZE * 1024 * 1024;
> +     const paddr_t maxgpa = VMM_MAX_VM_MEM_SIZE;
>
>       if (vcp->vcp_nmemranges == 0 ||
>           vcp->vcp_nmemranges > VMM_MAX_MEM_RANGES)
> blob - 94bb172832d4c2847b1e83ebb9cc05538db6ac80
> blob + 012a023943b9fbc70339166889070ff0b4619046
> --- sys/arch/amd64/include/vmmvar.h
> +++ sys/arch/amd64/include/vmmvar.h
> @@ -31,7 +31,7 @@
>  #define VMM_MAX_KERNEL_PATH  128
>  #define VMM_MAX_VCPUS                512
>  #define VMM_MAX_VCPUS_PER_VM 64
> -#define VMM_MAX_VM_MEM_SIZE  32768
> +#define VMM_MAX_VM_MEM_SIZE  32L * 1024 * 1024 * 1024        /* 32 GiB */
>  #define VMM_MAX_NICS_PER_VM  4
>
>  #define VMM_PCI_MMIO_BAR_BASE        0xF0000000ULL
> blob - 0f7e4329a00d54a64fe41e1fb2bd2afcbaa9d68a
> blob + c54aebcb982fdc14cc7a02910301d561e6623e4d
> --- usr.sbin/vmctl/main.c
> +++ usr.sbin/vmctl/main.c
> @@ -404,24 +404,39 @@ parse_network(struct parse_result *res, char *word)
>  int
>  parse_size(struct parse_result *res, char *word)
>  {
> -     long long val = 0;
> +     char             result[FMT_SCALED_STRSIZE];
> +     long long        val = 0;
>
>       if (word != NULL) {
>               if (scan_scaled(word, &val) != 0) {
> -                     warn("invalid size: %s", word);
> +                     warn("invalid memory size: %s", word);
>                       return (-1);
>               }
>       }
>
>       if (val < (1024 * 1024)) {
> -             warnx("size must be at least one megabyte");
> +             warnx("memory size must be at least 1M");
>               return (-1);
> -     } else
> -             res->size = val / 1024 / 1024;
> +     }
>
> -     if ((res->size * 1024 * 1024) != val)
> -             warnx("size rounded to %lld megabytes", res->size);
> +     if (val > VMM_MAX_VM_MEM_SIZE) {
> +             if (fmt_scaled(VMM_MAX_VM_MEM_SIZE, result) == 0)
> +                     warnx("memory size too large (limit is %s)", result);
> +             else
> +                     warnx("memory size too large");
> +             return (-1);
> +     }
>
> +     /* Round down to the megabyte. */
> +     res->size = (val / (1024 * 1024)) * (1024 * 1024);
> +
> +     if (res->size != (size_t)val) {
> +             if (fmt_scaled(res->size, result) == 0)
> +                     warnx("memory size rounded to %s", result);
> +             else
> +                     warnx("memory size rounded to %zu bytes", res->size);
> +     }
> +
>       return (0);
>  }
>
> blob - 4c0b62fc6e16adbeb5cf951dcafbaebdbc356da8
> blob + 15e6dd89ec15fa2501dcf6539c9ae9d90879ba56
> --- usr.sbin/vmctl/vmctl.c
> +++ usr.sbin/vmctl/vmctl.c
> @@ -73,7 +73,7 @@ struct imsgbuf *ibuf;
>   *  ENOMEM if a memory allocation failure occurred.
>   */
>  int
> -vm_start(uint32_t start_id, const char *name, int memsize, int nnics,
> +vm_start(uint32_t start_id, const char *name, size_t memsize, int nnics,
>      char **nics, int ndisks, char **disks, int *disktypes, char *kernel,
>      char *iso, char *instance, unsigned int bootdevice)
>  {
> @@ -122,7 +122,7 @@ vm_start(uint32_t start_id, const char *name, int mems
>
>       /*
>        * XXX: vmd(8) fills in the actual memory ranges. vmctl(8)
> -      * just passes in the actual memory size in MB here.
> +      * just passes in the actual memory size here.
>        */
>       vcp->vcp_nmemranges = 1;
>       vcp->vcp_memranges[0].vmr_size = memsize;
> blob - 4fd2b787debb3a0e6bea0eced9508fcce3a09991
> blob + 7d44c88f8fac106508807edcad393334d806edf2
> --- usr.sbin/vmctl/vmctl.h
> +++ usr.sbin/vmctl/vmctl.h
> @@ -48,7 +48,7 @@ struct parse_result {
>       char                    *name;
>       char                    *path;
>       char                    *isopath;
> -     long long                size;
> +     size_t                   size;
>       int                      nifs;
>       char                    **nets;
>       int                      nnets;
> @@ -93,7 +93,7 @@ int  open_imagefile(int, const char *, int,
>  int   create_imagefile(int, const char *, const char *, long, const char **);
>  int   create_raw_imagefile(const char *, long);
>  int   create_qc2_imagefile(const char *, const char *, long);
> -int   vm_start(uint32_t, const char *, int, int, char **, int,
> +int   vm_start(uint32_t, const char *, size_t, int, char **, int,
>           char **, int *, char *, char *, char *, unsigned int);
>  int   vm_start_complete(struct imsg *, int *, int);
>  void  terminate_vm(uint32_t, const char *, unsigned int);
> blob - ebebbf24750b075414dc872d1290a0bf9c20d52b
> blob + d37e53e6e7eeeb1f5b907ebb10d6a3793bd21ffd
> --- usr.sbin/vmd/parse.y
> +++ usr.sbin/vmd/parse.y
> @@ -1248,26 +1248,42 @@ symget(const char *nam)
>  ssize_t
>  parse_size(char *word, int64_t val)
>  {
> +     char             result[FMT_SCALED_STRSIZE];
>       ssize_t          size;
>       long long        res;
>
>       if (word != NULL) {
>               if (scan_scaled(word, &res) != 0) {
> -                     log_warn("invalid size: %s", word);
> +                     log_warn("invalid memory size: %s", word);
>                       return (-1);
>               }
>               val = (int64_t)res;
>       }
>
>       if (val < (1024 * 1024)) {
> -             log_warnx("size must be at least one megabyte");
> +             log_warnx("memory size must be at least 1M");
>               return (-1);
> -     } else
> -             size = val / 1024 / 1024;
> +     }
>
> -     if ((size * 1024 * 1024) != val)
> -             log_warnx("size rounded to %zd megabytes", size);
> +     if (val > VMM_MAX_VM_MEM_SIZE) {
> +             if (fmt_scaled(VMM_MAX_VM_MEM_SIZE, result) == 0)
> +                     log_warnx("memory size too large (limit is %s)",
> +                         result);
> +             else
> +                     log_warnx("memory size too large");
> +             return (-1);
> +     }
>
> +     /* Round down to the megabyte. */
> +     size = (val / (1024 * 1024)) * (1024 * 1024);
> +
> +     if (size != val) {
> +             if (fmt_scaled(size, result) == 0)
> +                     log_warnx("memory size rounded to %s", result);
> +             else
> +                     log_warnx("memory size rounded to %zd bytes", size);
> +     }
> +
>       return ((ssize_t)size);
>  }
>
> blob - 55d938ed1d118f204dc19492148fc171080c6961
> blob + fd63bf9ae5a84aee992473714efd939f37612094
> --- usr.sbin/vmd/vm.c
> +++ usr.sbin/vmd/vm.c
> @@ -871,15 +871,13 @@ vcpu_reset(uint32_t vmid, uint32_t vcpu_id, struct vcp
>  void
>  create_memory_map(struct vm_create_params *vcp)
>  {
> -     size_t len, mem_bytes, mem_mb;
> +     size_t len, mem_bytes;
>
> -     mem_mb = vcp->vcp_memranges[0].vmr_size;
> +     mem_bytes = vcp->vcp_memranges[0].vmr_size;
>       vcp->vcp_nmemranges = 0;
> -     if (mem_mb < 1 || mem_mb > VMM_MAX_VM_MEM_SIZE)
> +     if (mem_bytes == 0 || mem_bytes > VMM_MAX_VM_MEM_SIZE)
>               return;
>
> -     mem_bytes = mem_mb * 1024 * 1024;
> -
>       /* First memory region: 0 - LOWMEM_KB (DOS low mem) */
>       len = LOWMEM_KB * 1024;
>       vcp->vcp_memranges[0].vmr_gpa = 0x0;
> blob - 5f33b64831792420fd9231f0b76b11f31ad6b31c
> blob + 4d2a5a4aecf78957b3b035c1a5b5e9449f6fe769
> --- usr.sbin/vmd/vmd.h
> +++ usr.sbin/vmd/vmd.h
> @@ -56,7 +56,7 @@
>  #define MAX_TAP                      256
>  #define NR_BACKLOG           5
>  #define VMD_SWITCH_TYPE              "bridge"
> -#define VM_DEFAULT_MEMORY    512
> +#define VM_DEFAULT_MEMORY    512 * 1024 * 1024       /* 512 MiB */
>
>  #define VMD_DEFAULT_STAGGERED_START_DELAY 30
>

Reply via email to