Re: [PATCH V2 1/2] kvm tools: Add initial SPAPR PPC64 architecture support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 13.12.2011, at 08:00, Matt Evans <matt@xxxxxxxxxx> wrote:

> This patch adds a new arch directory, powerpc, basic file structure, register
> setup and where necessary stubs out arch-specific functions (e.g. interrupts,
> runloop exits) that later patches will provide.  The target is an
> SPAPR-compliant PPC64 machine (i.e. pSeries); there is no support for PPC32 or
> 'bare metal' PPC64 guests as yet.  Subsequent patches implement the hcalls and
> RTAS required to boot SPAPR pSeries kernels.
> 
> Memory is mapped from hugetlbfs (as that is currently required by upstream PPC64
> HV-mode KVM).  The mapping of a VRMA region is yet to be implemented; this is
> only necessary on processors that don't support VRMA, e.g. <= P6.  Work is
> therefore needed to get this going on pre-P7 CPUs.
> 
> Processor state is set up as a guest kernel would expect (both primary and
> secondaries), and SMP is fully supported.
> 
> Finally, support is added for simply loading flat binary kernels (plus initrd).
> (bzImages are not used on PPC, and this series does not add zImage support or an
> ELF loader.)  The intention is to later support loading firmware such as SLOF.
> 
> Signed-off-by: Matt Evans <matt@xxxxxxxxxx>
> ---
> tools/kvm/Makefile                           |   10 +
> tools/kvm/kvm.c                              |    3 +
> tools/kvm/powerpc/include/kvm/barrier.h      |    6 +
> tools/kvm/powerpc/include/kvm/kvm-arch.h     |   72 ++++++++
> tools/kvm/powerpc/include/kvm/kvm-cpu-arch.h |   66 ++++++++
> tools/kvm/powerpc/ioport.c                   |   18 ++
> tools/kvm/powerpc/irq.c                      |   40 +++++
> tools/kvm/powerpc/kvm-cpu.c                  |  233 ++++++++++++++++++++++++++
> tools/kvm/powerpc/kvm.c                      |  187 +++++++++++++++++++++
> 9 files changed, 635 insertions(+), 0 deletions(-)
> create mode 100644 tools/kvm/powerpc/include/kvm/barrier.h
> create mode 100644 tools/kvm/powerpc/include/kvm/kvm-arch.h
> create mode 100644 tools/kvm/powerpc/include/kvm/kvm-cpu-arch.h
> create mode 100644 tools/kvm/powerpc/ioport.c
> create mode 100644 tools/kvm/powerpc/irq.c
> create mode 100644 tools/kvm/powerpc/kvm-cpu.c
> create mode 100644 tools/kvm/powerpc/kvm.c
> 
> diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile
> index 2bf70c9..3f1e84a 100644
> --- a/tools/kvm/Makefile
> +++ b/tools/kvm/Makefile
> @@ -124,6 +124,16 @@ ifeq ($(ARCH),x86)
>    OTHEROBJS    += x86/bios/bios-rom.o
>    ARCH_INCLUDE := x86/include
> endif
> +# POWER/ppc:  Actually only support ppc64 currently.

Why? I usually run ppc32 user land. Doesn't that expose 'ppc' here?

> +ifeq ($(uname_M), ppc64)
> +    DEFINES += -DCONFIG_PPC
> +    OBJS    += powerpc/ioport.o
> +    OBJS    += powerpc/irq.o
> +    OBJS    += powerpc/kvm.o
> +    OBJS    += powerpc/kvm-cpu.o
> +    ARCH_INCLUDE := powerpc/include
> +    CFLAGS += -m64
> +endif
> 
> ###
> 
> diff --git a/tools/kvm/kvm.c b/tools/kvm/kvm.c
> index 35ca2c5..3fb46f6 100644
> --- a/tools/kvm/kvm.c
> +++ b/tools/kvm/kvm.c
> @@ -49,6 +49,9 @@ const char *kvm_exit_reasons[] = {
>    DEFINE_KVM_EXIT_REASON(KVM_EXIT_DCR),
>    DEFINE_KVM_EXIT_REASON(KVM_EXIT_NMI),
>    DEFINE_KVM_EXIT_REASON(KVM_EXIT_INTERNAL_ERROR),
> +#ifdef CONFIG_PPC64
> +    DEFINE_KVM_EXIT_REASON(KVM_EXIT_PAPR_HCALL),
> +#endif
> };
> 
> extern struct kvm *kvm;
> diff --git a/tools/kvm/powerpc/include/kvm/barrier.h b/tools/kvm/powerpc/include/kvm/barrier.h
> new file mode 100644
> index 0000000..bc7d179
> --- /dev/null
> +++ b/tools/kvm/powerpc/include/kvm/barrier.h
> @@ -0,0 +1,6 @@
> +#ifndef _KVM_BARRIER_H_
> +#define _KVM_BARRIER_H_
> +
> +#include <asm/system.h>
> +
> +#endif /* _KVM_BARRIER_H_ */
> diff --git a/tools/kvm/powerpc/include/kvm/kvm-arch.h b/tools/kvm/powerpc/include/kvm/kvm-arch.h
> new file mode 100644
> index 0000000..da61774
> --- /dev/null
> +++ b/tools/kvm/powerpc/include/kvm/kvm-arch.h
> @@ -0,0 +1,72 @@
> +/*
> + * PPC64 architecture-specific definitions
> + *
> + * Copyright 2011 Matt Evans <matt@xxxxxxxxxx>, IBM Corporation.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published
> + * by the Free Software Foundation.
> + */
> +
> +#ifndef KVM__KVM_ARCH_H
> +#define KVM__KVM_ARCH_H
> +
> +#include <stdbool.h>
> +#include <linux/types.h>
> +#include <time.h>
> +
> +#define KVM_NR_CPUS            (255)

Why?

> +
> +/*
> + * MMIO lives after RAM, but it'd be nice if it didn't constantly move.
> + * Choose a suitably high address, e.g. 63T...  This limits RAM size.
> + */
> +#define PPC_MMIO_START            0x3F0000000000UL
> +#define PPC_MMIO_SIZE            0x010000000000UL
> +
> +#define KERNEL_LOAD_ADDR            0x0000000000000000
> +#define KERNEL_START_ADDR           0x0000000000000000
> +#define KERNEL_SECONDARY_START_ADDR     0x0000000000000060
> +#define INITRD_LOAD_ADDR            0x0000000002800000
> +
> +#define FDT_MAX_SIZE                0x10000
> +#define RTAS_MAX_SIZE               0x10000
> +
> +#define TIMEBASE_FREQ               512000000ULL
> +
> +#define KVM_MMIO_START            PPC_MMIO_START
> +
> +/*
> + * This is the address that pci_get_io_space_block() starts allocating
> + * from.  Note that this is a PCI bus address.
> + */
> +#define KVM_PCI_MMIO_AREA        0x1000000
> +
> +struct kvm {
> +    int            sys_fd;        /* For system ioctls(), i.e. /dev/kvm */
> +    int            vm_fd;        /* For VM ioctls() */
> +    timer_t            timerid;    /* Posix timer for interrupts */
> +
> +    int            nrcpus;        /* Number of cpus to run */
> +
> +    u32            mem_slots;    /* for KVM_SET_USER_MEMORY_REGION */
> +
> +    u64            ram_size;
> +    void            *ram_start;
> +
> +    bool            nmi_disabled;
> +
> +    bool            single_step;
> +
> +    const char        *vmlinux;
> +    struct disk_image       **disks;
> +    int                     nr_disks;
> +    unsigned long        rtas_gra;
> +    unsigned long        rtas_size;
> +    unsigned long        fdt_gra;
> +    unsigned long        initrd_gra;
> +    unsigned long        initrd_size;
> +    const char        *name;
> +};
> +
> +#endif /* KVM__KVM_ARCH_H */
> diff --git a/tools/kvm/powerpc/include/kvm/kvm-cpu-arch.h b/tools/kvm/powerpc/include/kvm/kvm-cpu-arch.h
> new file mode 100644
> index 0000000..64e4510
> --- /dev/null
> +++ b/tools/kvm/powerpc/include/kvm/kvm-cpu-arch.h
> @@ -0,0 +1,66 @@
> +/*
> + * PPC64 cpu-specific definitions
> + *
> + * Copyright 2011 Matt Evans <matt@xxxxxxxxxx>, IBM Corporation.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published
> + * by the Free Software Foundation.
> + */
> +
> +#ifndef KVM__KVM_CPU_ARCH_H
> +#define KVM__KVM_CPU_ARCH_H
> +
> +/* Architecture-specific kvm_cpu definitions. */
> +
> +#include <linux/kvm.h>    /* for struct kvm_regs */
> +
> +#include <pthread.h>
> +
> +#define MSR_SF        (1UL<<63)
> +#define MSR_HV        (1UL<<60)
> +#define MSR_VEC        (1UL<<25)
> +#define MSR_VSX        (1UL<<23)
> +#define MSR_POW        (1UL<<18)
> +#define MSR_EE        (1UL<<15)
> +#define MSR_PR        (1UL<<14)
> +#define MSR_FP        (1UL<<13)
> +#define MSR_ME        (1UL<<12)
> +#define MSR_FE0        (1UL<<11)
> +#define MSR_SE        (1UL<<10)
> +#define MSR_BE        (1UL<<9)
> +#define MSR_FE1        (1UL<<8)
> +#define MSR_IR        (1UL<<5)
> +#define MSR_DR        (1UL<<4)
> +#define MSR_PMM        (1UL<<2)
> +#define MSR_RI        (1UL<<1)
> +#define MSR_LE        (1UL<<0)
> +
> +struct kvm;
> +
> +struct kvm_cpu {
> +    pthread_t        thread;        /* VCPU thread */
> +
> +    unsigned long        cpu_id;
> +
> +    struct kvm        *kvm;        /* parent KVM */
> +    int            vcpu_fd;    /* For VCPU ioctls() */
> +    struct kvm_run        *kvm_run;
> +
> +    struct kvm_regs        regs;
> +    struct kvm_sregs    sregs;
> +    struct kvm_fpu        fpu;
> +
> +    u8            is_running;
> +    u8            paused;
> +    u8            needs_nmi;
> +    /*
> +     * Although PPC KVM doesn't yet support coalesced MMIO, generic code
> +     * needs this in our kvm_cpu:
> +     */
> +    struct kvm_coalesced_mmio_ring  *ring;
> +};
> +
> +void kvm_cpu__irq(struct kvm_cpu *vcpu, int pin, int level);
> +
> +#endif /* KVM__KVM_CPU_ARCH_H */
> diff --git a/tools/kvm/powerpc/ioport.c b/tools/kvm/powerpc/ioport.c
> new file mode 100644
> index 0000000..a8e4dc3
> --- /dev/null
> +++ b/tools/kvm/powerpc/ioport.c
> @@ -0,0 +1,18 @@
> +/*
> + * PPC64 ioport platform setup.  There isn't any! :-)
> + *
> + * Copyright 2011 Matt Evans <matt@xxxxxxxxxx>, IBM Corporation.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published
> + * by the Free Software Foundation.
> + */
> +
> +#include "kvm/ioport.h"
> +
> +#include <stdlib.h>
> +
> +void ioport__setup_arch(void)
> +{
> +    /* PPC has no legacy ioports to set up */
> +}
> diff --git a/tools/kvm/powerpc/irq.c b/tools/kvm/powerpc/irq.c
> new file mode 100644
> index 0000000..46aa64f
> --- /dev/null
> +++ b/tools/kvm/powerpc/irq.c
> @@ -0,0 +1,40 @@
> +/*
> + * PPC64 IRQ routines
> + *
> + * Copyright 2011 Matt Evans <matt@xxxxxxxxxx>, IBM Corporation.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published
> + * by the Free Software Foundation.
> + */
> +
> +#include "kvm/irq.h"
> +#include "kvm/kvm.h"
> +#include "kvm/util.h"
> +
> +#include <linux/types.h>
> +#include <linux/rbtree.h>
> +#include <linux/list.h>
> +#include <linux/kvm.h>
> +#include <sys/ioctl.h>
> +
> +#include <stddef.h>
> +#include <stdlib.h>
> +
> +int irq__register_device(u32 dev, u8 *num, u8 *pin, u8 *line)
> +{
> +    fprintf(stderr, "irq__register_device(%d, [%d], [%d], [%d]\n",
> +        dev, *num, *pin, *line);
> +    return 0;
> +}
> +
> +void irq__init(struct kvm *kvm)
> +{
> +    fprintf(stderr, __func__);
> +}
> +
> +int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg)
> +{
> +    die(__FUNCTION__);
> +    return 0;
> +}
> diff --git a/tools/kvm/powerpc/kvm-cpu.c b/tools/kvm/powerpc/kvm-cpu.c
> new file mode 100644
> index 0000000..ea99666
> --- /dev/null
> +++ b/tools/kvm/powerpc/kvm-cpu.c
> @@ -0,0 +1,233 @@
> +/*
> + * PPC64 processor support
> + *
> + * Copyright 2011 Matt Evans <matt@xxxxxxxxxx>, IBM Corporation.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published
> + * by the Free Software Foundation.
> + */
> +
> +#include "kvm/kvm-cpu.h"
> +
> +#include "kvm/symbol.h"
> +#include "kvm/util.h"
> +#include "kvm/kvm.h"
> +
> +#include <sys/ioctl.h>
> +#include <sys/mman.h>
> +#include <signal.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <errno.h>
> +#include <stdio.h>
> +
> +static int debug_fd;
> +
> +void kvm_cpu__set_debug_fd(int fd)
> +{
> +    debug_fd = fd;
> +}
> +
> +int kvm_cpu__get_debug_fd(void)
> +{
> +    return debug_fd;
> +}
> +
> +static struct kvm_cpu *kvm_cpu__new(struct kvm *kvm)
> +{
> +    struct kvm_cpu *vcpu;
> +
> +    vcpu        = calloc(1, sizeof *vcpu);
> +    if (!vcpu)
> +        return NULL;
> +
> +    vcpu->kvm    = kvm;
> +
> +    return vcpu;
> +}
> +
> +void kvm_cpu__delete(struct kvm_cpu *vcpu)
> +{
> +    free(vcpu);
> +}
> +
> +struct kvm_cpu *kvm_cpu__init(struct kvm *kvm, unsigned long cpu_id)
> +{
> +    struct kvm_cpu *vcpu;
> +    int mmap_size;
> +    struct kvm_enable_cap papr_cap = { .cap = KVM_CAP_PPC_PAPR };
> +
> +    vcpu        = kvm_cpu__new(kvm);
> +    if (!vcpu)
> +        return NULL;
> +
> +    vcpu->cpu_id    = cpu_id;
> +
> +    vcpu->vcpu_fd = ioctl(vcpu->kvm->vm_fd, KVM_CREATE_VCPU, cpu_id);
> +    if (vcpu->vcpu_fd < 0)
> +        die_perror("KVM_CREATE_VCPU ioctl");
> +
> +    mmap_size = ioctl(vcpu->kvm->sys_fd, KVM_GET_VCPU_MMAP_SIZE, 0);
> +    if (mmap_size < 0)
> +        die_perror("KVM_GET_VCPU_MMAP_SIZE ioctl");
> +
> +    vcpu->kvm_run = mmap(NULL, mmap_size, PROT_RW, MAP_SHARED, vcpu->vcpu_fd, 0);
> +    if (vcpu->kvm_run == MAP_FAILED)
> +        die("unable to mmap vcpu fd");
> +
> +    ioctl(vcpu->vcpu_fd, KVM_ENABLE_CAP, &papr_cap);

Have you tried running this on PR KVM? That should also need HIOR synchronization.

Alex

> +
> +    /*
> +     * We start all CPUs, directing non-primary threads into the kernel's
> +     * secondary start point.  When we come to support SLOF, we will start
> +     * only one and SLOF will RTAS call us to ask for others to be
> +     * started.  (FIXME: make more generic & interface with whichever
> +     * firmware a platform may be using.)
> +     */
> +    vcpu->is_running = true;
> +
> +    return vcpu;
> +}
> +
> +static void kvm_cpu__setup_fpu(struct kvm_cpu *vcpu)
> +{
> +    /* Don't have to do anything, there's no expected FPU state. */
> +}
> +
> +static void kvm_cpu__setup_regs(struct kvm_cpu *vcpu)
> +{
> +    /*
> +     * FIXME: This assumes PPC64 and Linux guest.  It doesn't use the
> +     * OpenFirmware entry method, but instead the "embedded" entry which
> +     * passes the FDT address directly.
> +     */
> +    struct kvm_regs *r = &vcpu->regs;
> +
> +    if (vcpu->cpu_id == 0) {
> +        r->pc = KERNEL_START_ADDR;
> +        r->gpr[3] = vcpu->kvm->fdt_gra;
> +        r->gpr[5] = 0;
> +    } else {
> +        r->pc = KERNEL_SECONDARY_START_ADDR;
> +        r->gpr[3] = vcpu->cpu_id;
> +    }
> +    r->msr = 0x8000000000001000UL; /* 64bit, non-HV, ME */
> +
> +    if (ioctl(vcpu->vcpu_fd, KVM_SET_REGS, &vcpu->regs) < 0)
> +        die_perror("KVM_SET_REGS failed");
> +}
> +
> +static void kvm_cpu__setup_sregs(struct kvm_cpu *vcpu)
> +{
> +    /*
> +     * No sregs setup is required on PPC64/SPAPR (but there may be setup
> +     * required for non-paravirtualised platforms, e.g. TLB/SLB setup).
> +     */
> +}
> +
> +/**
> + * kvm_cpu__reset_vcpu - reset virtual CPU to a known state
> + */
> +void kvm_cpu__reset_vcpu(struct kvm_cpu *vcpu)
> +{
> +    kvm_cpu__setup_regs(vcpu);
> +    kvm_cpu__setup_sregs(vcpu);
> +    kvm_cpu__setup_fpu(vcpu);
> +}
> +
> +/* kvm_cpu__irq - set KVM's IRQ flag on this vcpu */
> +void kvm_cpu__irq(struct kvm_cpu *vcpu, int pin, int level)
> +{
> +}
> +
> +void kvm_cpu__arch_nmi(struct kvm_cpu *cpu)
> +{
> +}
> +
> +bool kvm_cpu__handle_exit(struct kvm_cpu *vcpu)
> +{
> +    bool ret = true;
> +    struct kvm_run *run = vcpu->kvm_run;
> +    switch(run->exit_reason) {
> +    default:
> +        ret = false;
> +    }
> +    return ret;
> +}
> +
> +#define CONDSTR_BIT(m, b) (((m) & MSR_##b) ? #b" " : "")
> +
> +void kvm_cpu__show_registers(struct kvm_cpu *vcpu)
> +{
> +    struct kvm_regs regs;
> +    struct kvm_sregs sregs;
> +    int r;
> +
> +    if (ioctl(vcpu->vcpu_fd, KVM_GET_REGS, &regs) < 0)
> +        die("KVM_GET_REGS failed");
> +        if (ioctl(vcpu->vcpu_fd, KVM_GET_SREGS, &sregs) < 0)
> +        die("KVM_GET_SREGS failed");
> +
> +    dprintf(debug_fd, "\n Registers:\n");
> +    dprintf(debug_fd, " NIP:   %016llx  MSR:   %016llx "
> +        "( %s%s%s%s%s%s%s%s%s%s%s%s)\n",
> +        regs.pc, regs.msr,
> +        CONDSTR_BIT(regs.msr, SF),
> +        CONDSTR_BIT(regs.msr, HV), /* ! */
> +        CONDSTR_BIT(regs.msr, VEC),
> +        CONDSTR_BIT(regs.msr, VSX),
> +        CONDSTR_BIT(regs.msr, EE),
> +        CONDSTR_BIT(regs.msr, PR),
> +        CONDSTR_BIT(regs.msr, FP),
> +        CONDSTR_BIT(regs.msr, ME),
> +        CONDSTR_BIT(regs.msr, IR),
> +        CONDSTR_BIT(regs.msr, DR),
> +        CONDSTR_BIT(regs.msr, RI),
> +        CONDSTR_BIT(regs.msr, LE));
> +    dprintf(debug_fd, " CTR:   %016llx  LR:    %016llx  CR:   %08llx\n",
> +        regs.ctr, regs.lr, regs.cr);
> +    dprintf(debug_fd, " SRR0:  %016llx  SRR1:  %016llx  XER:  %016llx\n",
> +        regs.srr0, regs.srr1, regs.xer);
> +    dprintf(debug_fd, " SPRG0: %016llx  SPRG1: %016llx\n",
> +        regs.sprg0, regs.sprg1);
> +    dprintf(debug_fd, " SPRG2: %016llx  SPRG3: %016llx\n",
> +        regs.sprg2, regs.sprg3);
> +    dprintf(debug_fd, " SPRG4: %016llx  SPRG5: %016llx\n",
> +        regs.sprg4, regs.sprg5);
> +    dprintf(debug_fd, " SPRG6: %016llx  SPRG7: %016llx\n",
> +        regs.sprg6, regs.sprg7);
> +    dprintf(debug_fd, " GPRs:\n ");
> +    for (r = 0; r < 32; r++) {
> +        dprintf(debug_fd, "%016llx  ", regs.gpr[r]);
> +        if ((r & 3) == 3)
> +            dprintf(debug_fd, "\n ");
> +    }
> +    dprintf(debug_fd, "\n");
> +
> +    /* FIXME: Assumes SLB-based (book3s) guest */
> +    for (r = 0; r < 32; r++) {
> +        dprintf(debug_fd, " SLB%02d  %016llx %016llx\n", r,
> +            sregs.u.s.ppc64.slb[r].slbe,
> +            sregs.u.s.ppc64.slb[r].slbv);
> +    }
> +    dprintf(debug_fd, "----------\n");
> +}
> +
> +void kvm_cpu__show_code(struct kvm_cpu *vcpu)
> +{
> +    if (ioctl(vcpu->vcpu_fd, KVM_GET_REGS, &vcpu->regs) < 0)
> +        die("KVM_GET_REGS failed");
> +
> +    /* FIXME: Dump/disassemble some code...! */
> +
> +    dprintf(debug_fd, "\n Stack:\n");
> +    dprintf(debug_fd,   " ------\n");
> +    /* Only works in real mode: */
> +    kvm__dump_mem(vcpu->kvm, vcpu->regs.gpr[1], 32);
> +}
> +
> +void kvm_cpu__show_page_tables(struct kvm_cpu *vcpu)
> +{
> +    /* Does nothing yet */
> +}
> diff --git a/tools/kvm/powerpc/kvm.c b/tools/kvm/powerpc/kvm.c
> new file mode 100644
> index 0000000..f838a8f
> --- /dev/null
> +++ b/tools/kvm/powerpc/kvm.c
> @@ -0,0 +1,187 @@
> +/*
> + * PPC64 (SPAPR) platform support
> + *
> + * Copyright 2011 Matt Evans <matt@xxxxxxxxxx>, IBM Corporation.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published
> + * by the Free Software Foundation.
> + */
> +
> +#include "kvm/kvm.h"
> +#include "kvm/util.h"
> +
> +#include <linux/kvm.h>
> +
> +#include <sys/types.h>
> +#include <sys/ioctl.h>
> +#include <sys/mman.h>
> +#include <stdbool.h>
> +#include <assert.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <stdio.h>
> +#include <fcntl.h>
> +#include <asm/unistd.h>
> +#include <errno.h>
> +
> +#include <linux/byteorder.h>
> +#include <libfdt.h>
> +
> +#define HUGETLBFS_PATH "/var/lib/hugetlbfs/global/pagesize-16MB/"
> +
> +static char kern_cmdline[2048];
> +
> +struct kvm_ext kvm_req_ext[] = {
> +    { 0, 0 }
> +};
> +
> +bool kvm__arch_cpu_supports_vm(void)
> +{
> +    return true;
> +}
> +
> +void kvm__init_ram(struct kvm *kvm)
> +{
> +    u64    phys_start, phys_size;
> +    void    *host_mem;
> +
> +    phys_start = 0;
> +    phys_size  = kvm->ram_size;
> +    host_mem   = kvm->ram_start;
> +
> +    /*
> +     * We put MMIO at PPC_MMIO_START, high up.  Make sure that this doesn't
> +     * crash into the end of RAM -- on PPC64 at least, this is so high
> +     * (63TB!) that this is unlikely.
> +     */
> +    if (phys_size >= PPC_MMIO_START)
> +        die("Too much memory (%lld, what a nice problem): "
> +            "overlaps MMIO!\n",
> +            phys_size);
> +
> +    kvm__register_mem(kvm, phys_start, phys_size, host_mem);
> +}
> +
> +void kvm__arch_set_cmdline(char *cmdline, bool video)
> +{
> +    /* We don't need anything unusual in here. */
> +}
> +
> +/* Architecture-specific KVM init */
> +void kvm__arch_init(struct kvm *kvm, const char *kvm_dev, const char *hugetlbfs_path, u64 ram_size, const char *name)
> +{
> +    int cap_ppc_rma;
> +
> +    kvm->ram_size        = ram_size;
> +
> +    /*
> +     * Currently, we must map from hugetlbfs; if --hugetlbfs not specified,
> +     * try a default path:
> +     */
> +    if (!hugetlbfs_path) {
> +        hugetlbfs_path = HUGETLBFS_PATH;
> +        pr_info("Using default %s for memory", hugetlbfs_path);
> +    }
> +
> +    kvm->ram_start = mmap_hugetlbfs(hugetlbfs_path, kvm->ram_size);
> +    if (kvm->ram_start == MAP_FAILED)
> +        die("Couldn't map %lld bytes for RAM (%d)\n",
> +            kvm->ram_size, errno);
> +
> +    /* FDT goes at top of memory, RTAS just below */
> +    kvm->fdt_gra = kvm->ram_size - FDT_MAX_SIZE;
> +    /* FIXME: Not all PPC systems have RTAS */
> +    kvm->rtas_gra = kvm->fdt_gra - RTAS_MAX_SIZE;
> +    madvise(kvm->ram_start, kvm->ram_size, MADV_MERGEABLE);
> +
> +    /* FIXME: This is book3s-specific */
> +    cap_ppc_rma = ioctl(kvm->sys_fd, KVM_CHECK_EXTENSION, KVM_CAP_PPC_RMA);
> +    if (cap_ppc_rma == 2)
> +        die("Need contiguous RMA allocation on this hardware, "
> +            "which is not yet supported.");
> +}
> +
> +void kvm__irq_line(struct kvm *kvm, int irq, int level)
> +{
> +    fprintf(stderr, "irq_line(%d, %d)\n", irq, level);
> +}
> +
> +void kvm__irq_trigger(struct kvm *kvm, int irq)
> +{
> +    kvm__irq_line(kvm, irq, 1);
> +    kvm__irq_line(kvm, irq, 0);
> +}
> +
> +int load_flat_binary(struct kvm *kvm, int fd_kernel, int fd_initrd, const char *kernel_cmdline)
> +{
> +    void *p;
> +    void *k_start;
> +    void *i_start;
> +    int nr;
> +
> +    if (lseek(fd_kernel, 0, SEEK_SET) < 0)
> +        die_perror("lseek");
> +
> +    p = k_start = guest_flat_to_host(kvm, KERNEL_LOAD_ADDR);
> +
> +    while ((nr = read(fd_kernel, p, 65536)) > 0)
> +        p += nr;
> +
> +    pr_info("Loaded kernel to 0x%x (%ld bytes)", KERNEL_LOAD_ADDR, p-k_start);
> +
> +    if (fd_initrd != -1) {
> +        if (lseek(fd_initrd, 0, SEEK_SET) < 0)
> +            die_perror("lseek");
> +
> +        if (p-k_start > INITRD_LOAD_ADDR)
> +            die("Kernel overlaps initrd!");
> +
> +        /* Round up kernel size to 8byte alignment, and load initrd right after. */
> +        i_start = p = guest_flat_to_host(kvm, INITRD_LOAD_ADDR);
> +
> +        while (((nr = read(fd_initrd, p, 65536)) > 0) &&
> +               p < (kvm->ram_start + kvm->ram_size))
> +            p += nr;
> +
> +        if (p >= (kvm->ram_start + kvm->ram_size))
> +            die("initrd too big to contain in guest RAM.\n");
> +
> +        pr_info("Loaded initrd to 0x%x (%ld bytes)",
> +            INITRD_LOAD_ADDR, p-i_start);
> +        kvm->initrd_gra = INITRD_LOAD_ADDR;
> +        kvm->initrd_size = p-i_start;
> +    } else {
> +        kvm->initrd_size = 0;
> +    }
> +    strncpy(kern_cmdline, kernel_cmdline, 2048);
> +    kern_cmdline[2047] = '\0';
> +
> +    return true;
> +}
> +
> +bool load_bzimage(struct kvm *kvm, int fd_kernel,
> +          int fd_initrd, const char *kernel_cmdline, u16 vidmode)
> +{
> +    /* We don't support bzImages. */
> +    return false;
> +}
> +
> +static void setup_fdt(struct kvm *kvm)
> +{
> +
> +}
> +
> +/**
> + * kvm__arch_setup_firmware
> + */
> +void kvm__arch_setup_firmware(struct kvm *kvm)
> +{
> +    /* Load RTAS */
> +
> +    /* Load SLOF */
> +
> +    /* Init FDT */
> +    setup_fdt(kvm);
> +}
> -- 
> 1.7.0.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux