From bc685f586e86605b5052138b20b0a52e90c6207e Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Wed, 5 Sep 2012 10:31:54 +0200 Subject: [PATCH] kvm tools: pci-shmem init-exit Make the init/exit of pci-shmem self-contained, so the global init code won't need to check if it was selected or not. Also move the parser out of builtin-run into the pci-shmem code. Signed-off-by: Sasha Levin Signed-off-by: Pekka Enberg --- tools/kvm/builtin-run.c | 134 ++-------------------------- tools/kvm/hw/pci-shmem.c | 143 +++++++++++++++++++++++++++++- tools/kvm/include/kvm/pci-shmem.h | 6 +- 3 files changed, 153 insertions(+), 130 deletions(-) diff --git a/tools/kvm/builtin-run.c b/tools/kvm/builtin-run.c index 236078aeda32..d1e7d631f010 100644 --- a/tools/kvm/builtin-run.c +++ b/tools/kvm/builtin-run.c @@ -237,130 +237,6 @@ done: return 0; } -static int shmem_parser(const struct option *opt, const char *arg, int unset) -{ - const u64 default_size = SHMEM_DEFAULT_SIZE; - const u64 default_phys_addr = SHMEM_DEFAULT_ADDR; - const char *default_handle = SHMEM_DEFAULT_HANDLE; - struct shmem_info *si = malloc(sizeof(struct shmem_info)); - u64 phys_addr; - u64 size; - char *handle = NULL; - int create = 0; - const char *p = arg; - char *next; - int base = 10; - int verbose = 0; - - const int skip_pci = strlen("pci:"); - if (verbose) - pr_info("shmem_parser(%p,%s,%d)", opt, arg, unset); - /* parse out optional addr family */ - if (strcasestr(p, "pci:")) { - p += skip_pci; - } else if (strcasestr(p, "mem:")) { - die("I can't add to E820 map yet.\n"); - } - /* parse out physical addr */ - base = 10; - if (strcasestr(p, "0x")) - base = 16; - phys_addr = strtoll(p, &next, base); - if (next == p && phys_addr == 0) { - pr_info("shmem: no physical addr specified, using default."); - phys_addr = default_phys_addr; - } - if (*next != ':' && *next != '\0') - die("shmem: unexpected chars after phys addr.\n"); - if (*next == '\0') - p = next; - else - p = next + 1; - /* parse out size */ - base = 10; - if (strcasestr(p, "0x")) - base = 16; - size = strtoll(p, &next, base); - if (next == p && size == 0) { - pr_info("shmem: no size specified, using default."); - size = default_size; - } - /* look for [KMGkmg][Bb]* uses base 2. */ - int skip_B = 0; - if (strspn(next, "KMGkmg")) { /* might have a prefix */ - if (*(next + 1) == 'B' || *(next + 1) == 'b') - skip_B = 1; - switch (*next) { - case 'K': - case 'k': - size = size << KB_SHIFT; - break; - case 'M': - case 'm': - size = size << MB_SHIFT; - break; - case 'G': - case 'g': - size = size << GB_SHIFT; - break; - default: - die("shmem: bug in detecting size prefix."); - break; - } - next += 1 + skip_B; - } - if (*next != ':' && *next != '\0') { - die("shmem: unexpected chars after phys size. <%c><%c>\n", - *next, *p); - } - if (*next == '\0') - p = next; - else - p = next + 1; - /* parse out optional shmem handle */ - const int skip_handle = strlen("handle="); - next = strcasestr(p, "handle="); - if (*p && next) { - if (p != next) - die("unexpected chars before handle\n"); - p += skip_handle; - next = strchrnul(p, ':'); - if (next - p) { - handle = malloc(next - p + 1); - strncpy(handle, p, next - p); - handle[next - p] = '\0'; /* just in case. */ - } - if (*next == '\0') - p = next; - else - p = next + 1; - } - /* parse optional create flag to see if we should create shm seg. */ - if (*p && strcasestr(p, "create")) { - create = 1; - p += strlen("create"); - } - if (*p != '\0') - die("shmem: unexpected trailing chars\n"); - if (handle == NULL) { - handle = malloc(strlen(default_handle) + 1); - strcpy(handle, default_handle); - } - if (verbose) { - pr_info("shmem: phys_addr = %llx", phys_addr); - pr_info("shmem: size = %llx", size); - pr_info("shmem: handle = %s", handle); - pr_info("shmem: create = %d", create); - } - - si->phys_addr = phys_addr; - si->size = size; - si->handle = handle; - si->create = create; - pci_shmem__register_mem(si); /* ownership of si, etc. passed on. */ - return 0; -} - #define BUILD_OPTIONS(name, cfg, kvm) \ struct option name[] = { \ OPT_GROUP("Basic options:"), \ @@ -1174,7 +1050,11 @@ static int kvm_cmd_run_init(int argc, const char **argv) kbd__init(kvm); #endif - pci_shmem__init(kvm); + r = pci_shmem__init(kvm); + if (r < 0) { + pr_err("pci_shmem__init() failed with error %d\n", r); + goto fail; + } if (kvm->cfg.vnc || kvm->cfg.sdl) { fb = vesa__init(kvm); @@ -1298,6 +1178,10 @@ static void kvm_cmd_run_exit(int guest_ret) if (r < 0) pr_warning("virtio_console__exit() failed with error %d\n", r); + r = pci_shmem__exit(kvm); + if (r < 0) + pr_warning("pci_shmem__exit() failed with error %d\n", r); + r = disk_image__exit(kvm); if (r < 0) pr_warning("disk_image__exit() failed with error %d\n", r); diff --git a/tools/kvm/hw/pci-shmem.c b/tools/kvm/hw/pci-shmem.c index ac2d264cf733..47bb337f4476 100644 --- a/tools/kvm/hw/pci-shmem.c +++ b/tools/kvm/hw/pci-shmem.c @@ -13,6 +13,10 @@ #include #include +#define MB_SHIFT (20) +#define KB_SHIFT (10) +#define GB_SHIFT (30) + static struct pci_device_header pci_shmem_pci_device = { .vendor_id = cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET), .device_id = cpu_to_le16(0x1110), @@ -216,6 +220,130 @@ static void *setup_shmem(const char *key, size_t len, int creating) return mem; } +int shmem_parser(const struct option *opt, const char *arg, int unset) +{ + const u64 default_size = SHMEM_DEFAULT_SIZE; + const u64 default_phys_addr = SHMEM_DEFAULT_ADDR; + const char *default_handle = SHMEM_DEFAULT_HANDLE; + struct shmem_info *si = malloc(sizeof(struct shmem_info)); + u64 phys_addr; + u64 size; + char *handle = NULL; + int create = 0; + const char *p = arg; + char *next; + int base = 10; + int verbose = 0; + + const int skip_pci = strlen("pci:"); + if (verbose) + pr_info("shmem_parser(%p,%s,%d)", opt, arg, unset); + /* parse out optional addr family */ + if (strcasestr(p, "pci:")) { + p += skip_pci; + } else if (strcasestr(p, "mem:")) { + die("I can't add to E820 map yet.\n"); + } + /* parse out physical addr */ + base = 10; + if (strcasestr(p, "0x")) + base = 16; + phys_addr = strtoll(p, &next, base); + if (next == p && phys_addr == 0) { + pr_info("shmem: no physical addr specified, using default."); + phys_addr = default_phys_addr; + } + if (*next != ':' && *next != '\0') + die("shmem: unexpected chars after phys addr.\n"); + if (*next == '\0') + p = next; + else + p = next + 1; + /* parse out size */ + base = 10; + if (strcasestr(p, "0x")) + base = 16; + size = strtoll(p, &next, base); + if (next == p && size == 0) { + pr_info("shmem: no size specified, using default."); + size = default_size; + } + /* look for [KMGkmg][Bb]* uses base 2. */ + int skip_B = 0; + if (strspn(next, "KMGkmg")) { /* might have a prefix */ + if (*(next + 1) == 'B' || *(next + 1) == 'b') + skip_B = 1; + switch (*next) { + case 'K': + case 'k': + size = size << KB_SHIFT; + break; + case 'M': + case 'm': + size = size << MB_SHIFT; + break; + case 'G': + case 'g': + size = size << GB_SHIFT; + break; + default: + die("shmem: bug in detecting size prefix."); + break; + } + next += 1 + skip_B; + } + if (*next != ':' && *next != '\0') { + die("shmem: unexpected chars after phys size. <%c><%c>\n", + *next, *p); + } + if (*next == '\0') + p = next; + else + p = next + 1; + /* parse out optional shmem handle */ + const int skip_handle = strlen("handle="); + next = strcasestr(p, "handle="); + if (*p && next) { + if (p != next) + die("unexpected chars before handle\n"); + p += skip_handle; + next = strchrnul(p, ':'); + if (next - p) { + handle = malloc(next - p + 1); + strncpy(handle, p, next - p); + handle[next - p] = '\0'; /* just in case. */ + } + if (*next == '\0') + p = next; + else + p = next + 1; + } + /* parse optional create flag to see if we should create shm seg. */ + if (*p && strcasestr(p, "create")) { + create = 1; + p += strlen("create"); + } + if (*p != '\0') + die("shmem: unexpected trailing chars\n"); + if (handle == NULL) { + handle = malloc(strlen(default_handle) + 1); + strcpy(handle, default_handle); + } + if (verbose) { + pr_info("shmem: phys_addr = %llx", phys_addr); + pr_info("shmem: size = %llx", size); + pr_info("shmem: handle = %s", handle); + pr_info("shmem: create = %d", create); + } + + si->phys_addr = phys_addr; + si->size = size; + si->handle = handle; + si->create = create; + pci_shmem__register_mem(si); /* ownership of si, etc. passed on. */ + return 0; +} + int pci_shmem__init(struct kvm *kvm) { u8 dev, line, pin; @@ -226,8 +354,9 @@ int pci_shmem__init(struct kvm *kvm) return 0; /* Register good old INTx */ - if (irq__register_device(PCI_DEVICE_ID_PCI_SHMEM, &dev, &pin, &line) < 0) - return 0; + r = irq__register_device(PCI_DEVICE_ID_PCI_SHMEM, &dev, &pin, &line); + if (r < 0) + return r; pci_shmem_pci_device.irq_pin = pin; pci_shmem_pci_device.irq_line = line; @@ -261,8 +390,14 @@ int pci_shmem__init(struct kvm *kvm) mem = setup_shmem(shmem_region->handle, shmem_region->size, shmem_region->create); if (mem == NULL) - return 0; + return -EINVAL; + kvm__register_mem(kvm, shmem_region->phys_addr, shmem_region->size, mem); - return 1; + return 0; +} + +int pci_shmem__exit(struct kvm *kvm) +{ + return 0; } diff --git a/tools/kvm/include/kvm/pci-shmem.h b/tools/kvm/include/kvm/pci-shmem.h index 599ab377a72d..6cff2b85bfd3 100644 --- a/tools/kvm/include/kvm/pci-shmem.h +++ b/tools/kvm/include/kvm/pci-shmem.h @@ -4,6 +4,8 @@ #include #include +#include "kvm/parse-options.h" + #define SHMEM_DEFAULT_SIZE (16 << MB_SHIFT) #define SHMEM_DEFAULT_ADDR (0xc8000000) #define SHMEM_DEFAULT_HANDLE "/kvm_shmem" @@ -18,8 +20,10 @@ struct shmem_info { int create; }; -int pci_shmem__init(struct kvm *self); +int pci_shmem__init(struct kvm *kvm); +int pci_shmem__exit(struct kvm *kvm); int pci_shmem__register_mem(struct shmem_info *si); +int shmem_parser(const struct option *opt, const char *arg, int unset); int pci_shmem__get_local_irqfd(struct kvm *kvm); int pci_shmem__add_client(struct kvm *kvm, u32 id, int fd); -- 2.39.5