On Mon, May 02, 2022 at 04:09:19PM -0400, Dave Voutila wrote:
>
> Dave Voutila <[email protected]> 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
>