diff mbox

[v8,01/16] target-or32: Add target stubs and QOM cpu

Message ID 1341110730-444-2-git-send-email-proljc@gmail.com
State New
Headers show

Commit Message

Jia Liu July 1, 2012, 2:45 a.m. UTC
Add OpenRISC target stubs and cpu support.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 arch_init.c                      |    2 +
 arch_init.h                      |    1 +
 configure                        |   14 +-
 cpu-exec.c                       |    2 +
 default-configs/or32-softmmu.mak |    4 +
 elf.h                            |    2 +
 hw/openrisc/Makefile.objs        |    1 +
 poison.h                         |    1 +
 target-openrisc/Makefile.objs    |    3 +
 target-openrisc/cpu.c            |  236 +++++++++++++++++++++++++++++++
 target-openrisc/cpu.h            |  286 ++++++++++++++++++++++++++++++++++++++
 target-openrisc/intrpt.c         |   30 ++++
 target-openrisc/machine.c        |   30 ++++
 target-openrisc/mmu.c            |   39 ++++++
 target-openrisc/mmu_helper.c     |   43 ++++++
 target-openrisc/translate.c      |   75 ++++++++++
 16 files changed, 767 insertions(+), 2 deletions(-)
 create mode 100644 default-configs/or32-softmmu.mak
 create mode 100644 hw/openrisc/Makefile.objs
 create mode 100644 target-openrisc/Makefile.objs
 create mode 100644 target-openrisc/cpu.c
 create mode 100644 target-openrisc/cpu.h
 create mode 100644 target-openrisc/intrpt.c
 create mode 100644 target-openrisc/machine.c
 create mode 100644 target-openrisc/mmu.c
 create mode 100644 target-openrisc/mmu_helper.c
 create mode 100644 target-openrisc/translate.c

Comments

Andreas Färber July 5, 2012, 1:22 p.m. UTC | #1
Am 01.07.2012 04:45, schrieb Jia Liu:
> Add OpenRISC target stubs and cpu support.
> 
> Signed-off-by: Jia Liu <proljc@gmail.com>
> ---
>  arch_init.c                      |    2 +
>  arch_init.h                      |    1 +
>  configure                        |   14 +-
>  cpu-exec.c                       |    2 +
>  default-configs/or32-softmmu.mak |    4 +
>  elf.h                            |    2 +
>  hw/openrisc/Makefile.objs        |    1 +
>  poison.h                         |    1 +
>  target-openrisc/Makefile.objs    |    3 +
>  target-openrisc/cpu.c            |  236 +++++++++++++++++++++++++++++++
>  target-openrisc/cpu.h            |  286 ++++++++++++++++++++++++++++++++++++++
>  target-openrisc/intrpt.c         |   30 ++++
>  target-openrisc/machine.c        |   30 ++++
>  target-openrisc/mmu.c            |   39 ++++++
>  target-openrisc/mmu_helper.c     |   43 ++++++
>  target-openrisc/translate.c      |   75 ++++++++++
>  16 files changed, 767 insertions(+), 2 deletions(-)
>  create mode 100644 default-configs/or32-softmmu.mak
>  create mode 100644 hw/openrisc/Makefile.objs
>  create mode 100644 target-openrisc/Makefile.objs
>  create mode 100644 target-openrisc/cpu.c
>  create mode 100644 target-openrisc/cpu.h
>  create mode 100644 target-openrisc/intrpt.c
>  create mode 100644 target-openrisc/machine.c
>  create mode 100644 target-openrisc/mmu.c
>  create mode 100644 target-openrisc/mmu_helper.c
>  create mode 100644 target-openrisc/translate.c

> diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
> new file mode 100644
> index 0000000..21b76b2
> --- /dev/null
> +++ b/target-openrisc/Makefile.objs
> @@ -0,0 +1,3 @@
> +obj-$(CONFIG_SOFTMMU) += machine.o
> +obj-y += cpu.o intrpt.o mmu.o translate.o

intrpt.o? Any chance of a better to read/remember file name?

> +obj-y += mmu_helper.o
> diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
> new file mode 100644
> index 0000000..64ddc98
> --- /dev/null
> +++ b/target-openrisc/cpu.c
> @@ -0,0 +1,236 @@
> +/*
> + *  QEMU OpenRISC CPU
> + *
> + *  Copyright (c) 2012 Jia Liu <proljc@gmail.com>

Two-space indentation? (also in other files)

> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "cpu.h"
> +#include "qemu-common.h"

> +#ifndef CONFIG_USER_ONLY
> +#include "hw/loader.h"
> +#endif

Not yet needed in this patch?

> +
> +/* CPUClass::reset() */
> +static void openrisc_cpu_reset(CPUState *s)
> +{
> +    OpenRISCCPU *cpu = OPENRISC_CPU(s);
> +    OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(cpu);
> +
> +    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
> +        qemu_log("CPU Reset (CPU %d)\n", cpu->env.cpu_index);
> +        log_cpu_state(&cpu->env, 0);
> +    }
> +
> +    occ->parent_reset(s);
> +
> +    memset(&cpu->env, 0, offsetof(CPUOpenRISCState, breakpoints));

Note, if you wanted, you could've declared a CPUOpenRISCState *env to
avoid re-typing "cpu->env." or "&cpu->env".

> +
> +    tlb_flush(&cpu->env, 1);
> +    /*tb_flush(&cpu->env);    FIXME: Do we need it?  */
> +
> +    cpu->env.pc = 0x100;
> +    cpu->env.sr = SR_FO | SR_SM;
> +    cpu->env.exception_index = -1;
> +
> +    cpu->env.upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP;
> +    cpu->env.cpucfgr = CPUCFGR_OB32S | CPUCFGR_OF32S;
> +    cpu->env.dmmucfgr = (DMMUCFGR_NTW & (0 << 2)) | (DMMUCFGR_NTS & (6 << 2));
> +    cpu->env.immucfgr = (IMMUCFGR_NTW & (0 << 2)) | (IMMUCFGR_NTS & (6 << 2));
> +
> +#ifndef CONFIG_USER_ONLY
> +    cpu->env.picmr = 0x00000000;
> +    cpu->env.picsr = 0x00000000;
> +
> +    cpu->env.ttmr = 0x00000000;
> +    cpu->env.ttcr = 0x00000000;
> +#endif
> +}
> +
> +static inline int openrisc_feature(OpenRISCCPU *cpu, int feature)

This could return bool.

> +{
> +    return (cpu->env.feature & (1u << feature)) != 0;
> +}
> +
> +static inline void set_feature(OpenRISCCPU *cpu, int feature)
> +{
> +    cpu->env.feature |= 1u << feature;
> +}
> +
> +void openrisc_cpu_realize(Object *obj, Error **errp)
> +{
> +    OpenRISCCPU *cpu = OPENRISC_CPU(obj);
> +    if (openrisc_feature(cpu, OPENRISC_FEATURE_OR1200)) {
> +        set_feature(cpu, OPENRISC_FEATURE_OB32S);
> +        set_feature(cpu, OPENRISC_FEATURE_OF32S);
> +    }
> +
> +    qemu_init_vcpu(&cpu->env);
> +}
> +
> +static void openrisc_cpu_initfn(Object *obj)
> +{
> +    OpenRISCCPU *cpu = OPENRISC_CPU(obj);
> +    cpu_exec_init(&cpu->env);
> +}
> +
> +/* CPU models */
> +static void or1200_initfn(Object *obj)
> +{
> +    OpenRISCCPU *cpu = OPENRISC_CPU(obj);
> +
> +    set_feature(cpu, OPENRISC_FEATURE_OR1200);
> +
> +    cpu_reset(CPU(cpu));
> +}
> +
> +static void openrisc_any_initfn(Object *obj)
> +{
> +    OpenRISCCPU *cpu = OPENRISC_CPU(obj);
> +
> +    set_feature(cpu, OPENRISC_FEATURE_OB32S);
> +    set_feature(cpu, OPENRISC_FEATURE_OF32S);
> +
> +    cpu_reset(CPU(cpu));
> +}

Paolo, could class_base_init or something help with this pattern of
needing to do something in every derived initfn?

On the other hand I think we should move cpu_reset() into the realizefn
instead, that would avoid this issue here.

> +
> +typedef struct OpenRISCCPUInfo {
> +    const char *name;
> +    void (*initfn)(Object *obj);
> +} OpenRISCCPUInfo;
> +
> +static const OpenRISCCPUInfo openrisc_cpus[] = {
> +    { .name = "or1200",      .initfn = or1200_initfn },
> +    { .name = "any",         .initfn = openrisc_any_initfn },
> +};
> +
> +static void openrisc_cpu_class_init(ObjectClass *oc, void *data)
> +{
> +    OpenRISCCPUClass *occ = OPENRISC_CPU_CLASS(oc);
> +    CPUClass *cc = CPU_CLASS(occ);
> +
> +    occ->parent_reset = cc->reset;
> +    cc->reset = openrisc_cpu_reset;
> +}
> +
> +static void cpu_register(const OpenRISCCPUInfo *info)
> +{
> +    TypeInfo type_info = {
> +        .name = info->name,
> +        .parent = TYPE_OPENRISC_CPU,
> +        .instance_size = sizeof(OpenRISCCPU),
> +        .instance_init = info->initfn,
> +        .class_size = sizeof(OpenRISCCPUClass),
> +    };
> +
> +    type_register_static(&type_info);
> +}
> +
> +static const TypeInfo openrisc_cpu_type_info = {
> +    .name = TYPE_OPENRISC_CPU,
> +    .parent = TYPE_CPU,
> +    .instance_size = sizeof(OpenRISCCPU),
> +    .instance_init = openrisc_cpu_initfn,
> +    .abstract = false,
> +    .class_size = sizeof(OpenRISCCPUClass),
> +    .class_init = openrisc_cpu_class_init,
> +};
> +
> +static void openrisc_cpu_register_types(void)
> +{
> +    int i;
> +
> +    type_register_static(&openrisc_cpu_type_info);
> +    for (i = 0; i < ARRAY_SIZE(openrisc_cpus); i++) {
> +        cpu_register(&openrisc_cpus[i]);
> +    }
> +}
> +
> +OpenRISCCPU *cpu_openrisc_init(const char *cpu_model)
> +{
> +    OpenRISCCPU *cpu;
> +    static int inited;
> +    inited = 0;
> +
> +    if (!object_class_by_name(cpu_model)) {
> +        return NULL;
> +    }
> +    cpu = OPENRISC_CPU(object_new(cpu_model));

This currently does a reset in initfn.

> +    cpu->env.cpu_model_str = cpu_model;
> +
> +    openrisc_cpu_realize(OBJECT(cpu), NULL);
> +
> +#ifndef CONFIG_USER_ONLY
> +    cpu_openrisc_mmu_init(cpu);
> +#endif
> +
> +    if (tcg_enabled() && !inited) {
> +        inited = 1;
> +        openrisc_translate_init();
> +    }

Could you move this into the initfn please like Igor has done for x86?

> +
> +    cpu_reset(CPU(cpu));

It is then reset again here, which is why I think doing it once in the
realizefn would be sufficient.

> +
> +    return cpu;
> +}
> +
> +typedef struct OpenRISCCPUList {
> +    fprintf_function cpu_fprintf;
> +    FILE *file;
> +} OpenRISCCPUList;
> +
> +/* Sort alphabetically by type name, except for "any". */
> +static gint openrisc_cpu_list_compare(gconstpointer a, gconstpointer b)
> +{
> +    ObjectClass *class_a = (ObjectClass *)a;
> +    ObjectClass *class_b = (ObjectClass *)b;
> +    const char *name_a, *name_b;
> +
> +    name_a = object_class_get_name(class_a);
> +    name_b = object_class_get_name(class_b);
> +    if (strcmp(name_a, "any") == 0) {
> +        return 1;
> +    } else if (strcmp(name_b, "any") == 0) {
> +        return -1;
> +    } else {
> +        return strcmp(name_a, name_b);
> +    }
> +}
> +
> +static void openrisc_cpu_list_entry(gpointer data, gpointer user_data)
> +{
> +    ObjectClass *oc = data;
> +    OpenRISCCPUList *s = user_data;
> +
> +    (*s->cpu_fprintf)(s->file, "  %s\n",
> +                      object_class_get_name(oc));
> +}
> +
> +void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf)
> +{
> +    OpenRISCCPUList s = {
> +        .file = f,
> +        .cpu_fprintf = cpu_fprintf,
> +    };
> +    GSList *list;
> +
> +    list = object_class_get_list(TYPE_OPENRISC_CPU, false);
> +    list = g_slist_sort(list, openrisc_cpu_list_compare);
> +    (*cpu_fprintf)(f, "Available CPUs:\n");
> +    g_slist_foreach(list, openrisc_cpu_list_entry, &s);
> +    g_slist_free(list);
> +}
> +
> +type_init(openrisc_cpu_register_types)
> diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
> new file mode 100644
> index 0000000..728e4b3
> --- /dev/null
> +++ b/target-openrisc/cpu.h
> @@ -0,0 +1,286 @@
> +/*
> + *  OpenRISC virtual CPU header.
> + *
> + *  Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef CPU_OPENRISC_H
> +#define CPU_OPENRISC_H
> +
> +#if defined(TARGET_OPENRISC64)
> +#define TARGET_LONG_BITS 64
> +#define ELF_MACHINE    EM_NONE

I don't see any provisions in configure for openrisc64?

> +#else
> +#define TARGET_LONG_BITS 32
> +#define ELF_MACHINE    EM_OPENRISC
> +#endif
> +
> +#define CPUArchState struct CPUOpenRISCState
> +
> +#include "config.h"
> +#include "qemu-common.h"
> +#include "cpu-defs.h"
> +#include "softfloat.h"
> +#include "qemu/cpu.h"
> +#include "error.h"
> +
> +#define TYPE_OPENRISC_CPU "or32-cpu"

"openrisc-cpu"? Also for or64 it should be adjusted.

> +
> +#define OPENRISC_CPU_CLASS(klass) \
> +    OBJECT_CLASS_CHECK(OpenRISCCPUClass, (klass), TYPE_OPENRISC_CPU)
> +#define OPENRISC_CPU(obj) \
> +    OBJECT_CHECK(OpenRISCCPU, (obj), TYPE_OPENRISC_CPU)
> +#define OPENRISC_CPU_GET_CLASS(obj) \
> +    OBJECT_GET_CLASS(OpenRISCCPUClass, (obj), TYPE_OPENRISC_CPU)
> +
> +/**
> + * OpenRISCCPUClass:
> + * @parent_reset: The parent class' reset handler.
> + *
> + * A OpenRISC CPU model.
> + */
> +typedef struct OpenRISCCPUClass {
> +    /*< private >*/
> +    CPUClass parent_class;
> +    /*< public >*/
> +
> +    void (*parent_reset)(CPUState *cpu);
> +} OpenRISCCPUClass;
> +
> +#define NB_MMU_MODES    3
> +
> +#define TARGET_PAGE_BITS 13
> +
> +#define TARGET_PHYS_ADDR_SPACE_BITS 32
> +#define TARGET_VIRT_ADDR_SPACE_BITS 32
> +
> +/* Internal flags, delay slot flag */
> +#define D_FLAG    1
> +
> +/* Registers */
> +enum {
> +    R0 = 0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10,
> +    R11, R12, R13, R14, R15, R16, R17, R18, R19, R20,
> +    R21, R22, R23, R24, R25, R26, R27, R28, R29, R30,
> +    R31
> +};
> +
> +/* Register aliases */
> +enum {
> +    R_ZERO = R0,
> +    R_SP = R1,
> +    R_FP = R2,
> +    R_LR = R9,
> +    R_RV = R11,
> +    R_RVH = R12
> +};
> +
> +/* Unit presece register */
> +enum {
> +    UPR_UP = (1 << 0),
> +    UPR_DCP = (1 << 1),
> +    UPR_ICP = (1 << 2),
> +    UPR_DMP = (1 << 3),
> +    UPR_IMP = (1 << 4),
> +    UPR_MP = (1 << 5),
> +    UPR_DUP = (1 << 6),
> +    UPR_PCUR = (1 << 7),
> +    UPR_PMP = (1 << 8),
> +    UPR_PICP = (1 << 9),
> +    UPR_TTP = (1 << 10),
> +    UPR_CUP = (255 << 24),
> +};
> +
> +/* CPU configure register */
> +enum {
> +    CPUCFGR_NSGF = (15 << 0),
> +    CPUCFGR_CGF = (1 << 4),
> +    CPUCFGR_OB32S = (1 << 5),
> +    CPUCFGR_OB64S = (1 << 6),
> +    CPUCFGR_OF32S = (1 << 7),
> +    CPUCFGR_OF64S = (1 << 8),
> +    CPUCFGR_OV64S = (1 << 9),
> +};
> +
> +/* DMMU configure register */
> +enum {
> +    DMMUCFGR_NTW = (3 << 0),
> +    DMMUCFGR_NTS = (7 << 2),
> +    DMMUCFGR_NAE = (7 << 5),
> +    DMMUCFGR_CRI = (1 << 8),
> +    DMMUCFGR_PRI = (1 << 9),
> +    DMMUCFGR_TEIRI = (1 << 10),
> +    DMMUCFGR_HTR = (1 << 11),
> +};
> +
> +/* IMMU configure register */
> +enum {
> +    IMMUCFGR_NTW = (3 << 0),
> +    IMMUCFGR_NTS = (7 << 2),
> +    IMMUCFGR_NAE = (7 << 5),
> +    IMMUCFGR_CRI = (1 << 8),
> +    IMMUCFGR_PRI = (1 << 9),
> +    IMMUCFGR_TEIRI = (1 << 10),
> +    IMMUCFGR_HTR = (1 << 11),
> +};
> +
> +/* Supervisor register */
> +enum {
> +    SR_SM = (1 << 0),
> +    SR_TEE = (1 << 1),
> +    SR_IEE = (1 << 2),
> +    SR_DCE = (1 << 3),
> +    SR_ICE = (1 << 4),
> +    SR_DME = (1 << 5),
> +    SR_IME = (1 << 6),
> +    SR_LEE = (1 << 7),
> +    SR_CE  = (1 << 8),
> +    SR_F   = (1 << 9),
> +    SR_CY  = (1 << 10),
> +    SR_OV  = (1 << 11),
> +    SR_OVE = (1 << 12),
> +    SR_DSX = (1 << 13),
> +    SR_EPH = (1 << 14),
> +    SR_FO  = (1 << 15),
> +    SR_SUMRA = (1 << 16),
> +    SR_SCE = (1 << 17),
> +};
> +
> +/* OpenRISC Hardware Capabilities */
> +enum {
> +    OPENRISC_FEATURE_NSGF,
> +    OPENRISC_FEATURE_CGF,
> +    OPENRISC_FEATURE_OB32S,
> +    OPENRISC_FEATURE_OB64S,
> +    OPENRISC_FEATURE_OF32S,
> +    OPENRISC_FEATURE_OF64S,
> +    OPENRISC_FEATURE_OV64S,
> +    OPENRISC_FEATURE_OR1200,
> +};
> +
> +typedef struct CPUOpenRISCState {
> +    target_ulong gpr[32];     /* General registers */
> +    target_ulong pc;          /* Program counter */
> +    target_ulong npc;         /* Next PC */
> +    target_ulong ppc;         /* Prev PC */
> +    target_ulong jmp_pc;      /* Jump PC */
> +
> +    uint32_t sr;              /* Supervisor register */
> +    uint32_t vr;              /* Version register */
> +    uint32_t upr;             /* Unit presence register */
> +    uint32_t cpucfgr;         /* CPU configure register */
> +    uint32_t dmmucfgr;        /* DMMU configure register */
> +    uint32_t immucfgr;        /* IMMU configure register */
> +
> +    uint32_t flags;           /* cpu_flags, we only use it for exception
> +                                 in solt so far.  */
> +    uint32_t btaken;          /* the SR_F bit */
> +
> +    CPU_COMMON
> +
> +#ifndef CONFIG_USER_ONLY
> +    struct QEMUTimer *timer;
> +    uint32_t ttmr;          /* Timer tick mode register */
> +    uint32_t ttcr;          /* Timer tick count register */
> +
> +    uint32_t picmr;         /* Interrupt mask register */
> +    uint32_t picsr;         /* Interrupt contrl register*/
> +#endif
> +    uint32_t feature;       /* CPU Capabilities */

Could the feature(s) field be moved into OpenRISCCPU after env?

> +} CPUOpenRISCState;
> +
> +/**
> + * OpenRISCCPU:
> + * @env: #CPUOpenRISCState
> + *
> + * A OpenRISC CPU.
> + */
> +typedef struct OpenRISCCPU {
> +    /*< private >*/
> +    CPUState parent_obj;
> +    /*< public >*/
> +
> +    CPUOpenRISCState env;
> +} OpenRISCCPU;
> +
> +static inline OpenRISCCPU *openrisc_env_get_cpu(CPUOpenRISCState *env)
> +{
> +    return OPENRISC_CPU(container_of(env, OpenRISCCPU, env));
> +}
> +
> +#define ENV_GET_CPU(e) CPU(openrisc_env_get_cpu(e))
> +
> +OpenRISCCPU *cpu_openrisc_init(const char *cpu_model);
> +void openrisc_cpu_realize(Object *obj, Error **errp);
> +
> +void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf);
> +int cpu_openrisc_exec(CPUOpenRISCState *s);
> +void do_interrupt(CPUOpenRISCState *env);
> +void openrisc_translate_init(void);
> +
> +#define cpu_list cpu_openrisc_list
> +#define cpu_exec cpu_openrisc_exec
> +#define cpu_gen_code cpu_openrisc_gen_code
> +
> +#define CPU_SAVE_VERSION 1

Is this still needed?

> +
> +#ifndef CONFIG_USER_ONLY
> +void cpu_openrisc_mmu_init(OpenRISCCPU *cpu);
> +#endif
> +
> +static inline CPUOpenRISCState *cpu_init(const char *cpu_model)
> +{
> +    OpenRISCCPU *cpu = cpu_openrisc_init(cpu_model);
> +    if (cpu) {
> +        return &cpu->env;
> +    }
> +    return NULL;
> +}
> +
> +#include "cpu-all.h"
> +
> +static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env,
> +                                        target_ulong *pc,
> +                                        target_ulong *cs_base, int *flags)
> +{
> +    *pc = env->pc;
> +    *cs_base = 0;
> +    *flags = 0;
> +}
> +
> +static inline int cpu_mmu_index(CPUOpenRISCState *env)
> +{
> +    return 0;
> +}
> +
> +static inline bool cpu_has_work(CPUOpenRISCState *env)
> +{
> +    return true;
> +}
> +
> +#include "exec-all.h"
> +
> +static inline target_ulong cpu_get_pc(CPUOpenRISCState *env)
> +{
> +    return env->pc;
> +}
> +
> +static inline void cpu_pc_from_tb(CPUOpenRISCState *env, TranslationBlock *tb)
> +{
> +    env->pc = tb->pc;
> +}
> +
> +#endif /* CPU_OPENRISC_H */
> diff --git a/target-openrisc/intrpt.c b/target-openrisc/intrpt.c
> new file mode 100644
> index 0000000..a3bb7f8
> --- /dev/null
> +++ b/target-openrisc/intrpt.c
> @@ -0,0 +1,30 @@
> +/*
> + *  OpenRISC interrupt.
> + *
> + *  Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "cpu.h"
> +#include "qemu-common.h"
> +#include "gdbstub.h"
> +#include "host-utils.h"
> +#ifndef CONFIG_USER_ONLY
> +#include "hw/loader.h"
> +#endif
> +
> +void do_interrupt(CPUOpenRISCState *env)
> +{
> +}
> diff --git a/target-openrisc/machine.c b/target-openrisc/machine.c
> new file mode 100644
> index 0000000..11bf275
> --- /dev/null
> +++ b/target-openrisc/machine.c
> @@ -0,0 +1,30 @@
> +/*
> + *  OpenRISC Machine
> + *
> + *  Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "hw/hw.h"
> +#include "hw/boards.h"
> +
> +void cpu_save(QEMUFile *f, void *opaque)
> +{
> +}
> +
> +int cpu_load(QEMUFile *f, void *opaque, int version_id)
> +{
> +    return 0;
> +}
[snip]

Shouldn't this be using VMState? Was there any problem converting?

Andreas
Paolo Bonzini July 5, 2012, 1:31 p.m. UTC | #2
Il 05/07/2012 15:22, Andreas Färber ha scritto:
>> > +static void openrisc_any_initfn(Object *obj)
>> > +{
>> > +    OpenRISCCPU *cpu = OPENRISC_CPU(obj);
>> > +
>> > +    set_feature(cpu, OPENRISC_FEATURE_OB32S);
>> > +    set_feature(cpu, OPENRISC_FEATURE_OF32S);
>> > +
>> > +    cpu_reset(CPU(cpu));
>> > +}
> Paolo, could class_base_init or something help with this pattern of
> needing to do something in every derived initfn?

I guess what you're looking for is some instance_post_init that is
called at init time after instance_init?

> On the other hand I think we should move cpu_reset() into the realizefn
> instead, that would avoid this issue here.

Yep.

Paolo
Andreas Färber July 5, 2012, 3:31 p.m. UTC | #3
Am 05.07.2012 15:31, schrieb Paolo Bonzini:
> Il 05/07/2012 15:22, Andreas Färber ha scritto:
>>>> +static void openrisc_any_initfn(Object *obj)
>>>> +{
>>>> +    OpenRISCCPU *cpu = OPENRISC_CPU(obj);
>>>> +
>>>> +    set_feature(cpu, OPENRISC_FEATURE_OB32S);
>>>> +    set_feature(cpu, OPENRISC_FEATURE_OF32S);
>>>> +
>>>> +    cpu_reset(CPU(cpu));
>>>> +}
>> Paolo, could class_base_init or something help with this pattern of
>> needing to do something in every derived initfn?
> 
> I guess what you're looking for is some instance_post_init that is
> called at init time after instance_init?

Sort of. The pattern I was seeing is parent initializes something, child
modifies it, some action is performed on it.

Here we can get away by deferring the common action to realize stage,
just like we did for arm. My reasoning was that it's better to reset in
realizefn for reproducible behavior over system_reset. Not sure if we
can always escape to such a late stage, but we can worry about that when
we have a concrete use case. :)

Andreas

>> On the other hand I think we should move cpu_reset() into the realizefn
>> instead, that would avoid this issue here.
> 
> Yep.
> 
> Paolo
Jia Liu July 9, 2012, 7:08 a.m. UTC | #4
Hi Andreas,

Thank you for comment.
I've tried fix them, but I'm afraid I didn't fully understand what you mean.
Please read the new code and give me some comment, please.

On Thu, Jul 5, 2012 at 9:22 PM, Andreas Färber <afaerber@suse.de> wrote:
> Am 01.07.2012 04:45, schrieb Jia Liu:
>> Add OpenRISC target stubs and cpu support.
>>
>> Signed-off-by: Jia Liu <proljc@gmail.com>
>> ---
>>  arch_init.c                      |    2 +
>>  arch_init.h                      |    1 +
>>  configure                        |   14 +-
>>  cpu-exec.c                       |    2 +
>>  default-configs/or32-softmmu.mak |    4 +
>>  elf.h                            |    2 +
>>  hw/openrisc/Makefile.objs        |    1 +
>>  poison.h                         |    1 +
>>  target-openrisc/Makefile.objs    |    3 +
>>  target-openrisc/cpu.c            |  236 +++++++++++++++++++++++++++++++
>>  target-openrisc/cpu.h            |  286 ++++++++++++++++++++++++++++++++++++++
>>  target-openrisc/intrpt.c         |   30 ++++
>>  target-openrisc/machine.c        |   30 ++++
>>  target-openrisc/mmu.c            |   39 ++++++
>>  target-openrisc/mmu_helper.c     |   43 ++++++
>>  target-openrisc/translate.c      |   75 ++++++++++
>>  16 files changed, 767 insertions(+), 2 deletions(-)
>>  create mode 100644 default-configs/or32-softmmu.mak
>>  create mode 100644 hw/openrisc/Makefile.objs
>>  create mode 100644 target-openrisc/Makefile.objs
>>  create mode 100644 target-openrisc/cpu.c
>>  create mode 100644 target-openrisc/cpu.h
>>  create mode 100644 target-openrisc/intrpt.c
>>  create mode 100644 target-openrisc/machine.c
>>  create mode 100644 target-openrisc/mmu.c
>>  create mode 100644 target-openrisc/mmu_helper.c
>>  create mode 100644 target-openrisc/translate.c
>
>> diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
>> new file mode 100644
>> index 0000000..21b76b2
>> --- /dev/null
>> +++ b/target-openrisc/Makefile.objs
>> @@ -0,0 +1,3 @@
>> +obj-$(CONFIG_SOFTMMU) += machine.o
>> +obj-y += cpu.o intrpt.o mmu.o translate.o
>
> intrpt.o? Any chance of a better to read/remember file name?

Is interrupt.o OK?

>
>> +obj-y += mmu_helper.o
>> diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
>> new file mode 100644
>> index 0000000..64ddc98
>> --- /dev/null
>> +++ b/target-openrisc/cpu.c
>> @@ -0,0 +1,236 @@
>> +/*
>> + *  QEMU OpenRISC CPU
>> + *
>> + *  Copyright (c) 2012 Jia Liu <proljc@gmail.com>
>
> Two-space indentation? (also in other files)

I'll change all of them into one-space indentation.

>
>> + *
>> + * This library is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU Lesser General Public
>> + * License as published by the Free Software Foundation; either
>> + * version 2 of the License, or (at your option) any later version.
>> + *
>> + * This library is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> + * Lesser General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU Lesser General Public
>> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include "cpu.h"
>> +#include "qemu-common.h"
>
>> +#ifndef CONFIG_USER_ONLY
>> +#include "hw/loader.h"
>> +#endif
>
> Not yet needed in this patch?

Thanks, I've deleted them.

>
>> +
>> +/* CPUClass::reset() */
>> +static void openrisc_cpu_reset(CPUState *s)
>> +{
>> +    OpenRISCCPU *cpu = OPENRISC_CPU(s);
>> +    OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(cpu);
>> +
>> +    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
>> +        qemu_log("CPU Reset (CPU %d)\n", cpu->env.cpu_index);
>> +        log_cpu_state(&cpu->env, 0);
>> +    }
>> +
>> +    occ->parent_reset(s);
>> +
>> +    memset(&cpu->env, 0, offsetof(CPUOpenRISCState, breakpoints));
>
> Note, if you wanted, you could've declared a CPUOpenRISCState *env to
> avoid re-typing "cpu->env." or "&cpu->env".

Thank you for notice me.

>
>> +
>> +    tlb_flush(&cpu->env, 1);
>> +    /*tb_flush(&cpu->env);    FIXME: Do we need it?  */
>> +
>> +    cpu->env.pc = 0x100;
>> +    cpu->env.sr = SR_FO | SR_SM;
>> +    cpu->env.exception_index = -1;
>> +
>> +    cpu->env.upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP;
>> +    cpu->env.cpucfgr = CPUCFGR_OB32S | CPUCFGR_OF32S;
>> +    cpu->env.dmmucfgr = (DMMUCFGR_NTW & (0 << 2)) | (DMMUCFGR_NTS & (6 << 2));
>> +    cpu->env.immucfgr = (IMMUCFGR_NTW & (0 << 2)) | (IMMUCFGR_NTS & (6 << 2));
>> +
>> +#ifndef CONFIG_USER_ONLY
>> +    cpu->env.picmr = 0x00000000;
>> +    cpu->env.picsr = 0x00000000;
>> +
>> +    cpu->env.ttmr = 0x00000000;
>> +    cpu->env.ttcr = 0x00000000;
>> +#endif
>> +}
>> +
>> +static inline int openrisc_feature(OpenRISCCPU *cpu, int feature)
>
> This could return bool.

Thank you for point this!

>
>> +{
>> +    return (cpu->env.feature & (1u << feature)) != 0;
>> +}
>> +
>> +static inline void set_feature(OpenRISCCPU *cpu, int feature)
>> +{
>> +    cpu->env.feature |= 1u << feature;
>> +}
>> +
>> +void openrisc_cpu_realize(Object *obj, Error **errp)
>> +{
>> +    OpenRISCCPU *cpu = OPENRISC_CPU(obj);
>> +    if (openrisc_feature(cpu, OPENRISC_FEATURE_OR1200)) {
>> +        set_feature(cpu, OPENRISC_FEATURE_OB32S);
>> +        set_feature(cpu, OPENRISC_FEATURE_OF32S);
>> +    }
>> +
>> +    qemu_init_vcpu(&cpu->env);
>> +}
>> +
>> +static void openrisc_cpu_initfn(Object *obj)
>> +{
>> +    OpenRISCCPU *cpu = OPENRISC_CPU(obj);
>> +    cpu_exec_init(&cpu->env);
>> +}
>> +
>> +/* CPU models */
>> +static void or1200_initfn(Object *obj)
>> +{
>> +    OpenRISCCPU *cpu = OPENRISC_CPU(obj);
>> +
>> +    set_feature(cpu, OPENRISC_FEATURE_OR1200);
>> +
>> +    cpu_reset(CPU(cpu));
>> +}
>> +
>> +static void openrisc_any_initfn(Object *obj)
>> +{
>> +    OpenRISCCPU *cpu = OPENRISC_CPU(obj);
>> +
>> +    set_feature(cpu, OPENRISC_FEATURE_OB32S);
>> +    set_feature(cpu, OPENRISC_FEATURE_OF32S);
>> +
>> +    cpu_reset(CPU(cpu));
>> +}
>
> Paolo, could class_base_init or something help with this pattern of
> needing to do something in every derived initfn?
>
> On the other hand I think we should move cpu_reset() into the realizefn
> instead, that would avoid this issue here.
>

Sorry, I'm not true about this.
May take a look at the new code?
/* CPU models */
static void or1200_initfn(Object *obj)
{
    OpenRISCCPU *cpu = OPENRISC_CPU(obj);

    set_feature(cpu, OPENRISC_FEATURE_OB32S);
    set_feature(cpu, OPENRISC_FEATURE_OF32S);
}

static void openrisc_any_initfn(Object *obj)
{
    OpenRISCCPU *cpu = OPENRISC_CPU(obj);

    set_feature(cpu, OPENRISC_FEATURE_OB32S);
}


>> +
>> +typedef struct OpenRISCCPUInfo {
>> +    const char *name;
>> +    void (*initfn)(Object *obj);
>> +} OpenRISCCPUInfo;
>> +
>> +static const OpenRISCCPUInfo openrisc_cpus[] = {
>> +    { .name = "or1200",      .initfn = or1200_initfn },
>> +    { .name = "any",         .initfn = openrisc_any_initfn },
>> +};
>> +
>> +static void openrisc_cpu_class_init(ObjectClass *oc, void *data)
>> +{
>> +    OpenRISCCPUClass *occ = OPENRISC_CPU_CLASS(oc);
>> +    CPUClass *cc = CPU_CLASS(occ);
>> +
>> +    occ->parent_reset = cc->reset;
>> +    cc->reset = openrisc_cpu_reset;
>> +}
>> +
>> +static void cpu_register(const OpenRISCCPUInfo *info)
>> +{
>> +    TypeInfo type_info = {
>> +        .name = info->name,
>> +        .parent = TYPE_OPENRISC_CPU,
>> +        .instance_size = sizeof(OpenRISCCPU),
>> +        .instance_init = info->initfn,
>> +        .class_size = sizeof(OpenRISCCPUClass),
>> +    };
>> +
>> +    type_register_static(&type_info);
>> +}
>> +
>> +static const TypeInfo openrisc_cpu_type_info = {
>> +    .name = TYPE_OPENRISC_CPU,
>> +    .parent = TYPE_CPU,
>> +    .instance_size = sizeof(OpenRISCCPU),
>> +    .instance_init = openrisc_cpu_initfn,
>> +    .abstract = false,
>> +    .class_size = sizeof(OpenRISCCPUClass),
>> +    .class_init = openrisc_cpu_class_init,
>> +};
>> +
>> +static void openrisc_cpu_register_types(void)
>> +{
>> +    int i;
>> +
>> +    type_register_static(&openrisc_cpu_type_info);
>> +    for (i = 0; i < ARRAY_SIZE(openrisc_cpus); i++) {
>> +        cpu_register(&openrisc_cpus[i]);
>> +    }
>> +}
>> +
>> +OpenRISCCPU *cpu_openrisc_init(const char *cpu_model)
>> +{
>> +    OpenRISCCPU *cpu;
>> +    static int inited;
>> +    inited = 0;
>> +
>> +    if (!object_class_by_name(cpu_model)) {
>> +        return NULL;
>> +    }
>> +    cpu = OPENRISC_CPU(object_new(cpu_model));
>
> This currently does a reset in initfn.
>
>> +    cpu->env.cpu_model_str = cpu_model;
>> +
>> +    openrisc_cpu_realize(OBJECT(cpu), NULL);
>> +
>> +#ifndef CONFIG_USER_ONLY
>> +    cpu_openrisc_mmu_init(cpu);
>> +#endif
>> +
>> +    if (tcg_enabled() && !inited) {
>> +        inited = 1;
>> +        openrisc_translate_init();
>> +    }
>
> Could you move this into the initfn please like Igor has done for x86?
>
>> +
>> +    cpu_reset(CPU(cpu));
>
> It is then reset again here, which is why I think doing it once in the
> realizefn would be sufficient.
>

Sorry, I didn't fully understand it. May you take a look at the new code?

OpenRISCCPU *cpu_openrisc_init(const char *cpu_model)
{
    OpenRISCCPU *cpu;
    static int inited;
    inited = 0;

    if (!object_class_by_name(cpu_model)) {
        return NULL;
    }
    cpu = OPENRISC_CPU(object_new(cpu_model));
    cpu->env.cpu_model_str = cpu_model;

    openrisc_cpu_realize(OBJECT(cpu), NULL);

#ifndef CONFIG_USER_ONLY
    cpu_openrisc_mmu_init(cpu);
#endif

    if (tcg_enabled() && !inited) {
        inited = 1;
        openrisc_translate_init();
    }

    return cpu;
}

>> +
>> +    return cpu;
>> +}
>> +
>> +typedef struct OpenRISCCPUList {
>> +    fprintf_function cpu_fprintf;
>> +    FILE *file;
>> +} OpenRISCCPUList;
>> +
>> +/* Sort alphabetically by type name, except for "any". */
>> +static gint openrisc_cpu_list_compare(gconstpointer a, gconstpointer b)
>> +{
>> +    ObjectClass *class_a = (ObjectClass *)a;
>> +    ObjectClass *class_b = (ObjectClass *)b;
>> +    const char *name_a, *name_b;
>> +
>> +    name_a = object_class_get_name(class_a);
>> +    name_b = object_class_get_name(class_b);
>> +    if (strcmp(name_a, "any") == 0) {
>> +        return 1;
>> +    } else if (strcmp(name_b, "any") == 0) {
>> +        return -1;
>> +    } else {
>> +        return strcmp(name_a, name_b);
>> +    }
>> +}
>> +
>> +static void openrisc_cpu_list_entry(gpointer data, gpointer user_data)
>> +{
>> +    ObjectClass *oc = data;
>> +    OpenRISCCPUList *s = user_data;
>> +
>> +    (*s->cpu_fprintf)(s->file, "  %s\n",
>> +                      object_class_get_name(oc));
>> +}
>> +
>> +void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf)
>> +{
>> +    OpenRISCCPUList s = {
>> +        .file = f,
>> +        .cpu_fprintf = cpu_fprintf,
>> +    };
>> +    GSList *list;
>> +
>> +    list = object_class_get_list(TYPE_OPENRISC_CPU, false);
>> +    list = g_slist_sort(list, openrisc_cpu_list_compare);
>> +    (*cpu_fprintf)(f, "Available CPUs:\n");
>> +    g_slist_foreach(list, openrisc_cpu_list_entry, &s);
>> +    g_slist_free(list);
>> +}
>> +
>> +type_init(openrisc_cpu_register_types)
>> diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
>> new file mode 100644
>> index 0000000..728e4b3
>> --- /dev/null
>> +++ b/target-openrisc/cpu.h
>> @@ -0,0 +1,286 @@
>> +/*
>> + *  OpenRISC virtual CPU header.
>> + *
>> + *  Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
>> + *
>> + * This library is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU Lesser General Public
>> + * License as published by the Free Software Foundation; either
>> + * version 2 of the License, or (at your option) any later version.
>> + *
>> + * This library is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> + * Lesser General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU Lesser General Public
>> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#ifndef CPU_OPENRISC_H
>> +#define CPU_OPENRISC_H
>> +
>> +#if defined(TARGET_OPENRISC64)
>> +#define TARGET_LONG_BITS 64
>> +#define ELF_MACHINE    EM_NONE
>
> I don't see any provisions in configure for openrisc64?

or64 is not implemented, I'll delete/commented all of them.

>
>> +#else
>> +#define TARGET_LONG_BITS 32
>> +#define ELF_MACHINE    EM_OPENRISC
>> +#endif
>> +
>> +#define CPUArchState struct CPUOpenRISCState
>> +
>> +#include "config.h"
>> +#include "qemu-common.h"
>> +#include "cpu-defs.h"
>> +#include "softfloat.h"
>> +#include "qemu/cpu.h"
>> +#include "error.h"
>> +
>> +#define TYPE_OPENRISC_CPU "or32-cpu"
>
> "openrisc-cpu"? Also for or64 it should be adjusted.
>

or64 is not implemented, I'll delete/comment all of them.

>> +
>> +#define OPENRISC_CPU_CLASS(klass) \
>> +    OBJECT_CLASS_CHECK(OpenRISCCPUClass, (klass), TYPE_OPENRISC_CPU)
>> +#define OPENRISC_CPU(obj) \
>> +    OBJECT_CHECK(OpenRISCCPU, (obj), TYPE_OPENRISC_CPU)
>> +#define OPENRISC_CPU_GET_CLASS(obj) \
>> +    OBJECT_GET_CLASS(OpenRISCCPUClass, (obj), TYPE_OPENRISC_CPU)
>> +
>> +/**
>> + * OpenRISCCPUClass:
>> + * @parent_reset: The parent class' reset handler.
>> + *
>> + * A OpenRISC CPU model.
>> + */
>> +typedef struct OpenRISCCPUClass {
>> +    /*< private >*/
>> +    CPUClass parent_class;
>> +    /*< public >*/
>> +
>> +    void (*parent_reset)(CPUState *cpu);
>> +} OpenRISCCPUClass;
>> +
>> +#define NB_MMU_MODES    3
>> +
>> +#define TARGET_PAGE_BITS 13
>> +
>> +#define TARGET_PHYS_ADDR_SPACE_BITS 32
>> +#define TARGET_VIRT_ADDR_SPACE_BITS 32
>> +
>> +/* Internal flags, delay slot flag */
>> +#define D_FLAG    1
>> +
>> +/* Registers */
>> +enum {
>> +    R0 = 0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10,
>> +    R11, R12, R13, R14, R15, R16, R17, R18, R19, R20,
>> +    R21, R22, R23, R24, R25, R26, R27, R28, R29, R30,
>> +    R31
>> +};
>> +
>> +/* Register aliases */
>> +enum {
>> +    R_ZERO = R0,
>> +    R_SP = R1,
>> +    R_FP = R2,
>> +    R_LR = R9,
>> +    R_RV = R11,
>> +    R_RVH = R12
>> +};
>> +
>> +/* Unit presece register */
>> +enum {
>> +    UPR_UP = (1 << 0),
>> +    UPR_DCP = (1 << 1),
>> +    UPR_ICP = (1 << 2),
>> +    UPR_DMP = (1 << 3),
>> +    UPR_IMP = (1 << 4),
>> +    UPR_MP = (1 << 5),
>> +    UPR_DUP = (1 << 6),
>> +    UPR_PCUR = (1 << 7),
>> +    UPR_PMP = (1 << 8),
>> +    UPR_PICP = (1 << 9),
>> +    UPR_TTP = (1 << 10),
>> +    UPR_CUP = (255 << 24),
>> +};
>> +
>> +/* CPU configure register */
>> +enum {
>> +    CPUCFGR_NSGF = (15 << 0),
>> +    CPUCFGR_CGF = (1 << 4),
>> +    CPUCFGR_OB32S = (1 << 5),
>> +    CPUCFGR_OB64S = (1 << 6),
>> +    CPUCFGR_OF32S = (1 << 7),
>> +    CPUCFGR_OF64S = (1 << 8),
>> +    CPUCFGR_OV64S = (1 << 9),
>> +};
>> +
>> +/* DMMU configure register */
>> +enum {
>> +    DMMUCFGR_NTW = (3 << 0),
>> +    DMMUCFGR_NTS = (7 << 2),
>> +    DMMUCFGR_NAE = (7 << 5),
>> +    DMMUCFGR_CRI = (1 << 8),
>> +    DMMUCFGR_PRI = (1 << 9),
>> +    DMMUCFGR_TEIRI = (1 << 10),
>> +    DMMUCFGR_HTR = (1 << 11),
>> +};
>> +
>> +/* IMMU configure register */
>> +enum {
>> +    IMMUCFGR_NTW = (3 << 0),
>> +    IMMUCFGR_NTS = (7 << 2),
>> +    IMMUCFGR_NAE = (7 << 5),
>> +    IMMUCFGR_CRI = (1 << 8),
>> +    IMMUCFGR_PRI = (1 << 9),
>> +    IMMUCFGR_TEIRI = (1 << 10),
>> +    IMMUCFGR_HTR = (1 << 11),
>> +};
>> +
>> +/* Supervisor register */
>> +enum {
>> +    SR_SM = (1 << 0),
>> +    SR_TEE = (1 << 1),
>> +    SR_IEE = (1 << 2),
>> +    SR_DCE = (1 << 3),
>> +    SR_ICE = (1 << 4),
>> +    SR_DME = (1 << 5),
>> +    SR_IME = (1 << 6),
>> +    SR_LEE = (1 << 7),
>> +    SR_CE  = (1 << 8),
>> +    SR_F   = (1 << 9),
>> +    SR_CY  = (1 << 10),
>> +    SR_OV  = (1 << 11),
>> +    SR_OVE = (1 << 12),
>> +    SR_DSX = (1 << 13),
>> +    SR_EPH = (1 << 14),
>> +    SR_FO  = (1 << 15),
>> +    SR_SUMRA = (1 << 16),
>> +    SR_SCE = (1 << 17),
>> +};
>> +
>> +/* OpenRISC Hardware Capabilities */
>> +enum {
>> +    OPENRISC_FEATURE_NSGF,
>> +    OPENRISC_FEATURE_CGF,
>> +    OPENRISC_FEATURE_OB32S,
>> +    OPENRISC_FEATURE_OB64S,
>> +    OPENRISC_FEATURE_OF32S,
>> +    OPENRISC_FEATURE_OF64S,
>> +    OPENRISC_FEATURE_OV64S,
>> +    OPENRISC_FEATURE_OR1200,
>> +};
>> +
>> +typedef struct CPUOpenRISCState {
>> +    target_ulong gpr[32];     /* General registers */
>> +    target_ulong pc;          /* Program counter */
>> +    target_ulong npc;         /* Next PC */
>> +    target_ulong ppc;         /* Prev PC */
>> +    target_ulong jmp_pc;      /* Jump PC */
>> +
>> +    uint32_t sr;              /* Supervisor register */
>> +    uint32_t vr;              /* Version register */
>> +    uint32_t upr;             /* Unit presence register */
>> +    uint32_t cpucfgr;         /* CPU configure register */
>> +    uint32_t dmmucfgr;        /* DMMU configure register */
>> +    uint32_t immucfgr;        /* IMMU configure register */
>> +
>> +    uint32_t flags;           /* cpu_flags, we only use it for exception
>> +                                 in solt so far.  */
>> +    uint32_t btaken;          /* the SR_F bit */
>> +
>> +    CPU_COMMON
>> +
>> +#ifndef CONFIG_USER_ONLY
>> +    struct QEMUTimer *timer;
>> +    uint32_t ttmr;          /* Timer tick mode register */
>> +    uint32_t ttcr;          /* Timer tick count register */
>> +
>> +    uint32_t picmr;         /* Interrupt mask register */
>> +    uint32_t picsr;         /* Interrupt contrl register*/
>> +#endif
>> +    uint32_t feature;       /* CPU Capabilities */
>
> Could the feature(s) field be moved into OpenRISCCPU after env?

Thank you, done.

>
>> +} CPUOpenRISCState;
>> +
>> +/**
>> + * OpenRISCCPU:
>> + * @env: #CPUOpenRISCState
>> + *
>> + * A OpenRISC CPU.
>> + */
>> +typedef struct OpenRISCCPU {
>> +    /*< private >*/
>> +    CPUState parent_obj;
>> +    /*< public >*/
>> +
>> +    CPUOpenRISCState env;
>> +} OpenRISCCPU;
>> +
>> +static inline OpenRISCCPU *openrisc_env_get_cpu(CPUOpenRISCState *env)
>> +{
>> +    return OPENRISC_CPU(container_of(env, OpenRISCCPU, env));
>> +}
>> +
>> +#define ENV_GET_CPU(e) CPU(openrisc_env_get_cpu(e))
>> +
>> +OpenRISCCPU *cpu_openrisc_init(const char *cpu_model);
>> +void openrisc_cpu_realize(Object *obj, Error **errp);
>> +
>> +void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf);
>> +int cpu_openrisc_exec(CPUOpenRISCState *s);
>> +void do_interrupt(CPUOpenRISCState *env);
>> +void openrisc_translate_init(void);
>> +
>> +#define cpu_list cpu_openrisc_list
>> +#define cpu_exec cpu_openrisc_exec
>> +#define cpu_gen_code cpu_openrisc_gen_code
>> +
>> +#define CPU_SAVE_VERSION 1
>
> Is this still needed?

Thanks, I'll delete it.

>
>> +
>> +#ifndef CONFIG_USER_ONLY
>> +void cpu_openrisc_mmu_init(OpenRISCCPU *cpu);
>> +#endif
>> +
>> +static inline CPUOpenRISCState *cpu_init(const char *cpu_model)
>> +{
>> +    OpenRISCCPU *cpu = cpu_openrisc_init(cpu_model);
>> +    if (cpu) {
>> +        return &cpu->env;
>> +    }
>> +    return NULL;
>> +}
>> +
>> +#include "cpu-all.h"
>> +
>> +static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env,
>> +                                        target_ulong *pc,
>> +                                        target_ulong *cs_base, int *flags)
>> +{
>> +    *pc = env->pc;
>> +    *cs_base = 0;
>> +    *flags = 0;
>> +}
>> +
>> +static inline int cpu_mmu_index(CPUOpenRISCState *env)
>> +{
>> +    return 0;
>> +}
>> +
>> +static inline bool cpu_has_work(CPUOpenRISCState *env)
>> +{
>> +    return true;
>> +}
>> +
>> +#include "exec-all.h"
>> +
>> +static inline target_ulong cpu_get_pc(CPUOpenRISCState *env)
>> +{
>> +    return env->pc;
>> +}
>> +
>> +static inline void cpu_pc_from_tb(CPUOpenRISCState *env, TranslationBlock *tb)
>> +{
>> +    env->pc = tb->pc;
>> +}
>> +
>> +#endif /* CPU_OPENRISC_H */
>> diff --git a/target-openrisc/intrpt.c b/target-openrisc/intrpt.c
>> new file mode 100644
>> index 0000000..a3bb7f8
>> --- /dev/null
>> +++ b/target-openrisc/intrpt.c
>> @@ -0,0 +1,30 @@
>> +/*
>> + *  OpenRISC interrupt.
>> + *
>> + *  Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
>> + *
>> + * This library is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU Lesser General Public
>> + * License as published by the Free Software Foundation; either
>> + * version 2 of the License, or (at your option) any later version.
>> + *
>> + * This library is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> + * Lesser General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU Lesser General Public
>> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include "cpu.h"
>> +#include "qemu-common.h"
>> +#include "gdbstub.h"
>> +#include "host-utils.h"
>> +#ifndef CONFIG_USER_ONLY
>> +#include "hw/loader.h"
>> +#endif
>> +
>> +void do_interrupt(CPUOpenRISCState *env)
>> +{
>> +}
>> diff --git a/target-openrisc/machine.c b/target-openrisc/machine.c
>> new file mode 100644
>> index 0000000..11bf275
>> --- /dev/null
>> +++ b/target-openrisc/machine.c
>> @@ -0,0 +1,30 @@
>> +/*
>> + *  OpenRISC Machine
>> + *
>> + *  Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
>> + *
>> + * This library is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU Lesser General Public
>> + * License as published by the Free Software Foundation; either
>> + * version 2 of the License, or (at your option) any later version.
>> + *
>> + * This library is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> + * Lesser General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU Lesser General Public
>> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include "hw/hw.h"
>> +#include "hw/boards.h"
>> +
>> +void cpu_save(QEMUFile *f, void *opaque)
>> +{
>> +}
>> +
>> +int cpu_load(QEMUFile *f, void *opaque, int version_id)
>> +{
>> +    return 0;
>> +}
> [snip]
>
> Shouldn't this be using VMState? Was there any problem converting?
>

Sorry, I'm not very sure. Is this code OK?

static const VMStateDescription vmstate_cpu = {
    .name = "cpu",
    .fields = (VMStateField[]) {
        VMSTATE_UINT32_ARRAY(gpr, CPUOpenRISCState, 32),
        VMSTATE_UINT32(sr, CPUOpenRISCState),
        VMSTATE_UINT32(epcr, CPUOpenRISCState),
        VMSTATE_UINT32(eear, CPUOpenRISCState),
        VMSTATE_UINT32(esr, CPUOpenRISCState),
        VMSTATE_UINT32(fpcsr, CPUOpenRISCState),
        VMSTATE_UINT32(pc, CPUOpenRISCState),
        VMSTATE_UINT32(npc, CPUOpenRISCState),
        VMSTATE_UINT32(ppc, CPUOpenRISCState),
        VMSTATE_END_OF_LIST()
    }
};

void cpu_save(QEMUFile *f, void *opaque)
{
    vmstate_save_state(f, &vmstate_cpu, opaque);
}

int cpu_load(QEMUFile *f, void *opaque, int version_id)
{
    return vmstate_load_state(f, &vmstate_cpu, opaque, version_id);
}


> Andreas
>
> --
> SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
> GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
>
>

Regards,
JIa.
diff mbox

Patch

diff --git a/arch_init.c b/arch_init.c
index a9e8b74..4b521e5 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -71,6 +71,8 @@  int graphic_depth = 15;
 #define QEMU_ARCH QEMU_ARCH_MICROBLAZE
 #elif defined(TARGET_MIPS)
 #define QEMU_ARCH QEMU_ARCH_MIPS
+#elif defined(TARGET_OPENRISC)
+#define QEMU_ARCH QEMU_ARCH_OPENRISC
 #elif defined(TARGET_PPC)
 #define QEMU_ARCH QEMU_ARCH_PPC
 #elif defined(TARGET_S390X)
diff --git a/arch_init.h b/arch_init.h
index c7cb94a..3dfea3b 100644
--- a/arch_init.h
+++ b/arch_init.h
@@ -16,6 +16,7 @@  enum {
     QEMU_ARCH_SH4 = 1024,
     QEMU_ARCH_SPARC = 2048,
     QEMU_ARCH_XTENSA = 4096,
+    QEMU_ARCH_OPENRISC = 8192,
 };
 
 extern const uint32_t arch_type;
diff --git a/configure b/configure
index 9f071b7..7780876 100755
--- a/configure
+++ b/configure
@@ -924,6 +924,7 @@  mips-softmmu \
 mipsel-softmmu \
 mips64-softmmu \
 mips64el-softmmu \
+or32-softmmu \
 ppc-softmmu \
 ppcemb-softmmu \
 ppc64-softmmu \
@@ -3503,7 +3504,7 @@  target_arch2=`echo $target | cut -d '-' -f 1`
 target_bigendian="no"
 
 case "$target_arch2" in
-  armeb|lm32|m68k|microblaze|mips|mipsn32|mips64|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb)
+  armeb|lm32|m68k|microblaze|mips|mipsn32|mips64|or32|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb)
   target_bigendian=yes
   ;;
 esac
@@ -3619,6 +3620,11 @@  case "$target_arch2" in
     target_phys_bits=64
     target_long_alignment=8
   ;;
+  or32)
+    TARGET_ARCH=openrisc
+    TARGET_BASE_ARCH=openrisc
+    target_phys_bits=32
+  ;;
   ppc)
     gdb_xml_files="power-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
     target_phys_bits=64
@@ -3697,7 +3703,7 @@  symlink "$source_path/Makefile.target" "$target_dir/Makefile"
 
 
 case "$target_arch2" in
-  alpha | sparc* | xtensa* | ppc*)
+  alpha | or32 | sparc* | xtensa* | ppc*)
     echo "CONFIG_TCG_PASS_AREG0=y" >> $config_target_mak
   ;;
 esac
@@ -3871,6 +3877,10 @@  for i in $ARCH $TARGET_BASE_ARCH ; do
     echo "CONFIG_MIPS_DIS=y"  >> $config_target_mak
     echo "CONFIG_MIPS_DIS=y"  >> $libdis_config_mak
   ;;
+  or32)
+    echo "CONFIG_OPENRISC_DIS=y"  >> $config_target_mak
+    echo "CONFIG_OPENRISC_DIS=y"  >> $libdis_config_mak
+  ;;
   ppc*)
     echo "CONFIG_PPC_DIS=y"  >> $config_target_mak
     echo "CONFIG_PPC_DIS=y"  >> $libdis_config_mak
diff --git a/cpu-exec.c b/cpu-exec.c
index 08c35f7..ce2d569 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -225,6 +225,7 @@  int cpu_exec(CPUArchState *env)
 #elif defined(TARGET_LM32)
 #elif defined(TARGET_MICROBLAZE)
 #elif defined(TARGET_MIPS)
+#elif defined(TARGET_OPENRISC)
 #elif defined(TARGET_SH4)
 #elif defined(TARGET_CRIS)
 #elif defined(TARGET_S390X)
@@ -634,6 +635,7 @@  int cpu_exec(CPUArchState *env)
               | env->cc_dest | (env->cc_x << 4);
 #elif defined(TARGET_MICROBLAZE)
 #elif defined(TARGET_MIPS)
+#elif defined(TARGET_OPENRISC)
 #elif defined(TARGET_SH4)
 #elif defined(TARGET_ALPHA)
 #elif defined(TARGET_CRIS)
diff --git a/default-configs/or32-softmmu.mak b/default-configs/or32-softmmu.mak
new file mode 100644
index 0000000..cce4746
--- /dev/null
+++ b/default-configs/or32-softmmu.mak
@@ -0,0 +1,4 @@ 
+# Default configuration for or32-softmmu
+
+CONFIG_SERIAL=y
+CONFIG_OPENCORES_ETH=y
diff --git a/elf.h b/elf.h
index 9c9acfa..a21ea53 100644
--- a/elf.h
+++ b/elf.h
@@ -106,6 +106,8 @@  typedef int64_t  Elf64_Sxword;
 #define EM_H8S          48      /* Hitachi H8S     */
 #define EM_LATTICEMICO32 138    /* LatticeMico32 */
 
+#define EM_OPENRISC     92        /* OpenCores OpenRISC */
+
 #define EM_UNICORE32    110     /* UniCore32 */
 
 /*
diff --git a/hw/openrisc/Makefile.objs b/hw/openrisc/Makefile.objs
new file mode 100644
index 0000000..bfead21
--- /dev/null
+++ b/hw/openrisc/Makefile.objs
@@ -0,0 +1 @@ 
+obj-y := $(addprefix ../,$(obj-y))
diff --git a/poison.h b/poison.h
index d396f20..7d7b23b 100644
--- a/poison.h
+++ b/poison.h
@@ -14,6 +14,7 @@ 
 #pragma GCC poison TARGET_M68K
 #pragma GCC poison TARGET_MIPS
 #pragma GCC poison TARGET_MIPS64
+#pragma GCC poison TARGET_OPENRISC
 #pragma GCC poison TARGET_PPC
 #pragma GCC poison TARGET_PPCEMB
 #pragma GCC poison TARGET_PPC64
diff --git a/target-openrisc/Makefile.objs b/target-openrisc/Makefile.objs
new file mode 100644
index 0000000..21b76b2
--- /dev/null
+++ b/target-openrisc/Makefile.objs
@@ -0,0 +1,3 @@ 
+obj-$(CONFIG_SOFTMMU) += machine.o
+obj-y += cpu.o intrpt.o mmu.o translate.o
+obj-y += mmu_helper.o
diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c
new file mode 100644
index 0000000..64ddc98
--- /dev/null
+++ b/target-openrisc/cpu.c
@@ -0,0 +1,236 @@ 
+/*
+ *  QEMU OpenRISC CPU
+ *
+ *  Copyright (c) 2012 Jia Liu <proljc@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#ifndef CONFIG_USER_ONLY
+#include "hw/loader.h"
+#endif
+
+/* CPUClass::reset() */
+static void openrisc_cpu_reset(CPUState *s)
+{
+    OpenRISCCPU *cpu = OPENRISC_CPU(s);
+    OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(cpu);
+
+    if (qemu_loglevel_mask(CPU_LOG_RESET)) {
+        qemu_log("CPU Reset (CPU %d)\n", cpu->env.cpu_index);
+        log_cpu_state(&cpu->env, 0);
+    }
+
+    occ->parent_reset(s);
+
+    memset(&cpu->env, 0, offsetof(CPUOpenRISCState, breakpoints));
+
+    tlb_flush(&cpu->env, 1);
+    /*tb_flush(&cpu->env);    FIXME: Do we need it?  */
+
+    cpu->env.pc = 0x100;
+    cpu->env.sr = SR_FO | SR_SM;
+    cpu->env.exception_index = -1;
+
+    cpu->env.upr = UPR_UP | UPR_DMP | UPR_IMP | UPR_PICP | UPR_TTP;
+    cpu->env.cpucfgr = CPUCFGR_OB32S | CPUCFGR_OF32S;
+    cpu->env.dmmucfgr = (DMMUCFGR_NTW & (0 << 2)) | (DMMUCFGR_NTS & (6 << 2));
+    cpu->env.immucfgr = (IMMUCFGR_NTW & (0 << 2)) | (IMMUCFGR_NTS & (6 << 2));
+
+#ifndef CONFIG_USER_ONLY
+    cpu->env.picmr = 0x00000000;
+    cpu->env.picsr = 0x00000000;
+
+    cpu->env.ttmr = 0x00000000;
+    cpu->env.ttcr = 0x00000000;
+#endif
+}
+
+static inline int openrisc_feature(OpenRISCCPU *cpu, int feature)
+{
+    return (cpu->env.feature & (1u << feature)) != 0;
+}
+
+static inline void set_feature(OpenRISCCPU *cpu, int feature)
+{
+    cpu->env.feature |= 1u << feature;
+}
+
+void openrisc_cpu_realize(Object *obj, Error **errp)
+{
+    OpenRISCCPU *cpu = OPENRISC_CPU(obj);
+    if (openrisc_feature(cpu, OPENRISC_FEATURE_OR1200)) {
+        set_feature(cpu, OPENRISC_FEATURE_OB32S);
+        set_feature(cpu, OPENRISC_FEATURE_OF32S);
+    }
+
+    qemu_init_vcpu(&cpu->env);
+}
+
+static void openrisc_cpu_initfn(Object *obj)
+{
+    OpenRISCCPU *cpu = OPENRISC_CPU(obj);
+    cpu_exec_init(&cpu->env);
+}
+
+/* CPU models */
+static void or1200_initfn(Object *obj)
+{
+    OpenRISCCPU *cpu = OPENRISC_CPU(obj);
+
+    set_feature(cpu, OPENRISC_FEATURE_OR1200);
+
+    cpu_reset(CPU(cpu));
+}
+
+static void openrisc_any_initfn(Object *obj)
+{
+    OpenRISCCPU *cpu = OPENRISC_CPU(obj);
+
+    set_feature(cpu, OPENRISC_FEATURE_OB32S);
+    set_feature(cpu, OPENRISC_FEATURE_OF32S);
+
+    cpu_reset(CPU(cpu));
+}
+
+typedef struct OpenRISCCPUInfo {
+    const char *name;
+    void (*initfn)(Object *obj);
+} OpenRISCCPUInfo;
+
+static const OpenRISCCPUInfo openrisc_cpus[] = {
+    { .name = "or1200",      .initfn = or1200_initfn },
+    { .name = "any",         .initfn = openrisc_any_initfn },
+};
+
+static void openrisc_cpu_class_init(ObjectClass *oc, void *data)
+{
+    OpenRISCCPUClass *occ = OPENRISC_CPU_CLASS(oc);
+    CPUClass *cc = CPU_CLASS(occ);
+
+    occ->parent_reset = cc->reset;
+    cc->reset = openrisc_cpu_reset;
+}
+
+static void cpu_register(const OpenRISCCPUInfo *info)
+{
+    TypeInfo type_info = {
+        .name = info->name,
+        .parent = TYPE_OPENRISC_CPU,
+        .instance_size = sizeof(OpenRISCCPU),
+        .instance_init = info->initfn,
+        .class_size = sizeof(OpenRISCCPUClass),
+    };
+
+    type_register_static(&type_info);
+}
+
+static const TypeInfo openrisc_cpu_type_info = {
+    .name = TYPE_OPENRISC_CPU,
+    .parent = TYPE_CPU,
+    .instance_size = sizeof(OpenRISCCPU),
+    .instance_init = openrisc_cpu_initfn,
+    .abstract = false,
+    .class_size = sizeof(OpenRISCCPUClass),
+    .class_init = openrisc_cpu_class_init,
+};
+
+static void openrisc_cpu_register_types(void)
+{
+    int i;
+
+    type_register_static(&openrisc_cpu_type_info);
+    for (i = 0; i < ARRAY_SIZE(openrisc_cpus); i++) {
+        cpu_register(&openrisc_cpus[i]);
+    }
+}
+
+OpenRISCCPU *cpu_openrisc_init(const char *cpu_model)
+{
+    OpenRISCCPU *cpu;
+    static int inited;
+    inited = 0;
+
+    if (!object_class_by_name(cpu_model)) {
+        return NULL;
+    }
+    cpu = OPENRISC_CPU(object_new(cpu_model));
+    cpu->env.cpu_model_str = cpu_model;
+
+    openrisc_cpu_realize(OBJECT(cpu), NULL);
+
+#ifndef CONFIG_USER_ONLY
+    cpu_openrisc_mmu_init(cpu);
+#endif
+
+    if (tcg_enabled() && !inited) {
+        inited = 1;
+        openrisc_translate_init();
+    }
+
+    cpu_reset(CPU(cpu));
+
+    return cpu;
+}
+
+typedef struct OpenRISCCPUList {
+    fprintf_function cpu_fprintf;
+    FILE *file;
+} OpenRISCCPUList;
+
+/* Sort alphabetically by type name, except for "any". */
+static gint openrisc_cpu_list_compare(gconstpointer a, gconstpointer b)
+{
+    ObjectClass *class_a = (ObjectClass *)a;
+    ObjectClass *class_b = (ObjectClass *)b;
+    const char *name_a, *name_b;
+
+    name_a = object_class_get_name(class_a);
+    name_b = object_class_get_name(class_b);
+    if (strcmp(name_a, "any") == 0) {
+        return 1;
+    } else if (strcmp(name_b, "any") == 0) {
+        return -1;
+    } else {
+        return strcmp(name_a, name_b);
+    }
+}
+
+static void openrisc_cpu_list_entry(gpointer data, gpointer user_data)
+{
+    ObjectClass *oc = data;
+    OpenRISCCPUList *s = user_data;
+
+    (*s->cpu_fprintf)(s->file, "  %s\n",
+                      object_class_get_name(oc));
+}
+
+void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf)
+{
+    OpenRISCCPUList s = {
+        .file = f,
+        .cpu_fprintf = cpu_fprintf,
+    };
+    GSList *list;
+
+    list = object_class_get_list(TYPE_OPENRISC_CPU, false);
+    list = g_slist_sort(list, openrisc_cpu_list_compare);
+    (*cpu_fprintf)(f, "Available CPUs:\n");
+    g_slist_foreach(list, openrisc_cpu_list_entry, &s);
+    g_slist_free(list);
+}
+
+type_init(openrisc_cpu_register_types)
diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h
new file mode 100644
index 0000000..728e4b3
--- /dev/null
+++ b/target-openrisc/cpu.h
@@ -0,0 +1,286 @@ 
+/*
+ *  OpenRISC virtual CPU header.
+ *
+ *  Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CPU_OPENRISC_H
+#define CPU_OPENRISC_H
+
+#if defined(TARGET_OPENRISC64)
+#define TARGET_LONG_BITS 64
+#define ELF_MACHINE    EM_NONE
+#else
+#define TARGET_LONG_BITS 32
+#define ELF_MACHINE    EM_OPENRISC
+#endif
+
+#define CPUArchState struct CPUOpenRISCState
+
+#include "config.h"
+#include "qemu-common.h"
+#include "cpu-defs.h"
+#include "softfloat.h"
+#include "qemu/cpu.h"
+#include "error.h"
+
+#define TYPE_OPENRISC_CPU "or32-cpu"
+
+#define OPENRISC_CPU_CLASS(klass) \
+    OBJECT_CLASS_CHECK(OpenRISCCPUClass, (klass), TYPE_OPENRISC_CPU)
+#define OPENRISC_CPU(obj) \
+    OBJECT_CHECK(OpenRISCCPU, (obj), TYPE_OPENRISC_CPU)
+#define OPENRISC_CPU_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(OpenRISCCPUClass, (obj), TYPE_OPENRISC_CPU)
+
+/**
+ * OpenRISCCPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * A OpenRISC CPU model.
+ */
+typedef struct OpenRISCCPUClass {
+    /*< private >*/
+    CPUClass parent_class;
+    /*< public >*/
+
+    void (*parent_reset)(CPUState *cpu);
+} OpenRISCCPUClass;
+
+#define NB_MMU_MODES    3
+
+#define TARGET_PAGE_BITS 13
+
+#define TARGET_PHYS_ADDR_SPACE_BITS 32
+#define TARGET_VIRT_ADDR_SPACE_BITS 32
+
+/* Internal flags, delay slot flag */
+#define D_FLAG    1
+
+/* Registers */
+enum {
+    R0 = 0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10,
+    R11, R12, R13, R14, R15, R16, R17, R18, R19, R20,
+    R21, R22, R23, R24, R25, R26, R27, R28, R29, R30,
+    R31
+};
+
+/* Register aliases */
+enum {
+    R_ZERO = R0,
+    R_SP = R1,
+    R_FP = R2,
+    R_LR = R9,
+    R_RV = R11,
+    R_RVH = R12
+};
+
+/* Unit presece register */
+enum {
+    UPR_UP = (1 << 0),
+    UPR_DCP = (1 << 1),
+    UPR_ICP = (1 << 2),
+    UPR_DMP = (1 << 3),
+    UPR_IMP = (1 << 4),
+    UPR_MP = (1 << 5),
+    UPR_DUP = (1 << 6),
+    UPR_PCUR = (1 << 7),
+    UPR_PMP = (1 << 8),
+    UPR_PICP = (1 << 9),
+    UPR_TTP = (1 << 10),
+    UPR_CUP = (255 << 24),
+};
+
+/* CPU configure register */
+enum {
+    CPUCFGR_NSGF = (15 << 0),
+    CPUCFGR_CGF = (1 << 4),
+    CPUCFGR_OB32S = (1 << 5),
+    CPUCFGR_OB64S = (1 << 6),
+    CPUCFGR_OF32S = (1 << 7),
+    CPUCFGR_OF64S = (1 << 8),
+    CPUCFGR_OV64S = (1 << 9),
+};
+
+/* DMMU configure register */
+enum {
+    DMMUCFGR_NTW = (3 << 0),
+    DMMUCFGR_NTS = (7 << 2),
+    DMMUCFGR_NAE = (7 << 5),
+    DMMUCFGR_CRI = (1 << 8),
+    DMMUCFGR_PRI = (1 << 9),
+    DMMUCFGR_TEIRI = (1 << 10),
+    DMMUCFGR_HTR = (1 << 11),
+};
+
+/* IMMU configure register */
+enum {
+    IMMUCFGR_NTW = (3 << 0),
+    IMMUCFGR_NTS = (7 << 2),
+    IMMUCFGR_NAE = (7 << 5),
+    IMMUCFGR_CRI = (1 << 8),
+    IMMUCFGR_PRI = (1 << 9),
+    IMMUCFGR_TEIRI = (1 << 10),
+    IMMUCFGR_HTR = (1 << 11),
+};
+
+/* Supervisor register */
+enum {
+    SR_SM = (1 << 0),
+    SR_TEE = (1 << 1),
+    SR_IEE = (1 << 2),
+    SR_DCE = (1 << 3),
+    SR_ICE = (1 << 4),
+    SR_DME = (1 << 5),
+    SR_IME = (1 << 6),
+    SR_LEE = (1 << 7),
+    SR_CE  = (1 << 8),
+    SR_F   = (1 << 9),
+    SR_CY  = (1 << 10),
+    SR_OV  = (1 << 11),
+    SR_OVE = (1 << 12),
+    SR_DSX = (1 << 13),
+    SR_EPH = (1 << 14),
+    SR_FO  = (1 << 15),
+    SR_SUMRA = (1 << 16),
+    SR_SCE = (1 << 17),
+};
+
+/* OpenRISC Hardware Capabilities */
+enum {
+    OPENRISC_FEATURE_NSGF,
+    OPENRISC_FEATURE_CGF,
+    OPENRISC_FEATURE_OB32S,
+    OPENRISC_FEATURE_OB64S,
+    OPENRISC_FEATURE_OF32S,
+    OPENRISC_FEATURE_OF64S,
+    OPENRISC_FEATURE_OV64S,
+    OPENRISC_FEATURE_OR1200,
+};
+
+typedef struct CPUOpenRISCState {
+    target_ulong gpr[32];     /* General registers */
+    target_ulong pc;          /* Program counter */
+    target_ulong npc;         /* Next PC */
+    target_ulong ppc;         /* Prev PC */
+    target_ulong jmp_pc;      /* Jump PC */
+
+    uint32_t sr;              /* Supervisor register */
+    uint32_t vr;              /* Version register */
+    uint32_t upr;             /* Unit presence register */
+    uint32_t cpucfgr;         /* CPU configure register */
+    uint32_t dmmucfgr;        /* DMMU configure register */
+    uint32_t immucfgr;        /* IMMU configure register */
+
+    uint32_t flags;           /* cpu_flags, we only use it for exception
+                                 in solt so far.  */
+    uint32_t btaken;          /* the SR_F bit */
+
+    CPU_COMMON
+
+#ifndef CONFIG_USER_ONLY
+    struct QEMUTimer *timer;
+    uint32_t ttmr;          /* Timer tick mode register */
+    uint32_t ttcr;          /* Timer tick count register */
+
+    uint32_t picmr;         /* Interrupt mask register */
+    uint32_t picsr;         /* Interrupt contrl register*/
+#endif
+    uint32_t feature;       /* CPU Capabilities */
+} CPUOpenRISCState;
+
+/**
+ * OpenRISCCPU:
+ * @env: #CPUOpenRISCState
+ *
+ * A OpenRISC CPU.
+ */
+typedef struct OpenRISCCPU {
+    /*< private >*/
+    CPUState parent_obj;
+    /*< public >*/
+
+    CPUOpenRISCState env;
+} OpenRISCCPU;
+
+static inline OpenRISCCPU *openrisc_env_get_cpu(CPUOpenRISCState *env)
+{
+    return OPENRISC_CPU(container_of(env, OpenRISCCPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(openrisc_env_get_cpu(e))
+
+OpenRISCCPU *cpu_openrisc_init(const char *cpu_model);
+void openrisc_cpu_realize(Object *obj, Error **errp);
+
+void cpu_openrisc_list(FILE *f, fprintf_function cpu_fprintf);
+int cpu_openrisc_exec(CPUOpenRISCState *s);
+void do_interrupt(CPUOpenRISCState *env);
+void openrisc_translate_init(void);
+
+#define cpu_list cpu_openrisc_list
+#define cpu_exec cpu_openrisc_exec
+#define cpu_gen_code cpu_openrisc_gen_code
+
+#define CPU_SAVE_VERSION 1
+
+#ifndef CONFIG_USER_ONLY
+void cpu_openrisc_mmu_init(OpenRISCCPU *cpu);
+#endif
+
+static inline CPUOpenRISCState *cpu_init(const char *cpu_model)
+{
+    OpenRISCCPU *cpu = cpu_openrisc_init(cpu_model);
+    if (cpu) {
+        return &cpu->env;
+    }
+    return NULL;
+}
+
+#include "cpu-all.h"
+
+static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env,
+                                        target_ulong *pc,
+                                        target_ulong *cs_base, int *flags)
+{
+    *pc = env->pc;
+    *cs_base = 0;
+    *flags = 0;
+}
+
+static inline int cpu_mmu_index(CPUOpenRISCState *env)
+{
+    return 0;
+}
+
+static inline bool cpu_has_work(CPUOpenRISCState *env)
+{
+    return true;
+}
+
+#include "exec-all.h"
+
+static inline target_ulong cpu_get_pc(CPUOpenRISCState *env)
+{
+    return env->pc;
+}
+
+static inline void cpu_pc_from_tb(CPUOpenRISCState *env, TranslationBlock *tb)
+{
+    env->pc = tb->pc;
+}
+
+#endif /* CPU_OPENRISC_H */
diff --git a/target-openrisc/intrpt.c b/target-openrisc/intrpt.c
new file mode 100644
index 0000000..a3bb7f8
--- /dev/null
+++ b/target-openrisc/intrpt.c
@@ -0,0 +1,30 @@ 
+/*
+ *  OpenRISC interrupt.
+ *
+ *  Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#include "gdbstub.h"
+#include "host-utils.h"
+#ifndef CONFIG_USER_ONLY
+#include "hw/loader.h"
+#endif
+
+void do_interrupt(CPUOpenRISCState *env)
+{
+}
diff --git a/target-openrisc/machine.c b/target-openrisc/machine.c
new file mode 100644
index 0000000..11bf275
--- /dev/null
+++ b/target-openrisc/machine.c
@@ -0,0 +1,30 @@ 
+/*
+ *  OpenRISC Machine
+ *
+ *  Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw/hw.h"
+#include "hw/boards.h"
+
+void cpu_save(QEMUFile *f, void *opaque)
+{
+}
+
+int cpu_load(QEMUFile *f, void *opaque, int version_id)
+{
+    return 0;
+}
diff --git a/target-openrisc/mmu.c b/target-openrisc/mmu.c
new file mode 100644
index 0000000..3403def
--- /dev/null
+++ b/target-openrisc/mmu.c
@@ -0,0 +1,39 @@ 
+/*
+ *  OpenRISC MMU.
+ *
+ *  Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ *                          Zhizhou Zhang <etouzh@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "qemu-common.h"
+#include "gdbstub.h"
+#include "host-utils.h"
+#ifndef CONFIG_USER_ONLY
+#include "hw/loader.h"
+#endif
+
+#ifndef CONFIG_USER_ONLY
+target_phys_addr_t cpu_get_phys_page_debug(CPUOpenRISCState *env,
+                                           target_ulong addr)
+{
+    return addr;
+}
+
+void cpu_openrisc_mmu_init(OpenRISCCPU *cpu)
+{
+}
+#endif
diff --git a/target-openrisc/mmu_helper.c b/target-openrisc/mmu_helper.c
new file mode 100644
index 0000000..f526ba8
--- /dev/null
+++ b/target-openrisc/mmu_helper.c
@@ -0,0 +1,43 @@ 
+/*
+ *  OpenRISC MMU helper routines
+ *
+ *  Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ *                          Zhizhou Zhang <etouzh@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+
+#ifndef CONFIG_USER_ONLY
+#include "softmmu_exec.h"
+#define MMUSUFFIX _mmu
+
+#define SHIFT 0
+#include "softmmu_template.h"
+
+#define SHIFT 1
+#include "softmmu_template.h"
+
+#define SHIFT 2
+#include "softmmu_template.h"
+
+#define SHIFT 3
+#include "softmmu_template.h"
+
+void tlb_fill(CPUOpenRISCState *env, target_ulong addr, int is_write,
+              int mmu_idx, uintptr_t retaddr)
+{
+}
+#endif
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
new file mode 100644
index 0000000..4d4aa23
--- /dev/null
+++ b/target-openrisc/translate.c
@@ -0,0 +1,75 @@ 
+/*
+ *  OpenRISC translation
+ *
+ *  Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com>
+ *                          Feng Gao <gf91597@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cpu.h"
+#include "exec-all.h"
+#include "disas.h"
+#include "tcg-op.h"
+#include "qemu-common.h"
+#include "qemu-log.h"
+#include "config.h"
+
+#define OPENRISC_DISAS
+
+#ifdef OPENRISC_DISAS
+#  define LOG_DIS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
+#else
+#  define LOG_DIS(...) do { } while (0)
+#endif
+
+void openrisc_translate_init(void)
+{
+}
+
+static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu,
+                                                  TranslationBlock *tb,
+                                                  int search_pc)
+{
+}
+
+void gen_intermediate_code(CPUOpenRISCState *env, struct TranslationBlock *tb)
+{
+    gen_intermediate_code_internal(openrisc_env_get_cpu(env), tb, 0);
+}
+
+void gen_intermediate_code_pc(CPUOpenRISCState *env,
+                              struct TranslationBlock *tb)
+{
+    gen_intermediate_code_internal(openrisc_env_get_cpu(env), tb, 1);
+}
+
+void cpu_dump_state(CPUOpenRISCState *env, FILE *f,
+                    fprintf_function cpu_fprintf,
+                    int flags)
+{
+    int i;
+    uint32_t *regs = env->gpr;
+    cpu_fprintf(f, "PC=%08x\n", env->pc);
+    for (i = 0; i < 32; ++i) {
+        cpu_fprintf(f, "R%02d=%08x%c", i, regs[i],
+                    (i % 4) == 3 ? '\n' : ' ');
+    }
+}
+
+void restore_state_to_opc(CPUOpenRISCState *env, TranslationBlock *tb,
+                          int pc_pos)
+{
+    env->pc = gen_opc_pc[pc_pos];
+}