From 74bc41511af5c389cd9f37956bd6e7fd7de35c49 Mon Sep 17 00:00:00 2001 From: Roger Pau Monne Date: Fri, 23 May 2014 17:57:47 +0200 Subject: [PATCH 1/3] xen: fix usage of ENODATA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ENODATA doesn't exist on FreeBSD, so ENODATA errors returned by the hypervisor are translated to ENOENT. Also, the error code is returned in errno if the call returns -1, so compare the error code with the value in errno instead of the value returned by the function. Signed-off-by: Roger Pau Monné Signed-off-by: Stefano Stabellini Cc: xen-devel@lists.xenproject.org Cc: Stefano Stabellini Cc: Anthony Perard --- xen-hvm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/xen-hvm.c b/xen-hvm.c index a2486cfd7e..91de2e230b 100644 --- a/xen-hvm.c +++ b/xen-hvm.c @@ -513,11 +513,14 @@ static void xen_sync_dirty_bitmap(XenIOState *state, start_addr >> TARGET_PAGE_BITS, npages, bitmap); if (rc < 0) { - if (rc != -ENODATA) { +#ifndef ENODATA +#define ENODATA ENOENT +#endif + if (errno == ENODATA) { memory_region_set_dirty(framebuffer, 0, size); DPRINTF("xen: track_dirty_vram failed (0x" TARGET_FMT_plx ", 0x" TARGET_FMT_plx "): %s\n", - start_addr, start_addr + size, strerror(-rc)); + start_addr, start_addr + size, strerror(errno)); } return; } From 8677de2b4d26f8878b7414d540a6b2e139bc4d91 Mon Sep 17 00:00:00 2001 From: Roger Pau Monne Date: Fri, 23 May 2014 17:57:48 +0200 Subject: [PATCH 2/3] tap-bsd: implement a FreeBSD only version of tap_open MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current behaviour of tap_open for BSD systems differ greatly from it's Linux counterpart. Since FreeBSD supports interface renaming and tap device cloning by opening /dev/tap, implement a FreeBSD specific version of tap_open that behaves like it's Linux counterpart. This is specially important for toolstacks that use Qemu (like Xen libxl), in order to have a unified behaviour across suported platforms. Signed-off-by: Roger Pau Monné Signed-off-by: Stefano Stabellini Reviewed-by: Stefan Hajnoczi --- net/tap-bsd.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/net/tap-bsd.c b/net/tap-bsd.c index 90f8a02276..bf91bd03fd 100644 --- a/net/tap-bsd.c +++ b/net/tap-bsd.c @@ -27,12 +27,13 @@ #include "sysemu/sysemu.h" #include "qemu/error-report.h" -#ifdef __NetBSD__ +#if defined(__NetBSD__) || defined(__FreeBSD__) #include #include #include #endif +#ifndef __FreeBSD__ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required, int mq_required) { @@ -108,6 +109,73 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, return fd; } +#else /* __FreeBSD__ */ + +#define PATH_NET_TAP "/dev/tap" + +int tap_open(char *ifname, int ifname_size, int *vnet_hdr, + int vnet_hdr_required, int mq_required) +{ + int fd, s, ret; + struct ifreq ifr; + + TFR(fd = open(PATH_NET_TAP, O_RDWR)); + if (fd < 0) { + error_report("could not open %s: %s", PATH_NET_TAP, strerror(errno)); + return -1; + } + + memset(&ifr, 0, sizeof(ifr)); + + ret = ioctl(fd, TAPGIFNAME, (void *)&ifr); + if (ret < 0) { + error_report("could not get tap interface name"); + goto error; + } + + if (ifname[0] != '\0') { + /* User requested the interface to have a specific name */ + s = socket(AF_LOCAL, SOCK_DGRAM, 0); + if (s < 0) { + error_report("could not open socket to set interface name"); + goto error; + } + ifr.ifr_data = ifname; + ret = ioctl(s, SIOCSIFNAME, (void *)&ifr); + close(s); + if (ret < 0) { + error_report("could not set tap interface name"); + goto error; + } + } else { + pstrcpy(ifname, ifname_size, ifr.ifr_name); + } + + if (*vnet_hdr) { + /* BSD doesn't have IFF_VNET_HDR */ + *vnet_hdr = 0; + + if (vnet_hdr_required && !*vnet_hdr) { + error_report("vnet_hdr=1 requested, but no kernel " + "support for IFF_VNET_HDR available"); + goto error; + } + } + if (mq_required) { + error_report("mq_required requested, but not kernel support" + "for IFF_MULTI_QUEUE available"); + goto error; + } + + fcntl(fd, F_SETFL, O_NONBLOCK); + return fd; + +error: + close(fd); + return -1; +} +#endif /* __FreeBSD__ */ + int tap_set_sndbuf(int fd, const NetdevTapOptions *tap) { return 0; From b33a5bbfbaab6c1ce653a8e3665a18ca67de1456 Mon Sep 17 00:00:00 2001 From: Chunyan Liu Date: Mon, 7 Jul 2014 14:34:35 +0800 Subject: [PATCH 3/3] qemu: support xen hvm direct kernel boot qemu side patch to support xen HVM direct kernel boot: if -kernel exists, calls xen_load_linux(), which will read kernel/initrd and add a linuxboot.bin or multiboot.bin option rom. The linuxboot.bin/multiboot.bin will load kernel/initrd and jump to execute kernel directly. It's working when xen uses seabios. During this work, found the 'kvmvapic' is in option_rom list, it should not be there in xen case. Set s->vapic_control = 0 in xen_apic_realize() to handle that. Signed-off-by: Chunyan Liu Acked-by: Stefano Stabellini Acked-by: Michael S. Tsirkin --- hw/i386/pc.c | 25 +++++++++++++++++++++++++ hw/i386/pc_piix.c | 7 +++++++ hw/i386/xen/xen_apic.c | 1 + include/hw/i386/pc.h | 5 +++++ 4 files changed, 38 insertions(+) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 2cf22b1293..9e589825f0 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1190,6 +1190,31 @@ void pc_acpi_init(const char *default_dsdt) } } +FWCfgState *xen_load_linux(const char *kernel_filename, + const char *kernel_cmdline, + const char *initrd_filename, + ram_addr_t below_4g_mem_size, + PcGuestInfo *guest_info) +{ + int i; + FWCfgState *fw_cfg; + + assert(kernel_filename != NULL); + + fw_cfg = fw_cfg_init(BIOS_CFG_IOPORT, BIOS_CFG_IOPORT + 1, 0, 0); + rom_set_fw(fw_cfg); + + load_linux(fw_cfg, kernel_filename, initrd_filename, + kernel_cmdline, below_4g_mem_size); + for (i = 0; i < nb_option_roms; i++) { + assert(!strcmp(option_rom[i].name, "linuxboot.bin") || + !strcmp(option_rom[i].name, "multiboot.bin")); + rom_add_option(option_rom[i].name, option_rom[i].bootindex); + } + guest_info->fw_cfg = fw_cfg; + return fw_cfg; +} + FWCfgState *pc_memory_init(MachineState *machine, MemoryRegion *system_memory, ram_addr_t below_4g_mem_size, diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 9694f88057..4f22be85da 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -182,6 +182,13 @@ static void pc_init1(MachineState *machine, fw_cfg = pc_memory_init(machine, system_memory, below_4g_mem_size, above_4g_mem_size, rom_memory, &ram_memory, guest_info); + } else if (machine->kernel_filename != NULL) { + /* For xen HVM direct kernel boot, load linux here */ + fw_cfg = xen_load_linux(machine->kernel_filename, + machine->kernel_cmdline, + machine->initrd_filename, + below_4g_mem_size, + guest_info); } gsi_state = g_malloc0(sizeof(*gsi_state)); diff --git a/hw/i386/xen/xen_apic.c b/hw/i386/xen/xen_apic.c index 63bb7f77c6..f5acd6a096 100644 --- a/hw/i386/xen/xen_apic.c +++ b/hw/i386/xen/xen_apic.c @@ -40,6 +40,7 @@ static void xen_apic_realize(DeviceState *dev, Error **errp) { APICCommonState *s = APIC_COMMON(dev); + s->vapic_control = 0; memory_region_init_io(&s->io_memory, OBJECT(s), &xen_apic_io_ops, s, "xen-apic-msi", APIC_SPACE_SIZE); diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index f4b9b2bb71..863eefbf8c 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -188,6 +188,11 @@ PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size, void pc_pci_as_mapping_init(Object *owner, MemoryRegion *system_memory, MemoryRegion *pci_address_space); +FWCfgState *xen_load_linux(const char *kernel_filename, + const char *kernel_cmdline, + const char *initrd_filename, + ram_addr_t below_4g_mem_size, + PcGuestInfo *guest_info); FWCfgState *pc_memory_init(MachineState *machine, MemoryRegion *system_memory, ram_addr_t below_4g_mem_size,