qemu/hw/ppc440_bamboo.c
Amit Shah 98b19252cf virtio-console: qdev conversion, new virtio-serial-bus
This commit converts the virtio-console device to create a new
virtio-serial bus that can host console and generic serial ports. The
file hosting this code is now called virtio-serial-bus.c.

The virtio console is now a very simple qdev device that sits on the
virtio-serial-bus and communicates between the bus and qemu's chardevs.

This commit also includes a few changes to the virtio backing code for
pci and s390 to spawn the virtio-serial bus.

As a result of the qdev conversion, we get rid of a lot of legacy code.
The old-style way of instantiating a virtio console using

    -virtioconsole ...

is maintained, but the new, preferred way is to use

    -device virtio-serial -device virtconsole,chardev=...

With this commit, multiple devices as well as multiple ports with a
single device can be supported.

For multiple ports support, each port gets an IO vq pair. Since the
guest needs to know in advance how many vqs a particular device will
need, we have to set this number as a property of the virtio-serial
device and also as a config option.

In addition, we also spawn a pair of control IO vqs. This is an internal
channel meant for guest-host communication for things like port
open/close, sending port properties over to the guest, etc.

This commit is a part of a series of other commits to get the full
implementation of multiport support. Future commits will add other
support as well as ride on the savevm version that we bump up here.

Signed-off-by: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
2010-01-20 08:25:23 -06:00

186 lines
5.3 KiB
C

/*
* Qemu PowerPC 440 Bamboo board emulation
*
* Copyright 2007 IBM Corporation.
* Authors:
* Jerone Young <jyoung5@us.ibm.com>
* Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
* Hollis Blanchard <hollisb@us.ibm.com>
*
* This work is licensed under the GNU GPL license version 2 or later.
*
*/
#include "config.h"
#include "qemu-common.h"
#include "net.h"
#include "hw.h"
#include "pci.h"
#include "boards.h"
#include "sysemu.h"
#include "ppc440.h"
#include "kvm.h"
#include "kvm_ppc.h"
#include "device_tree.h"
#include "loader.h"
#include "elf.h"
#define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
static void *bamboo_load_device_tree(target_phys_addr_t addr,
uint32_t ramsize,
target_phys_addr_t initrd_base,
target_phys_addr_t initrd_size,
const char *kernel_cmdline)
{
void *fdt = NULL;
#ifdef CONFIG_FDT
uint32_t mem_reg_property[] = { 0, 0, ramsize };
char *filename;
int fdt_size;
int ret;
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, BINARY_DEVICE_TREE_FILE);
if (!filename) {
goto out;
}
fdt = load_device_tree(filename, &fdt_size);
qemu_free(filename);
if (fdt == NULL) {
goto out;
}
/* Manipulate device tree in memory. */
ret = qemu_devtree_setprop(fdt, "/memory", "reg", mem_reg_property,
sizeof(mem_reg_property));
if (ret < 0)
fprintf(stderr, "couldn't set /memory/reg\n");
ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-start",
initrd_base);
if (ret < 0)
fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n");
ret = qemu_devtree_setprop_cell(fdt, "/chosen", "linux,initrd-end",
(initrd_base + initrd_size));
if (ret < 0)
fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n");
ret = qemu_devtree_setprop_string(fdt, "/chosen", "bootargs",
kernel_cmdline);
if (ret < 0)
fprintf(stderr, "couldn't set /chosen/bootargs\n");
if (kvm_enabled())
kvmppc_fdt_update(fdt);
cpu_physical_memory_write (addr, (void *)fdt, fdt_size);
out:
#endif
return fdt;
}
static void bamboo_init(ram_addr_t ram_size,
const char *boot_device,
const char *kernel_filename,
const char *kernel_cmdline,
const char *initrd_filename,
const char *cpu_model)
{
unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
PCIBus *pcibus;
CPUState *env;
uint64_t elf_entry;
uint64_t elf_lowaddr;
target_phys_addr_t entry = 0;
target_phys_addr_t loadaddr = 0;
target_long kernel_size = 0;
target_ulong initrd_base = 0;
target_long initrd_size = 0;
target_ulong dt_base = 0;
void *fdt;
int i;
/* Setup CPU. */
env = ppc440ep_init(&ram_size, &pcibus, pci_irq_nrs, 1, cpu_model);
if (pcibus) {
/* Register network interfaces. */
for (i = 0; i < nb_nics; i++) {
/* There are no PCI NICs on the Bamboo board, but there are
* PCI slots, so we can pick whatever default model we want. */
pci_nic_init_nofail(&nd_table[i], "e1000", NULL);
}
}
/* Load kernel. */
if (kernel_filename) {
kernel_size = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
if (kernel_size < 0) {
kernel_size = load_elf(kernel_filename, 0, &elf_entry, &elf_lowaddr,
NULL, 1, ELF_MACHINE, 0);
entry = elf_entry;
loadaddr = elf_lowaddr;
}
/* XXX try again as binary */
if (kernel_size < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
kernel_filename);
exit(1);
}
}
/* Load initrd. */
if (initrd_filename) {
initrd_base = kernel_size + loadaddr;
initrd_size = load_image_targphys(initrd_filename, initrd_base,
ram_size - initrd_base);
if (initrd_size < 0) {
fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
initrd_filename);
exit(1);
}
}
/* If we're loading a kernel directly, we must load the device tree too. */
if (kernel_filename) {
if (initrd_base)
dt_base = initrd_base + initrd_size;
else
dt_base = kernel_size + loadaddr;
fdt = bamboo_load_device_tree(dt_base, ram_size,
initrd_base, initrd_size, kernel_cmdline);
if (fdt == NULL) {
fprintf(stderr, "couldn't load device tree\n");
exit(1);
}
/* Set initial guest state. */
env->gpr[1] = (16<<20) - 8;
env->gpr[3] = dt_base;
env->nip = entry;
/* XXX we currently depend on KVM to create some initial TLB entries. */
}
if (kvm_enabled())
kvmppc_init();
}
static QEMUMachine bamboo_machine = {
.name = "bamboo",
.desc = "bamboo",
.init = bamboo_init,
};
static void bamboo_machine_init(void)
{
qemu_register_machine(&bamboo_machine);
}
machine_init(bamboo_machine_init);