We currently keep Guest memory pointer and size in globals. We move this into a structure and explicitly hand that to to_guest_phys() and from_guest_phys() so we can deal with other Guests' memory. Signed-off-by: Rusty Russell <rusty@xxxxxxxxxxxxxxx> --- Documentation/lguest/lguest.c | 89 +++++++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 40 deletions(-) diff -r 95558c7d210e Documentation/lguest/lguest.c --- a/Documentation/lguest/lguest.c Thu Mar 13 14:11:40 2008 +1100 +++ b/Documentation/lguest/lguest.c Thu Mar 13 23:05:35 2008 +1100 @@ -76,10 +76,20 @@ static bool verbose; /* The pipe to send commands to the waker process */ static int waker_fd; -/* The pointer to the start of guest memory. */ -static void *guest_base; -/* The maximum guest physical address allowed, and maximum possible. */ -static unsigned long guest_limit, guest_max; + +struct guest_memory +{ + /* The pointer to the start of guest memory. */ + void *base; + /* The maximum guest physical address allowed. */ + unsigned long limit; +}; + +/* The maximum possible page for the guest. */ +static unsigned long guest_max; + +/* This Guest's memory. */ +static struct guest_memory gmem; /* a per-cpu variable indicating whose vcpu is currently running */ static unsigned int __thread cpu_id; @@ -207,20 +217,19 @@ static u8 *get_feature_bits(struct devic * will get you through this section. Or, maybe not. * * The Launcher sets up a big chunk of memory to be the Guest's "physical" - * memory and stores it in "guest_base". In other words, Guest physical == - * Launcher virtual with an offset. + * memory. In other words, Guest physical == Launcher virtual with an offset. * * This can be tough to get your head around, but usually it just means that we * use these trivial conversion functions when the Guest gives us it's * "physical" addresses: */ -static void *from_guest_phys(unsigned long addr) +static void *from_guest_phys(struct guest_memory *mem, unsigned long addr) { - return guest_base + addr; + return mem->base + addr; } -static unsigned long to_guest_phys(const void *addr) +static unsigned long to_guest_phys(struct guest_memory *mem, const void *addr) { - return (addr - guest_base); + return (addr - mem->base); } /*L:130 @@ -287,10 +296,10 @@ static void *map_zeroed_pages(unsigned i /* Get some more pages for a device. */ static void *get_pages(unsigned int num) { - void *addr = from_guest_phys(guest_limit); + void *addr = from_guest_phys(&gmem, gmem.limit); - guest_limit += num * getpagesize(); - if (guest_limit > guest_max) + gmem.limit += num * getpagesize(); + if (gmem.limit > guest_max) errx(1, "Not enough memory for devices"); return addr; } @@ -351,7 +360,7 @@ static unsigned long map_elf(int elf_fd, i, phdr[i].p_memsz, (void *)phdr[i].p_paddr); /* We map this section of the file at its physical address. */ - map_at(elf_fd, from_guest_phys(phdr[i].p_paddr), + map_at(elf_fd, from_guest_phys(&gmem, phdr[i].p_paddr), phdr[i].p_offset, phdr[i].p_filesz); } @@ -371,7 +380,7 @@ static unsigned long load_bzimage(int fd struct boot_params boot; int r; /* Modern bzImages get loaded at 1M. */ - void *p = from_guest_phys(0x100000); + void *p = from_guest_phys(&gmem, 0x100000); /* Go back to the start of the file and read the header. It should be * a Linux boot header (see Documentation/i386/boot.txt) */ @@ -444,7 +453,7 @@ static unsigned long load_initrd(const c /* We map the initrd at the top of memory, but mmap wants it to be * page-aligned, so we round the size up for that. */ len = page_align(st.st_size); - map_at(ifd, from_guest_phys(mem - len), 0, st.st_size); + map_at(ifd, from_guest_phys(&gmem, mem - len), 0, st.st_size); /* Once a file is mapped, you can close the file descriptor. It's a * little odd, but quite useful. */ close(ifd); @@ -473,7 +482,7 @@ static unsigned long setup_pagetables(un linear_pages = (mapped_pages + ptes_per_page-1)/ptes_per_page; /* We put the toplevel page directory page at the top of memory. */ - pgdir = from_guest_phys(mem) - initrd_size - getpagesize(); + pgdir = from_guest_phys(&gmem, mem) - initrd_size - getpagesize(); /* Now we use the next linear_pages pages as pte pages */ linear = (void *)pgdir - linear_pages*getpagesize(); @@ -487,16 +496,16 @@ static unsigned long setup_pagetables(un /* The top level points to the linear page table pages above. */ for (i = 0; i < mapped_pages; i += ptes_per_page) { pgdir[i/ptes_per_page] - = ((to_guest_phys(linear) + i*sizeof(void *)) + = ((to_guest_phys(&gmem, linear) + i*sizeof(void *)) | PAGE_PRESENT); } verbose("Linear mapping of %u pages in %u pte pages at %#lx\n", - mapped_pages, linear_pages, to_guest_phys(linear)); + mapped_pages, linear_pages, to_guest_phys(&gmem, linear)); /* We return the top level (guest-physical) address: the kernel needs * to know where it is. */ - return to_guest_phys(pgdir); + return to_guest_phys(&gmem, pgdir); } /*:*/ @@ -525,12 +534,12 @@ static int tell_kernel(unsigned long pgd static int tell_kernel(unsigned long pgdir, unsigned long start) { unsigned long args[] = { LHREQ_INITIALIZE, - (unsigned long)guest_base, - guest_limit / getpagesize(), pgdir, start }; + (unsigned long)gmem.base, + gmem.limit / getpagesize(), pgdir, start }; int fd; verbose("Guest: %p - %p (%#lx)\n", - guest_base, guest_base + guest_limit, guest_limit); + gmem.base, gmem.base + gmem.limit, gmem.limit); fd = open_or_die("/dev/lguest", O_RDWR); if (write(fd, args, sizeof(args)) < 0) err(1, "Writing to /dev/lguest"); @@ -629,18 +638,18 @@ static int setup_waker(int lguest_fd) * if something funny is going on: */ static void *_check_pointer(unsigned long addr, unsigned int size, - unsigned int line) + struct guest_memory *mem, unsigned int line) { /* We have to separately check addr and addr+size, because size could * be huge and addr + size might wrap around. */ - if (addr >= guest_limit || addr + size >= guest_limit) + if (addr >= mem->limit || addr + size >= mem->limit) errx(1, "%s:%i: Invalid address %#lx", __FILE__, line, addr); /* We return a pointer for the caller's convenience, now we know it's * safe to use. */ - return from_guest_phys(addr); + return from_guest_phys(&gmem, addr); } /* A macro which transparently hands the line number to the real function. */ -#define check_pointer(addr,size) _check_pointer(addr, size, __LINE__) +#define check_pointer(mem,addr,size) _check_pointer(addr, size, mem, __LINE__) /* Each buffer in the virtqueues is actually a chain of descriptors. This * function returns the next descriptor in the chain, or vq->vring.num if we're @@ -702,7 +711,7 @@ static unsigned get_vq_desc(struct virtq /* Grab the first descriptor, and check it's OK. */ iov[*out_num + *in_num].iov_len = vq->vring.desc[i].len; iov[*out_num + *in_num].iov_base - = check_pointer(vq->vring.desc[i].addr, + = check_pointer(&gmem, vq->vring.desc[i].addr, vq->vring.desc[i].len); /* If this is an input descriptor, increment that count. */ if (vq->vring.desc[i].flags & VRING_DESC_F_WRITE) @@ -975,7 +984,7 @@ static void handle_output(int fd, unsign /* Check each device and virtqueue. */ for (i = devices.dev; i; i = i->next) { /* Notifications to device descriptors reset the device. */ - if (from_guest_phys(addr) == i->desc) { + if (from_guest_phys(&gmem, addr) == i->desc) { reset_device(i); return; } @@ -1002,11 +1011,11 @@ static void handle_output(int fd, unsign /* Early console write is done using notify on a nul-terminated string * in Guest memory. */ - if (addr >= guest_limit) + if (addr >= gmem.limit) errx(1, "Bad NOTIFY %#lx", addr); - write(STDOUT_FILENO, from_guest_phys(addr), - strnlen(from_guest_phys(addr), guest_limit - addr)); + write(STDOUT_FILENO, from_guest_phys(&gmem, addr), + strnlen(from_guest_phys(&gmem, addr), gmem.limit - addr)); } /* This is called when the Waker wakes us up: check for incoming file @@ -1112,7 +1121,7 @@ static void add_virtqueue(struct device /* Initialize the configuration. */ vq->config.num = num_descs; vq->config.irq = devices.next_irq++; - vq->config.pfn = to_guest_phys(p) / getpagesize(); + vq->config.pfn = to_guest_phys(&gmem, p) / getpagesize(); /* Initialize the vring. */ vring_init(&vq->vring, num_descs, p, getpagesize()); @@ -1125,7 +1134,7 @@ static void add_virtqueue(struct device memcpy(device_config(dev), &vq->config, sizeof(vq->config)); dev->desc->num_vq++; - verbose("Virtqueue page %#lx\n", to_guest_phys(p)); + verbose("Virtqueue page %#lx\n", to_guest_phys(&gmem, p)); /* Add to tail of list, so dev->vq is first vq, dev->vq->next is * second. */ @@ -1731,9 +1740,9 @@ int main(int argc, char *argv[]) * guest-physical memory range. This fills it with 0, * and ensures that the Guest won't be killed when it * tries to access it. */ - guest_base = map_zeroed_pages(mem / getpagesize() - + DEVICE_PAGES); - guest_limit = mem; + gmem.base = map_zeroed_pages(mem / getpagesize() + + DEVICE_PAGES); + gmem.limit = mem; guest_max = mem + DEVICE_PAGES*getpagesize(); devices.descpage = get_pages(1); break; @@ -1765,7 +1774,7 @@ int main(int argc, char *argv[]) if (optind + 2 > argc) usage(); - verbose("Guest base is at %p\n", guest_base); + verbose("Guest base is at %p\n", gmem.base); /* We always have a console device */ setup_console(); @@ -1774,7 +1783,7 @@ int main(int argc, char *argv[]) start = load_kernel(open_or_die(argv[optind+1], O_RDONLY)); /* Boot information is stashed at physical address 0 */ - boot = from_guest_phys(0); + boot = from_guest_phys(&gmem, 0); /* Map the initrd image if requested (at top of physical memory) */ if (initrd_name) { @@ -1796,7 +1805,7 @@ int main(int argc, char *argv[]) boot->e820_map[0] = ((struct e820entry) { 0, mem, E820_RAM }); /* The boot header contains a command line pointer: we put the command * line after the boot header. */ - boot->hdr.cmd_line_ptr = to_guest_phys(boot + 1); + boot->hdr.cmd_line_ptr = to_guest_phys(&gmem, boot + 1); /* We use a simple helper to copy the arguments separated by spaces. */ concat((char *)(boot + 1), argv+optind+2); _______________________________________________ Virtualization mailing list Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/virtualization