diff mbox

[v7,11/16] target-or32: Add a IIS dummy board

Message ID 1340790854-15580-12-git-send-email-proljc@gmail.com
State New
Headers show

Commit Message

Jia Liu June 27, 2012, 9:54 a.m. UTC
Add a IIS dummy board.

Signed-off-by: Jia Liu <proljc@gmail.com>
---
 hw/openrisc/Makefile.objs |    2 +-
 hw/openrisc_sim.c         |  149 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 150 insertions(+), 1 deletion(-)
 create mode 100644 hw/openrisc_sim.c

Comments

Peter A. G. Crosthwaite June 27, 2012, 12:25 p.m. UTC | #1
Hi Jia,

On Wed, Jun 27, 2012 at 7:54 PM, Jia Liu <proljc@gmail.com> wrote:
> Add a IIS dummy board.
>
> Signed-off-by: Jia Liu <proljc@gmail.com>
> ---
>  hw/openrisc/Makefile.objs |    2 +-
>  hw/openrisc_sim.c         |  149 +++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 150 insertions(+), 1 deletion(-)
>  create mode 100644 hw/openrisc_sim.c
>
> diff --git a/hw/openrisc/Makefile.objs b/hw/openrisc/Makefile.objs
> index 1c541a5..38ff8f5 100644
> --- a/hw/openrisc/Makefile.objs
> +++ b/hw/openrisc/Makefile.objs
> @@ -1,3 +1,3 @@
> -obj-y = openrisc_pic.o openrisc_timer.o
> +obj-y = openrisc_pic.o openrisc_sim.o openrisc_timer.o
>
>  obj-y := $(addprefix ../,$(obj-y))
> diff --git a/hw/openrisc_sim.c b/hw/openrisc_sim.c
> new file mode 100644
> index 0000000..b0c1e69
> --- /dev/null
> +++ b/hw/openrisc_sim.c
> @@ -0,0 +1,149 @@
> +/*
> + *  OpenRISC simulator for use as an IIS.
> + *
> + *  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 "hw.h"
> +#include "openrisc_cpudev.h"
> +#include "boards.h"
> +#include "elf.h"
> +#include "pc.h"
> +#include "loader.h"
> +#include "exec-memory.h"
> +#include "sysemu.h"
> +#include "sysbus.h"
> +#include "qtest.h"
> +
> +#define KERNEL_LOAD_ADDR 0x100
> +

Unused definition.

> +static struct _loaderparams {
> +    uint64_t ram_size;
> +    const char *kernel_filename;
> +    const char *kernel_cmdline;
> +    const char *initrd_filename;

ram_size, kernel_cmdline and initrd_filename are all unused AFAICT?
Can you simplify your bootloader by passing just the filename and none
of this Linux specific stuff?

> +} loaderparams;
> +
> +static void main_cpu_reset(void *opaque)
> +{
> +    CPUOpenRISCState *env = opaque;
> +    cpu_reset(ENV_GET_CPU(env));
> +}
> +
> +static void openrisc_sim_net_init(MemoryRegion *address_space,
> +                                  target_phys_addr_t base,
> +                                  target_phys_addr_t descriptors,
> +                                  qemu_irq irq, NICInfo *nd)
> +{
> +    DeviceState *dev;
> +    SysBusDevice *s;
> +
> +    dev = qdev_create(NULL, "open_eth");
> +    qdev_set_nic_properties(dev, nd);
> +    qdev_init_nofail(dev);
> +
> +    s = sysbus_from_qdev(dev);
> +    sysbus_connect_irq(s, 0, irq);
> +    memory_region_add_subregion(address_space, base,
> +                                sysbus_mmio_get_region(s, 0));
> +    memory_region_add_subregion(address_space, descriptors,
> +                                sysbus_mmio_get_region(s, 1));
> +}
> +
> +static uint64_t openrisc_load_kernel(void)
> +{

cc Peter Maydell Re the bootloader discussion. - This is yet another
bootloader. This one is just load elf else load uimage else load
raw-image. No append, initrd, dtb etc. Not a blocker at this stage but
looking ahead this will fall under the umbrella of the bootloader
unifications we need to discuss.

> +    long kernel_size;
> +    uint64_t elf_entry;
> +    target_phys_addr_t entry;
> +
> +    if (loaderparams.kernel_filename && !qtest_enabled()) {
> +        kernel_size = load_uimage(loaderparams.kernel_filename,
> +                                  &entry, NULL, NULL);
> +        if (kernel_size < 0) {
> +            kernel_size = load_elf(loaderparams.kernel_filename, NULL, NULL,
> +                                   &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1);
> +            entry = elf_entry;
> +        }
> +
> +        if (kernel_size < 0) {
> +            fprintf(stderr, "QEMU: couldn't load the kernel '%s'\n",
> +                    loaderparams.kernel_filename);
> +            exit(1);
> +        }
> +    }
> +
> +    return entry;
> +}
> +
> +static void openrisc_sim_init(ram_addr_t ram_size,
> +                              const char *boot_device,
> +                              const char *kernel_filename,
> +                              const char *kernel_cmdline,
> +                              const char *initrd_filename,
> +                              const char *cpu_model)
> +{
> +    CPUOpenRISCState *env;
> +    MemoryRegion *ram = g_new(MemoryRegion, 1);
> +
> +    if (!cpu_model) {
> +        cpu_model = "or1200";
> +    }
> +    env = cpu_init(cpu_model);
> +    if (!env) {
> +        fprintf(stderr, "Unable to find CPU definition!\n");
> +        exit(1);
> +    }
> +
> +    qemu_register_reset(main_cpu_reset, env);
> +    main_cpu_reset(env);
> +

I think this needs rebasing. Andreas a while back abstracted back to
the CPU level instead for resets. Andreas can you confirm? should this
be changed to pass the CPU QOM object to the reset instead? cc
andreas.

> +    memory_region_init_ram(ram, "openrisc.ram", ram_size);
> +    memory_region_add_subregion(get_system_memory(), 0, ram);
> +
> +    if (kernel_filename) {
> +        loaderparams.ram_size = ram_size;
> +        loaderparams.kernel_filename = kernel_filename;
> +        loaderparams.kernel_cmdline = kernel_cmdline;
> +        env->pc = openrisc_load_kernel();
> +    }

Its probably more usual and safer to bootload last. You are still
creating your machine after this. Can you move this hunk to be the
last thing in the function?

Regards,
Peter
> +
> +    cpu_openrisc_pic_init(env);
> +    cpu_openrisc_clock_init(env);
> +
> +    serial_mm_init(get_system_memory(), 0x90000000, 0,
> +                   env->irq[2], 115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
> +
> +    if (nd_table[0].vlan) {
> +        openrisc_sim_net_init(get_system_memory(), 0x92000000,
> +                              0x92000400, env->irq[4], nd_table);
> +    }
> +}
> +
> +static QEMUMachine openrisc_sim_machine = {
> +    .name = "or32-sim",
> +    .desc = "or32 simulation",
> +    .init = openrisc_sim_init,
> +    .max_cpus = 1,
> +    .is_default = 1,
> +};
> +
> +static void openrisc_sim_machine_init(void)
> +{
> +    qemu_register_machine(&openrisc_sim_machine);
> +}
> +
> +machine_init(openrisc_sim_machine_init);
> --
> 1.7.9.5
>
>
Andreas Färber June 27, 2012, 1:04 p.m. UTC | #2
Am 27.06.2012 14:25, schrieb Peter Crosthwaite:
> Hi Jia,
> 
> On Wed, Jun 27, 2012 at 7:54 PM, Jia Liu <proljc@gmail.com> wrote:
>> +static void openrisc_sim_init(ram_addr_t ram_size,
>> +                              const char *boot_device,
>> +                              const char *kernel_filename,
>> +                              const char *kernel_cmdline,
>> +                              const char *initrd_filename,
>> +                              const char *cpu_model)
>> +{
>> +    CPUOpenRISCState *env;
>> +    MemoryRegion *ram = g_new(MemoryRegion, 1);
>> +
>> +    if (!cpu_model) {
>> +        cpu_model = "or1200";
>> +    }
>> +    env = cpu_init(cpu_model);
>> +    if (!env) {
>> +        fprintf(stderr, "Unable to find CPU definition!\n");
>> +        exit(1);
>> +    }
>> +
>> +    qemu_register_reset(main_cpu_reset, env);
>> +    main_cpu_reset(env);
>> +
> 
> I think this needs rebasing. Andreas a while back abstracted back to
> the CPU level instead for resets. Andreas can you confirm? should this
> be changed to pass the CPU QOM object to the reset instead? cc
> andreas.

Thought I had commented that already... maybe I'm starting to confuse
uc32 and or32? :) Yes please, cpu_or32_init() should be called and
return an OpenRISCCPU *cpu. main_cpu_reset() should be passed the cpu,
too. All new APIs (static helpers etc.) should use OpenRISCCPU, not
CPUOpenRISCState. That will greatly simplify moving forward.

Thanks for catching this, Peter.

Andreas
Peter A. G. Crosthwaite June 27, 2012, 1:10 p.m. UTC | #3
On Wed, Jun 27, 2012 at 11:04 PM, Andreas Färber <afaerber@suse.de> wrote:
> Am 27.06.2012 14:25, schrieb Peter Crosthwaite:
>> Hi Jia,
>>
>> On Wed, Jun 27, 2012 at 7:54 PM, Jia Liu <proljc@gmail.com> wrote:
>>> +static void openrisc_sim_init(ram_addr_t ram_size,
>>> +                              const char *boot_device,
>>> +                              const char *kernel_filename,
>>> +                              const char *kernel_cmdline,
>>> +                              const char *initrd_filename,
>>> +                              const char *cpu_model)
>>> +{
>>> +    CPUOpenRISCState *env;
>>> +    MemoryRegion *ram = g_new(MemoryRegion, 1);
>>> +
>>> +    if (!cpu_model) {
>>> +        cpu_model = "or1200";
>>> +    }
>>> +    env = cpu_init(cpu_model);
>>> +    if (!env) {
>>> +        fprintf(stderr, "Unable to find CPU definition!\n");
>>> +        exit(1);
>>> +    }
>>> +
>>> +    qemu_register_reset(main_cpu_reset, env);
>>> +    main_cpu_reset(env);
>>> +
>>
>> I think this needs rebasing. Andreas a while back abstracted back to
>> the CPU level instead for resets. Andreas can you confirm? should this
>> be changed to pass the CPU QOM object to the reset instead? cc
>> andreas.
>
> Thought I had commented that already... maybe I'm starting to confuse
> uc32 and or32? :) Yes please, cpu_or32_init() should be called and
> return an OpenRISCCPU *cpu. main_cpu_reset() should be passed the cpu,
> too. All new APIs (static helpers etc.) should use OpenRISCCPU, not
> CPUOpenRISCState.

That rule has significant impact on patches 9-10. Andreas, you may
wish to check these out - they are psuedo device-models tightly
coupled to the cpu env.

Regards,
Peter

That will greatly simplify moving forward.
>
> Thanks for catching this, Peter.
>
> Andreas
>
> --
> SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
> GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
Jia Liu June 28, 2012, 1:56 p.m. UTC | #4
Hi, Peter, Andreas, and Peter,

I've replace env with cpu, and rewrite the load_kernel.
Please review these new files:

openrisc_pic.c

#include "hw.h"
#include "cpu.h"

/* OpenRISC pic handler */
static void openrisc_pic_cpu_handler(void *opaque, int irq, int level)
{
    OpenRISCCPU *cpu = (OpenRISCCPU *)opaque;
    int i;
    uint32_t irq_bit = 1 << irq;

    if (irq > 31 || irq < 0) {
        return;
    }

    if (level) {
        cpu->env.picsr |= irq_bit;
    } else {
        cpu->env.picsr &= ~irq_bit;
    }

    for (i = 0; i < 32; i++) {
        if ((cpu->env.picsr && (1 << i)) && (cpu->env.picmr && (1 << i))) {
            cpu_interrupt(&cpu->env, CPU_INTERRUPT_HARD);
        } else {
            cpu_reset_interrupt(&cpu->env, CPU_INTERRUPT_HARD);
            cpu->env.picsr &= ~(1 << i);
        }
    }
}

void cpu_openrisc_pic_init(OpenRISCCPU *cpu)
{
    int i;
    qemu_irq *qi;
    qi = qemu_allocate_irqs(openrisc_pic_cpu_handler, cpu, NR_IRQS);

    for (i = 0; i < NR_IRQS; i++) {
        cpu->env.irq[i] = qi[i];
    }
}
--------------------------------------------------------------------

openrisc_timer.c

#include "cpu.h"
#include "hw.h"
#include "qemu-timer.h"

#define TIMER_FREQ    (20 * 1000 * 1000)    /* 20MHz */

/* The time when TTCR changes */
static uint64_t last_clk;
static int is_counting;

void cpu_openrisc_count_update(OpenRISCCPU *cpu)
{
    uint64_t now, next;
    uint32_t wait;

    now = qemu_get_clock_ns(vm_clock);
    if (!is_counting) {
        qemu_del_timer(cpu->env.timer);
        last_clk = now;
        return;
    }

    cpu->env.ttcr += (uint32_t)muldiv64(now - last_clk, TIMER_FREQ,
                                        get_ticks_per_sec());
    last_clk = now;

    if ((cpu->env.ttmr & TTMR_TP) <= (cpu->env.ttcr & TTMR_TP)) {
        wait = TTMR_TP - (cpu->env.ttcr & TTMR_TP) + 1;
        wait += cpu->env.ttmr & TTMR_TP;
    } else {
        wait = (cpu->env.ttmr & TTMR_TP) - (cpu->env.ttcr & TTMR_TP);
    }

    next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ);
    qemu_mod_timer(cpu->env.timer, next);
}

void cpu_openrisc_count_start(OpenRISCCPU *cpu)
{
    is_counting = 1;
    cpu_openrisc_count_update(cpu);
}

void cpu_openrisc_count_stop(OpenRISCCPU *cpu)
{
    is_counting = 0;
    cpu_openrisc_count_update(cpu);
}

static void openrisc_timer_cb(void *opaque)
{
    OpenRISCCPU *cpu = opaque;

    if ((cpu->env.ttmr & TTMR_IE) &&
         qemu_timer_expired(cpu->env.timer, qemu_get_clock_ns(vm_clock))) {
        cpu->env.ttmr |= TTMR_IP;
        cpu->env.interrupt_request |= CPU_INTERRUPT_TIMER;
    }

    switch (cpu->env.ttmr & TTMR_M) {
    case TIMER_NONE:
        break;
    case TIMER_INTR:
        cpu->env.ttcr = 0;
        cpu_openrisc_count_start(cpu);
        break;
    case TIMER_SHOT:
        cpu_openrisc_count_stop(cpu);
        break;
    case TIMER_CONT:
        cpu_openrisc_count_start(cpu);
        break;
    }
}

void cpu_openrisc_clock_init(OpenRISCCPU *cpu)
{
    cpu->env.timer = qemu_new_timer_ns(vm_clock, &openrisc_timer_cb, cpu);
    cpu->env.ttmr = 0x00000000;
    cpu->env.ttcr = 0x00000000;
}
--------------------------------------------------------------------

openrisc_sim.c

#include "hw.h"
#include "boards.h"
#include "elf.h"
#include "pc.h"
#include "loader.h"
#include "exec-memory.h"
#include "sysemu.h"
#include "sysbus.h"
#include "qtest.h"

#define KERNEL_LOAD_ADDR 0x100

static void main_cpu_reset(void *opaque)
{
    OpenRISCCPU *cpu = opaque;

    cpu_reset(CPU(cpu));
}

static void openrisc_sim_net_init(MemoryRegion *address_space,
                                  target_phys_addr_t base,
                                  target_phys_addr_t descriptors,
                                  qemu_irq irq, NICInfo *nd)
{
    DeviceState *dev;
    SysBusDevice *s;

    dev = qdev_create(NULL, "open_eth");
    qdev_set_nic_properties(dev, nd);
    qdev_init_nofail(dev);

    s = sysbus_from_qdev(dev);
    sysbus_connect_irq(s, 0, irq);
    memory_region_add_subregion(address_space, base,
                                sysbus_mmio_get_region(s, 0));
    memory_region_add_subregion(address_space, descriptors,
                                sysbus_mmio_get_region(s, 1));
}

static void openrisc_sim_init(ram_addr_t ram_size,
                              const char *boot_device,
                              const char *kernel_filename,
                              const char *kernel_cmdline,
                              const char *initrd_filename,
                              const char *cpu_model)
{
    long kernel_size;
    uint64_t elf_entry;
    target_phys_addr_t entry;
    OpenRISCCPU *cpu = NULL;
    MemoryRegion *ram;
    int n;

    if (!cpu_model) {
        cpu_model = "or1200";
    }

    for (n = 0; n < smp_cpus; n++) {
        cpu = cpu_openrisc_init(cpu_model);
        if (cpu == NULL) {
            qemu_log("Unable to find CPU defineition!\n");
            exit(1);
        }
        qemu_register_reset(main_cpu_reset, cpu);
        main_cpu_reset(cpu);
    }

    ram = g_malloc(sizeof(*ram));
    memory_region_init_ram(ram, "openrisc.ram", ram_size);
    vmstate_register_ram_global(ram);
    memory_region_add_subregion(get_system_memory(), 0, ram);

    /* load kernel */
    if (kernel_filename && !qtest_enabled()) {
        kernel_size = load_elf(kernel_filename, NULL, NULL,
                               &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1);
        entry = elf_entry;
        if (kernel_size < 0) {
            kernel_size = load_uimage(kernel_filename,
                                      &entry, NULL, NULL);
        }
        if (kernel_size < 0) {
            kernel_size = load_image_targphys(kernel_filename,
                                              KERNEL_LOAD_ADDR,
                                              ram_size - KERNEL_LOAD_ADDR);
            entry = KERNEL_LOAD_ADDR;
        }

        if (kernel_size < 0) {
            qemu_log("QEMU: couldn't load the kernel '%s'\n",
                    kernel_filename);
            exit(1);
        }
    }

    cpu_openrisc_pic_init(cpu);
    cpu_openrisc_clock_init(cpu);

    serial_mm_init(get_system_memory(), 0x90000000, 0, cpu->env.irq[2],
                   115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);

    if (nd_table[0].vlan) {
        openrisc_sim_net_init(get_system_memory(), 0x92000000,
                              0x92000400, cpu->env.irq[4], nd_table);
    }

    cpu->env.pc = entry;
}

static QEMUMachine openrisc_sim_machine = {
    .name = "or32-sim",
    .desc = "or32 simulation",
    .init = openrisc_sim_init,
    .max_cpus = 1,
    .is_default = 1,
};

static void openrisc_sim_machine_init(void)
{
    qemu_register_machine(&openrisc_sim_machine);
}

machine_init(openrisc_sim_machine_init);


Please review and let me the new is OK or not, please.
Thank you, very much, all of you.


On Wed, Jun 27, 2012 at 9:10 PM, Peter Crosthwaite
<peter.crosthwaite@petalogix.com> wrote:
> On Wed, Jun 27, 2012 at 11:04 PM, Andreas Färber <afaerber@suse.de> wrote:
>> Am 27.06.2012 14:25, schrieb Peter Crosthwaite:
>>> Hi Jia,
>>>
>>> On Wed, Jun 27, 2012 at 7:54 PM, Jia Liu <proljc@gmail.com> wrote:
>>>> +static void openrisc_sim_init(ram_addr_t ram_size,
>>>> +                              const char *boot_device,
>>>> +                              const char *kernel_filename,
>>>> +                              const char *kernel_cmdline,
>>>> +                              const char *initrd_filename,
>>>> +                              const char *cpu_model)
>>>> +{
>>>> +    CPUOpenRISCState *env;
>>>> +    MemoryRegion *ram = g_new(MemoryRegion, 1);
>>>> +
>>>> +    if (!cpu_model) {
>>>> +        cpu_model = "or1200";
>>>> +    }
>>>> +    env = cpu_init(cpu_model);
>>>> +    if (!env) {
>>>> +        fprintf(stderr, "Unable to find CPU definition!\n");
>>>> +        exit(1);
>>>> +    }
>>>> +
>>>> +    qemu_register_reset(main_cpu_reset, env);
>>>> +    main_cpu_reset(env);
>>>> +
>>>
>>> I think this needs rebasing. Andreas a while back abstracted back to
>>> the CPU level instead for resets. Andreas can you confirm? should this
>>> be changed to pass the CPU QOM object to the reset instead? cc
>>> andreas.
>>
>> Thought I had commented that already... maybe I'm starting to confuse
>> uc32 and or32? :) Yes please, cpu_or32_init() should be called and
>> return an OpenRISCCPU *cpu. main_cpu_reset() should be passed the cpu,
>> too. All new APIs (static helpers etc.) should use OpenRISCCPU, not
>> CPUOpenRISCState.
>
> That rule has significant impact on patches 9-10. Andreas, you may
> wish to check these out - they are psuedo device-models tightly
> coupled to the cpu env.
>
> Regards,
> Peter
>
> That will greatly simplify moving forward.
>>
>> Thanks for catching this, Peter.
>>
>> 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.
陳韋任 June 29, 2012, 3:03 a.m. UTC | #5
> /* OpenRISC pic handler */
> static void openrisc_pic_cpu_handler(void *opaque, int irq, int level)
> {
>     OpenRISCCPU *cpu = (OpenRISCCPU *)opaque;
                         ^^^^^^^^^^^^^^
  Do we need casting before assigning opaque to cpu?

Regards,
chenwj
Peter A. G. Crosthwaite June 29, 2012, 3:15 a.m. UTC | #6
On Thu, Jun 28, 2012 at 11:56 PM, Jia Liu <proljc@gmail.com> wrote:
> Hi, Peter, Andreas, and Peter,
>
> I've replace env with cpu, and rewrite the load_kernel.
> Please review these new files:
>
> openrisc_pic.c
>
> #include "hw.h"
> #include "cpu.h"
>
> /* OpenRISC pic handler */
> static void openrisc_pic_cpu_handler(void *opaque, int irq, int level)
> {
>    OpenRISCCPU *cpu = (OpenRISCCPU *)opaque;
>    int i;
>    uint32_t irq_bit = 1 << irq;
>
>    if (irq > 31 || irq < 0) {
>        return;
>    }
>
>    if (level) {
>        cpu->env.picsr |= irq_bit;
>    } else {
>        cpu->env.picsr &= ~irq_bit;
>    }
>
>    for (i = 0; i < 32; i++) {
>        if ((cpu->env.picsr && (1 << i)) && (cpu->env.picmr && (1 << i))) {
>            cpu_interrupt(&cpu->env, CPU_INTERRUPT_HARD);
>        } else {
>            cpu_reset_interrupt(&cpu->env, CPU_INTERRUPT_HARD);
>            cpu->env.picsr &= ~(1 << i);
>        }
>    }
> }
>
> void cpu_openrisc_pic_init(OpenRISCCPU *cpu)
> {
>    int i;
>    qemu_irq *qi;
>    qi = qemu_allocate_irqs(openrisc_pic_cpu_handler, cpu, NR_IRQS);
>
>    for (i = 0; i < NR_IRQS; i++) {
>        cpu->env.irq[i] = qi[i];
>    }
> }
> --------------------------------------------------------------------
>
> openrisc_timer.c
>
> #include "cpu.h"
> #include "hw.h"
> #include "qemu-timer.h"
>
> #define TIMER_FREQ    (20 * 1000 * 1000)    /* 20MHz */
>
> /* The time when TTCR changes */
> static uint64_t last_clk;
> static int is_counting;
>
> void cpu_openrisc_count_update(OpenRISCCPU *cpu)
> {
>    uint64_t now, next;
>    uint32_t wait;
>
>    now = qemu_get_clock_ns(vm_clock);
>    if (!is_counting) {
>        qemu_del_timer(cpu->env.timer);
>        last_clk = now;
>        return;
>    }
>
>    cpu->env.ttcr += (uint32_t)muldiv64(now - last_clk, TIMER_FREQ,
>                                        get_ticks_per_sec());
>    last_clk = now;
>
>    if ((cpu->env.ttmr & TTMR_TP) <= (cpu->env.ttcr & TTMR_TP)) {
>        wait = TTMR_TP - (cpu->env.ttcr & TTMR_TP) + 1;
>        wait += cpu->env.ttmr & TTMR_TP;
>    } else {
>        wait = (cpu->env.ttmr & TTMR_TP) - (cpu->env.ttcr & TTMR_TP);
>    }
>
>    next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ);
>    qemu_mod_timer(cpu->env.timer, next);
> }
>
> void cpu_openrisc_count_start(OpenRISCCPU *cpu)
> {
>    is_counting = 1;
>    cpu_openrisc_count_update(cpu);
> }
>
> void cpu_openrisc_count_stop(OpenRISCCPU *cpu)
> {
>    is_counting = 0;
>    cpu_openrisc_count_update(cpu);
> }
>
> static void openrisc_timer_cb(void *opaque)
> {
>    OpenRISCCPU *cpu = opaque;
>
>    if ((cpu->env.ttmr & TTMR_IE) &&
>         qemu_timer_expired(cpu->env.timer, qemu_get_clock_ns(vm_clock))) {
>        cpu->env.ttmr |= TTMR_IP;
>        cpu->env.interrupt_request |= CPU_INTERRUPT_TIMER;
>    }
>
>    switch (cpu->env.ttmr & TTMR_M) {
>    case TIMER_NONE:
>        break;
>    case TIMER_INTR:
>        cpu->env.ttcr = 0;
>        cpu_openrisc_count_start(cpu);
>        break;
>    case TIMER_SHOT:
>        cpu_openrisc_count_stop(cpu);
>        break;
>    case TIMER_CONT:
>        cpu_openrisc_count_start(cpu);
>        break;
>    }
> }
>
> void cpu_openrisc_clock_init(OpenRISCCPU *cpu)
> {
>    cpu->env.timer = qemu_new_timer_ns(vm_clock, &openrisc_timer_cb, cpu);
>    cpu->env.ttmr = 0x00000000;
>    cpu->env.ttcr = 0x00000000;
> }
> --------------------------------------------------------------------
>
> openrisc_sim.c
>
> #include "hw.h"
> #include "boards.h"
> #include "elf.h"
> #include "pc.h"
> #include "loader.h"
> #include "exec-memory.h"
> #include "sysemu.h"
> #include "sysbus.h"
> #include "qtest.h"
>
> #define KERNEL_LOAD_ADDR 0x100
>
> static void main_cpu_reset(void *opaque)
> {
>    OpenRISCCPU *cpu = opaque;
>
>    cpu_reset(CPU(cpu));
> }
>
> static void openrisc_sim_net_init(MemoryRegion *address_space,
>                                  target_phys_addr_t base,
>                                  target_phys_addr_t descriptors,
>                                  qemu_irq irq, NICInfo *nd)
> {
>    DeviceState *dev;
>    SysBusDevice *s;
>
>    dev = qdev_create(NULL, "open_eth");
>    qdev_set_nic_properties(dev, nd);
>    qdev_init_nofail(dev);
>
>    s = sysbus_from_qdev(dev);
>    sysbus_connect_irq(s, 0, irq);
>    memory_region_add_subregion(address_space, base,
>                                sysbus_mmio_get_region(s, 0));
>    memory_region_add_subregion(address_space, descriptors,
>                                sysbus_mmio_get_region(s, 1));
> }
>
> static void openrisc_sim_init(ram_addr_t ram_size,
>                              const char *boot_device,
>                              const char *kernel_filename,
>                              const char *kernel_cmdline,
>                              const char *initrd_filename,
>                              const char *cpu_model)
> {
>    long kernel_size;
>    uint64_t elf_entry;
>    target_phys_addr_t entry;
>    OpenRISCCPU *cpu = NULL;
>    MemoryRegion *ram;
>    int n;
>
>    if (!cpu_model) {
>        cpu_model = "or1200";
>    }
>
>    for (n = 0; n < smp_cpus; n++) {
>        cpu = cpu_openrisc_init(cpu_model);
>        if (cpu == NULL) {
>            qemu_log("Unable to find CPU defineition!\n");
>            exit(1);
>        }
>        qemu_register_reset(main_cpu_reset, cpu);
>        main_cpu_reset(cpu);
>    }
>
>    ram = g_malloc(sizeof(*ram));
>    memory_region_init_ram(ram, "openrisc.ram", ram_size);
>    vmstate_register_ram_global(ram);
>    memory_region_add_subregion(get_system_memory(), 0, ram);
>
>    /* load kernel */
>    if (kernel_filename && !qtest_enabled()) {
>        kernel_size = load_elf(kernel_filename, NULL, NULL,
>                               &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1);
>        entry = elf_entry;
>        if (kernel_size < 0) {
>            kernel_size = load_uimage(kernel_filename,
>                                      &entry, NULL, NULL);
>        }
>        if (kernel_size < 0) {
>            kernel_size = load_image_targphys(kernel_filename,
>                                              KERNEL_LOAD_ADDR,
>                                              ram_size - KERNEL_LOAD_ADDR);
>            entry = KERNEL_LOAD_ADDR;
>        }
>
>        if (kernel_size < 0) {
>            qemu_log("QEMU: couldn't load the kernel '%s'\n",
>                    kernel_filename);
>            exit(1);
>        }
>    }

I think it was cleaner to have the load_kernel() as its own function,
just without all the dead struct args. Seperates bootloader from
machine init and add a little bit of future proofing when we come to
extract out bootloaders from machine models. But I wont block on it.
Can you move this hunk (or the load_kernel() call) to the end of the
function so bootloading happens after machine creation?

Regards,
Peter

>
>    cpu_openrisc_pic_init(cpu);
>    cpu_openrisc_clock_init(cpu);
>
>    serial_mm_init(get_system_memory(), 0x90000000, 0, cpu->env.irq[2],
>                   115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
>
>    if (nd_table[0].vlan) {
>        openrisc_sim_net_init(get_system_memory(), 0x92000000,
>                              0x92000400, cpu->env.irq[4], nd_table);
>    }

So after this stuff. Bootload here.

>
>    cpu->env.pc = entry;

I would roll this into the load_kernel call too if you went for that
approach. Part of loading a kernel is setting the entry point so it
makes sense to have one BL function do everything. Again, I wont
block, just a suggestion.

> }
>
> static QEMUMachine openrisc_sim_machine = {
>    .name = "or32-sim",
>    .desc = "or32 simulation",
>    .init = openrisc_sim_init,
>    .max_cpus = 1,
>    .is_default = 1,
> };
>
> static void openrisc_sim_machine_init(void)
> {
>    qemu_register_machine(&openrisc_sim_machine);
> }
>
> machine_init(openrisc_sim_machine_init);
>
>
> Please review and let me the new is OK or not, please.
> Thank you, very much, all of you.
>
>
> On Wed, Jun 27, 2012 at 9:10 PM, Peter Crosthwaite
> <peter.crosthwaite@petalogix.com> wrote:
>> On Wed, Jun 27, 2012 at 11:04 PM, Andreas Färber <afaerber@suse.de> wrote:
>>> Am 27.06.2012 14:25, schrieb Peter Crosthwaite:
>>>> Hi Jia,
>>>>
>>>> On Wed, Jun 27, 2012 at 7:54 PM, Jia Liu <proljc@gmail.com> wrote:
>>>>> +static void openrisc_sim_init(ram_addr_t ram_size,
>>>>> +                              const char *boot_device,
>>>>> +                              const char *kernel_filename,
>>>>> +                              const char *kernel_cmdline,
>>>>> +                              const char *initrd_filename,
>>>>> +                              const char *cpu_model)
>>>>> +{
>>>>> +    CPUOpenRISCState *env;
>>>>> +    MemoryRegion *ram = g_new(MemoryRegion, 1);
>>>>> +
>>>>> +    if (!cpu_model) {
>>>>> +        cpu_model = "or1200";
>>>>> +    }
>>>>> +    env = cpu_init(cpu_model);
>>>>> +    if (!env) {
>>>>> +        fprintf(stderr, "Unable to find CPU definition!\n");
>>>>> +        exit(1);
>>>>> +    }
>>>>> +
>>>>> +    qemu_register_reset(main_cpu_reset, env);
>>>>> +    main_cpu_reset(env);
>>>>> +
>>>>
>>>> I think this needs rebasing. Andreas a while back abstracted back to
>>>> the CPU level instead for resets. Andreas can you confirm? should this
>>>> be changed to pass the CPU QOM object to the reset instead? cc
>>>> andreas.
>>>
>>> Thought I had commented that already... maybe I'm starting to confuse
>>> uc32 and or32? :) Yes please, cpu_or32_init() should be called and
>>> return an OpenRISCCPU *cpu. main_cpu_reset() should be passed the cpu,
>>> too. All new APIs (static helpers etc.) should use OpenRISCCPU, not
>>> CPUOpenRISCState.
>>
>> That rule has significant impact on patches 9-10. Andreas, you may
>> wish to check these out - they are psuedo device-models tightly
>> coupled to the cpu env.
>>
>> Regards,
>> Peter
>>
>> That will greatly simplify moving forward.
>>>
>>> Thanks for catching this, Peter.
>>>
>>> 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.
Jia Liu June 29, 2012, 5:16 a.m. UTC | #7
On Fri, Jun 29, 2012 at 11:03 AM, 陳韋任 (Wei-Ren Chen)
<chenwj@iis.sinica.edu.tw> wrote:
>> /* OpenRISC pic handler */
>> static void openrisc_pic_cpu_handler(void *opaque, int irq, int level)
>> {
>>     OpenRISCCPU *cpu = (OpenRISCCPU *)opaque;
>                         ^^^^^^^^^^^^^^
>  Do we need casting before assigning opaque to cpu?
>

nope. I'll remove it.

Thank you.

> Regards,
> chenwj
>
> --
> Wei-Ren Chen (陳韋任)
> Computer Systems Lab, Institute of Information Science,
> Academia Sinica, Taiwan (R.O.C.)
> Tel:886-2-2788-3799 #1667
> Homepage: http://people.cs.nctu.edu.tw/~chenwj
Jia Liu June 29, 2012, 5:56 a.m. UTC | #8
Hi Peter,

On Fri, Jun 29, 2012 at 11:15 AM, Peter Crosthwaite
<peter.crosthwaite@petalogix.com> wrote:
> On Thu, Jun 28, 2012 at 11:56 PM, Jia Liu <proljc@gmail.com> wrote:
>> Hi, Peter, Andreas, and Peter,
>>
>> I've replace env with cpu, and rewrite the load_kernel.
>> Please review these new files:
>>
>> openrisc_pic.c
>>
>> #include "hw.h"
>> #include "cpu.h"
>>
>> /* OpenRISC pic handler */
>> static void openrisc_pic_cpu_handler(void *opaque, int irq, int level)
>> {
>>    OpenRISCCPU *cpu = (OpenRISCCPU *)opaque;
>>    int i;
>>    uint32_t irq_bit = 1 << irq;
>>
>>    if (irq > 31 || irq < 0) {
>>        return;
>>    }
>>
>>    if (level) {
>>        cpu->env.picsr |= irq_bit;
>>    } else {
>>        cpu->env.picsr &= ~irq_bit;
>>    }
>>
>>    for (i = 0; i < 32; i++) {
>>        if ((cpu->env.picsr && (1 << i)) && (cpu->env.picmr && (1 << i))) {
>>            cpu_interrupt(&cpu->env, CPU_INTERRUPT_HARD);
>>        } else {
>>            cpu_reset_interrupt(&cpu->env, CPU_INTERRUPT_HARD);
>>            cpu->env.picsr &= ~(1 << i);
>>        }
>>    }
>> }
>>
>> void cpu_openrisc_pic_init(OpenRISCCPU *cpu)
>> {
>>    int i;
>>    qemu_irq *qi;
>>    qi = qemu_allocate_irqs(openrisc_pic_cpu_handler, cpu, NR_IRQS);
>>
>>    for (i = 0; i < NR_IRQS; i++) {
>>        cpu->env.irq[i] = qi[i];
>>    }
>> }
>> --------------------------------------------------------------------
>>
>> openrisc_timer.c
>>
>> #include "cpu.h"
>> #include "hw.h"
>> #include "qemu-timer.h"
>>
>> #define TIMER_FREQ    (20 * 1000 * 1000)    /* 20MHz */
>>
>> /* The time when TTCR changes */
>> static uint64_t last_clk;
>> static int is_counting;
>>
>> void cpu_openrisc_count_update(OpenRISCCPU *cpu)
>> {
>>    uint64_t now, next;
>>    uint32_t wait;
>>
>>    now = qemu_get_clock_ns(vm_clock);
>>    if (!is_counting) {
>>        qemu_del_timer(cpu->env.timer);
>>        last_clk = now;
>>        return;
>>    }
>>
>>    cpu->env.ttcr += (uint32_t)muldiv64(now - last_clk, TIMER_FREQ,
>>                                        get_ticks_per_sec());
>>    last_clk = now;
>>
>>    if ((cpu->env.ttmr & TTMR_TP) <= (cpu->env.ttcr & TTMR_TP)) {
>>        wait = TTMR_TP - (cpu->env.ttcr & TTMR_TP) + 1;
>>        wait += cpu->env.ttmr & TTMR_TP;
>>    } else {
>>        wait = (cpu->env.ttmr & TTMR_TP) - (cpu->env.ttcr & TTMR_TP);
>>    }
>>
>>    next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ);
>>    qemu_mod_timer(cpu->env.timer, next);
>> }
>>
>> void cpu_openrisc_count_start(OpenRISCCPU *cpu)
>> {
>>    is_counting = 1;
>>    cpu_openrisc_count_update(cpu);
>> }
>>
>> void cpu_openrisc_count_stop(OpenRISCCPU *cpu)
>> {
>>    is_counting = 0;
>>    cpu_openrisc_count_update(cpu);
>> }
>>
>> static void openrisc_timer_cb(void *opaque)
>> {
>>    OpenRISCCPU *cpu = opaque;
>>
>>    if ((cpu->env.ttmr & TTMR_IE) &&
>>         qemu_timer_expired(cpu->env.timer, qemu_get_clock_ns(vm_clock))) {
>>        cpu->env.ttmr |= TTMR_IP;
>>        cpu->env.interrupt_request |= CPU_INTERRUPT_TIMER;
>>    }
>>
>>    switch (cpu->env.ttmr & TTMR_M) {
>>    case TIMER_NONE:
>>        break;
>>    case TIMER_INTR:
>>        cpu->env.ttcr = 0;
>>        cpu_openrisc_count_start(cpu);
>>        break;
>>    case TIMER_SHOT:
>>        cpu_openrisc_count_stop(cpu);
>>        break;
>>    case TIMER_CONT:
>>        cpu_openrisc_count_start(cpu);
>>        break;
>>    }
>> }
>>
>> void cpu_openrisc_clock_init(OpenRISCCPU *cpu)
>> {
>>    cpu->env.timer = qemu_new_timer_ns(vm_clock, &openrisc_timer_cb, cpu);
>>    cpu->env.ttmr = 0x00000000;
>>    cpu->env.ttcr = 0x00000000;
>> }
>> --------------------------------------------------------------------
>>
>> openrisc_sim.c
>>
>> #include "hw.h"
>> #include "boards.h"
>> #include "elf.h"
>> #include "pc.h"
>> #include "loader.h"
>> #include "exec-memory.h"
>> #include "sysemu.h"
>> #include "sysbus.h"
>> #include "qtest.h"
>>
>> #define KERNEL_LOAD_ADDR 0x100
>>
>> static void main_cpu_reset(void *opaque)
>> {
>>    OpenRISCCPU *cpu = opaque;
>>
>>    cpu_reset(CPU(cpu));
>> }
>>
>> static void openrisc_sim_net_init(MemoryRegion *address_space,
>>                                  target_phys_addr_t base,
>>                                  target_phys_addr_t descriptors,
>>                                  qemu_irq irq, NICInfo *nd)
>> {
>>    DeviceState *dev;
>>    SysBusDevice *s;
>>
>>    dev = qdev_create(NULL, "open_eth");
>>    qdev_set_nic_properties(dev, nd);
>>    qdev_init_nofail(dev);
>>
>>    s = sysbus_from_qdev(dev);
>>    sysbus_connect_irq(s, 0, irq);
>>    memory_region_add_subregion(address_space, base,
>>                                sysbus_mmio_get_region(s, 0));
>>    memory_region_add_subregion(address_space, descriptors,
>>                                sysbus_mmio_get_region(s, 1));
>> }
>>
>> static void openrisc_sim_init(ram_addr_t ram_size,
>>                              const char *boot_device,
>>                              const char *kernel_filename,
>>                              const char *kernel_cmdline,
>>                              const char *initrd_filename,
>>                              const char *cpu_model)
>> {
>>    long kernel_size;
>>    uint64_t elf_entry;
>>    target_phys_addr_t entry;
>>    OpenRISCCPU *cpu = NULL;
>>    MemoryRegion *ram;
>>    int n;
>>
>>    if (!cpu_model) {
>>        cpu_model = "or1200";
>>    }
>>
>>    for (n = 0; n < smp_cpus; n++) {
>>        cpu = cpu_openrisc_init(cpu_model);
>>        if (cpu == NULL) {
>>            qemu_log("Unable to find CPU defineition!\n");
>>            exit(1);
>>        }
>>        qemu_register_reset(main_cpu_reset, cpu);
>>        main_cpu_reset(cpu);
>>    }
>>
>>    ram = g_malloc(sizeof(*ram));
>>    memory_region_init_ram(ram, "openrisc.ram", ram_size);
>>    vmstate_register_ram_global(ram);
>>    memory_region_add_subregion(get_system_memory(), 0, ram);
>>
>>    /* load kernel */
>>    if (kernel_filename && !qtest_enabled()) {
>>        kernel_size = load_elf(kernel_filename, NULL, NULL,
>>                               &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1);
>>        entry = elf_entry;
>>        if (kernel_size < 0) {
>>            kernel_size = load_uimage(kernel_filename,
>>                                      &entry, NULL, NULL);
>>        }
>>        if (kernel_size < 0) {
>>            kernel_size = load_image_targphys(kernel_filename,
>>                                              KERNEL_LOAD_ADDR,
>>                                              ram_size - KERNEL_LOAD_ADDR);
>>            entry = KERNEL_LOAD_ADDR;
>>        }
>>
>>        if (kernel_size < 0) {
>>            qemu_log("QEMU: couldn't load the kernel '%s'\n",
>>                    kernel_filename);
>>            exit(1);
>>        }
>>    }
>
> I think it was cleaner to have the load_kernel() as its own function,
> just without all the dead struct args. Seperates bootloader from
> machine init and add a little bit of future proofing when we come to
> extract out bootloaders from machine models. But I wont block on it.
> Can you move this hunk (or the load_kernel() call) to the end of the
> function so bootloading happens after machine creation?
>
> Regards,
> Peter
>
>>
>>    cpu_openrisc_pic_init(cpu);
>>    cpu_openrisc_clock_init(cpu);
>>
>>    serial_mm_init(get_system_memory(), 0x90000000, 0, cpu->env.irq[2],
>>                   115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
>>
>>    if (nd_table[0].vlan) {
>>        openrisc_sim_net_init(get_system_memory(), 0x92000000,
>>                              0x92000400, cpu->env.irq[4], nd_table);
>>    }
>
> So after this stuff. Bootload here.
>
>>
>>    cpu->env.pc = entry;
>
> I would roll this into the load_kernel call too if you went for that
> approach. Part of loading a kernel is setting the entry point so it
> makes sense to have one BL function do everything. Again, I wont
> block, just a suggestion.
>

Thanks for review. And, thank you very much for your suggestion.

Is this new code OK?

static void cpu_openrisc_load_kernel(ram_addr_t ram_size,
                                     const char* kernel_filename,
                                     OpenRISCCPU *cpu)
{
    long kernel_size;
    uint64_t elf_entry;
    target_phys_addr_t entry;

    if (kernel_filename && !qtest_enabled()) {
        kernel_size = load_elf(kernel_filename, NULL, NULL,
                               &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1);
        entry = elf_entry;
        if (kernel_size < 0) {
            kernel_size = load_uimage(kernel_filename,
                                      &entry, NULL, NULL);
        }
        if (kernel_size < 0) {
            kernel_size = load_image_targphys(kernel_filename,
                                              KERNEL_LOAD_ADDR,
                                              ram_size - KERNEL_LOAD_ADDR);
            entry = KERNEL_LOAD_ADDR;
        }

        if (kernel_size < 0) {
            qemu_log("QEMU: couldn't load the kernel '%s'\n",
                    kernel_filename);
            exit(1);
        }
    }

    cpu->env.pc = entry;
}

static void openrisc_sim_init(ram_addr_t ram_size,
                              const char *boot_device,
                              const char *kernel_filename,
                              const char *kernel_cmdline,
                              const char *initrd_filename,
                              const char *cpu_model)
{
   OpenRISCCPU *cpu = NULL;
    MemoryRegion *ram;
    int n;

    if (!cpu_model) {
        cpu_model = "or1200";
    }

    for (n = 0; n < smp_cpus; n++) {
        cpu = cpu_openrisc_init(cpu_model);
        if (cpu == NULL) {
            qemu_log("Unable to find CPU defineition!\n");
            exit(1);
        }
        qemu_register_reset(main_cpu_reset, cpu);
        main_cpu_reset(cpu);
    }

    ram = g_malloc(sizeof(*ram));
    memory_region_init_ram(ram, "openrisc.ram", ram_size);
    vmstate_register_ram_global(ram);
    memory_region_add_subregion(get_system_memory(), 0, ram);

    cpu_openrisc_pic_init(cpu);
    cpu_openrisc_clock_init(cpu);

    serial_mm_init(get_system_memory(), 0x90000000, 0, cpu->env.irq[2],
                   115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);

    if (nd_table[0].vlan) {
        openrisc_sim_net_init(get_system_memory(), 0x92000000,
                              0x92000400, cpu->env.irq[4], nd_table);
    }

    cpu_openrisc_load_kernel(ram_size, kernel_filename, cpu);
}

>> }
>>
>> static QEMUMachine openrisc_sim_machine = {
>>    .name = "or32-sim",
>>    .desc = "or32 simulation",
>>    .init = openrisc_sim_init,
>>    .max_cpus = 1,
>>    .is_default = 1,
>> };
>>
>> static void openrisc_sim_machine_init(void)
>> {
>>    qemu_register_machine(&openrisc_sim_machine);
>> }
>>
>> machine_init(openrisc_sim_machine_init);
>>
>>
>> Please review and let me the new is OK or not, please.
>> Thank you, very much, all of you.
>>
>>
>> On Wed, Jun 27, 2012 at 9:10 PM, Peter Crosthwaite
>> <peter.crosthwaite@petalogix.com> wrote:
>>> On Wed, Jun 27, 2012 at 11:04 PM, Andreas Färber <afaerber@suse.de> wrote:
>>>> Am 27.06.2012 14:25, schrieb Peter Crosthwaite:
>>>>> Hi Jia,
>>>>>
>>>>> On Wed, Jun 27, 2012 at 7:54 PM, Jia Liu <proljc@gmail.com> wrote:
>>>>>> +static void openrisc_sim_init(ram_addr_t ram_size,
>>>>>> +                              const char *boot_device,
>>>>>> +                              const char *kernel_filename,
>>>>>> +                              const char *kernel_cmdline,
>>>>>> +                              const char *initrd_filename,
>>>>>> +                              const char *cpu_model)
>>>>>> +{
>>>>>> +    CPUOpenRISCState *env;
>>>>>> +    MemoryRegion *ram = g_new(MemoryRegion, 1);
>>>>>> +
>>>>>> +    if (!cpu_model) {
>>>>>> +        cpu_model = "or1200";
>>>>>> +    }
>>>>>> +    env = cpu_init(cpu_model);
>>>>>> +    if (!env) {
>>>>>> +        fprintf(stderr, "Unable to find CPU definition!\n");
>>>>>> +        exit(1);
>>>>>> +    }
>>>>>> +
>>>>>> +    qemu_register_reset(main_cpu_reset, env);
>>>>>> +    main_cpu_reset(env);
>>>>>> +
>>>>>
>>>>> I think this needs rebasing. Andreas a while back abstracted back to
>>>>> the CPU level instead for resets. Andreas can you confirm? should this
>>>>> be changed to pass the CPU QOM object to the reset instead? cc
>>>>> andreas.
>>>>
>>>> Thought I had commented that already... maybe I'm starting to confuse
>>>> uc32 and or32? :) Yes please, cpu_or32_init() should be called and
>>>> return an OpenRISCCPU *cpu. main_cpu_reset() should be passed the cpu,
>>>> too. All new APIs (static helpers etc.) should use OpenRISCCPU, not
>>>> CPUOpenRISCState.
>>>
>>> That rule has significant impact on patches 9-10. Andreas, you may
>>> wish to check these out - they are psuedo device-models tightly
>>> coupled to the cpu env.
>>>
>>> Regards,
>>> Peter
>>>
>>> That will greatly simplify moving forward.
>>>>
>>>> Thanks for catching this, Peter.
>>>>
>>>> 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.

Regards,
Jia.
Peter A. G. Crosthwaite June 29, 2012, 6:27 a.m. UTC | #9
Looks good to me,

Peter

On Fri, Jun 29, 2012 at 3:56 PM, Jia Liu <proljc@gmail.com> wrote:
> Hi Peter,
>
> On Fri, Jun 29, 2012 at 11:15 AM, Peter Crosthwaite
> <peter.crosthwaite@petalogix.com> wrote:
>> On Thu, Jun 28, 2012 at 11:56 PM, Jia Liu <proljc@gmail.com> wrote:
>>> Hi, Peter, Andreas, and Peter,
>>>
>>> I've replace env with cpu, and rewrite the load_kernel.
>>> Please review these new files:
>>>
>>> openrisc_pic.c
>>>
>>> #include "hw.h"
>>> #include "cpu.h"
>>>
>>> /* OpenRISC pic handler */
>>> static void openrisc_pic_cpu_handler(void *opaque, int irq, int level)
>>> {
>>>    OpenRISCCPU *cpu = (OpenRISCCPU *)opaque;
>>>    int i;
>>>    uint32_t irq_bit = 1 << irq;
>>>
>>>    if (irq > 31 || irq < 0) {
>>>        return;
>>>    }
>>>
>>>    if (level) {
>>>        cpu->env.picsr |= irq_bit;
>>>    } else {
>>>        cpu->env.picsr &= ~irq_bit;
>>>    }
>>>
>>>    for (i = 0; i < 32; i++) {
>>>        if ((cpu->env.picsr && (1 << i)) && (cpu->env.picmr && (1 << i))) {
>>>            cpu_interrupt(&cpu->env, CPU_INTERRUPT_HARD);
>>>        } else {
>>>            cpu_reset_interrupt(&cpu->env, CPU_INTERRUPT_HARD);
>>>            cpu->env.picsr &= ~(1 << i);
>>>        }
>>>    }
>>> }
>>>
>>> void cpu_openrisc_pic_init(OpenRISCCPU *cpu)
>>> {
>>>    int i;
>>>    qemu_irq *qi;
>>>    qi = qemu_allocate_irqs(openrisc_pic_cpu_handler, cpu, NR_IRQS);
>>>
>>>    for (i = 0; i < NR_IRQS; i++) {
>>>        cpu->env.irq[i] = qi[i];
>>>    }
>>> }
>>> --------------------------------------------------------------------
>>>
>>> openrisc_timer.c
>>>
>>> #include "cpu.h"
>>> #include "hw.h"
>>> #include "qemu-timer.h"
>>>
>>> #define TIMER_FREQ    (20 * 1000 * 1000)    /* 20MHz */
>>>
>>> /* The time when TTCR changes */
>>> static uint64_t last_clk;
>>> static int is_counting;
>>>
>>> void cpu_openrisc_count_update(OpenRISCCPU *cpu)
>>> {
>>>    uint64_t now, next;
>>>    uint32_t wait;
>>>
>>>    now = qemu_get_clock_ns(vm_clock);
>>>    if (!is_counting) {
>>>        qemu_del_timer(cpu->env.timer);
>>>        last_clk = now;
>>>        return;
>>>    }
>>>
>>>    cpu->env.ttcr += (uint32_t)muldiv64(now - last_clk, TIMER_FREQ,
>>>                                        get_ticks_per_sec());
>>>    last_clk = now;
>>>
>>>    if ((cpu->env.ttmr & TTMR_TP) <= (cpu->env.ttcr & TTMR_TP)) {
>>>        wait = TTMR_TP - (cpu->env.ttcr & TTMR_TP) + 1;
>>>        wait += cpu->env.ttmr & TTMR_TP;
>>>    } else {
>>>        wait = (cpu->env.ttmr & TTMR_TP) - (cpu->env.ttcr & TTMR_TP);
>>>    }
>>>
>>>    next = now + muldiv64(wait, get_ticks_per_sec(), TIMER_FREQ);
>>>    qemu_mod_timer(cpu->env.timer, next);
>>> }
>>>
>>> void cpu_openrisc_count_start(OpenRISCCPU *cpu)
>>> {
>>>    is_counting = 1;
>>>    cpu_openrisc_count_update(cpu);
>>> }
>>>
>>> void cpu_openrisc_count_stop(OpenRISCCPU *cpu)
>>> {
>>>    is_counting = 0;
>>>    cpu_openrisc_count_update(cpu);
>>> }
>>>
>>> static void openrisc_timer_cb(void *opaque)
>>> {
>>>    OpenRISCCPU *cpu = opaque;
>>>
>>>    if ((cpu->env.ttmr & TTMR_IE) &&
>>>         qemu_timer_expired(cpu->env.timer, qemu_get_clock_ns(vm_clock))) {
>>>        cpu->env.ttmr |= TTMR_IP;
>>>        cpu->env.interrupt_request |= CPU_INTERRUPT_TIMER;
>>>    }
>>>
>>>    switch (cpu->env.ttmr & TTMR_M) {
>>>    case TIMER_NONE:
>>>        break;
>>>    case TIMER_INTR:
>>>        cpu->env.ttcr = 0;
>>>        cpu_openrisc_count_start(cpu);
>>>        break;
>>>    case TIMER_SHOT:
>>>        cpu_openrisc_count_stop(cpu);
>>>        break;
>>>    case TIMER_CONT:
>>>        cpu_openrisc_count_start(cpu);
>>>        break;
>>>    }
>>> }
>>>
>>> void cpu_openrisc_clock_init(OpenRISCCPU *cpu)
>>> {
>>>    cpu->env.timer = qemu_new_timer_ns(vm_clock, &openrisc_timer_cb, cpu);
>>>    cpu->env.ttmr = 0x00000000;
>>>    cpu->env.ttcr = 0x00000000;
>>> }
>>> --------------------------------------------------------------------
>>>
>>> openrisc_sim.c
>>>
>>> #include "hw.h"
>>> #include "boards.h"
>>> #include "elf.h"
>>> #include "pc.h"
>>> #include "loader.h"
>>> #include "exec-memory.h"
>>> #include "sysemu.h"
>>> #include "sysbus.h"
>>> #include "qtest.h"
>>>
>>> #define KERNEL_LOAD_ADDR 0x100
>>>
>>> static void main_cpu_reset(void *opaque)
>>> {
>>>    OpenRISCCPU *cpu = opaque;
>>>
>>>    cpu_reset(CPU(cpu));
>>> }
>>>
>>> static void openrisc_sim_net_init(MemoryRegion *address_space,
>>>                                  target_phys_addr_t base,
>>>                                  target_phys_addr_t descriptors,
>>>                                  qemu_irq irq, NICInfo *nd)
>>> {
>>>    DeviceState *dev;
>>>    SysBusDevice *s;
>>>
>>>    dev = qdev_create(NULL, "open_eth");
>>>    qdev_set_nic_properties(dev, nd);
>>>    qdev_init_nofail(dev);
>>>
>>>    s = sysbus_from_qdev(dev);
>>>    sysbus_connect_irq(s, 0, irq);
>>>    memory_region_add_subregion(address_space, base,
>>>                                sysbus_mmio_get_region(s, 0));
>>>    memory_region_add_subregion(address_space, descriptors,
>>>                                sysbus_mmio_get_region(s, 1));
>>> }
>>>
>>> static void openrisc_sim_init(ram_addr_t ram_size,
>>>                              const char *boot_device,
>>>                              const char *kernel_filename,
>>>                              const char *kernel_cmdline,
>>>                              const char *initrd_filename,
>>>                              const char *cpu_model)
>>> {
>>>    long kernel_size;
>>>    uint64_t elf_entry;
>>>    target_phys_addr_t entry;
>>>    OpenRISCCPU *cpu = NULL;
>>>    MemoryRegion *ram;
>>>    int n;
>>>
>>>    if (!cpu_model) {
>>>        cpu_model = "or1200";
>>>    }
>>>
>>>    for (n = 0; n < smp_cpus; n++) {
>>>        cpu = cpu_openrisc_init(cpu_model);
>>>        if (cpu == NULL) {
>>>            qemu_log("Unable to find CPU defineition!\n");
>>>            exit(1);
>>>        }
>>>        qemu_register_reset(main_cpu_reset, cpu);
>>>        main_cpu_reset(cpu);
>>>    }
>>>
>>>    ram = g_malloc(sizeof(*ram));
>>>    memory_region_init_ram(ram, "openrisc.ram", ram_size);
>>>    vmstate_register_ram_global(ram);
>>>    memory_region_add_subregion(get_system_memory(), 0, ram);
>>>
>>>    /* load kernel */
>>>    if (kernel_filename && !qtest_enabled()) {
>>>        kernel_size = load_elf(kernel_filename, NULL, NULL,
>>>                               &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1);
>>>        entry = elf_entry;
>>>        if (kernel_size < 0) {
>>>            kernel_size = load_uimage(kernel_filename,
>>>                                      &entry, NULL, NULL);
>>>        }
>>>        if (kernel_size < 0) {
>>>            kernel_size = load_image_targphys(kernel_filename,
>>>                                              KERNEL_LOAD_ADDR,
>>>                                              ram_size - KERNEL_LOAD_ADDR);
>>>            entry = KERNEL_LOAD_ADDR;
>>>        }
>>>
>>>        if (kernel_size < 0) {
>>>            qemu_log("QEMU: couldn't load the kernel '%s'\n",
>>>                    kernel_filename);
>>>            exit(1);
>>>        }
>>>    }
>>
>> I think it was cleaner to have the load_kernel() as its own function,
>> just without all the dead struct args. Seperates bootloader from
>> machine init and add a little bit of future proofing when we come to
>> extract out bootloaders from machine models. But I wont block on it.
>> Can you move this hunk (or the load_kernel() call) to the end of the
>> function so bootloading happens after machine creation?
>>
>> Regards,
>> Peter
>>
>>>
>>>    cpu_openrisc_pic_init(cpu);
>>>    cpu_openrisc_clock_init(cpu);
>>>
>>>    serial_mm_init(get_system_memory(), 0x90000000, 0, cpu->env.irq[2],
>>>                   115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
>>>
>>>    if (nd_table[0].vlan) {
>>>        openrisc_sim_net_init(get_system_memory(), 0x92000000,
>>>                              0x92000400, cpu->env.irq[4], nd_table);
>>>    }
>>
>> So after this stuff. Bootload here.
>>
>>>
>>>    cpu->env.pc = entry;
>>
>> I would roll this into the load_kernel call too if you went for that
>> approach. Part of loading a kernel is setting the entry point so it
>> makes sense to have one BL function do everything. Again, I wont
>> block, just a suggestion.
>>
>
> Thanks for review. And, thank you very much for your suggestion.
>
> Is this new code OK?
>
> static void cpu_openrisc_load_kernel(ram_addr_t ram_size,
>                                     const char* kernel_filename,
>                                     OpenRISCCPU *cpu)
> {
>    long kernel_size;
>    uint64_t elf_entry;
>    target_phys_addr_t entry;
>
>    if (kernel_filename && !qtest_enabled()) {
>        kernel_size = load_elf(kernel_filename, NULL, NULL,
>                               &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1);
>        entry = elf_entry;
>        if (kernel_size < 0) {
>            kernel_size = load_uimage(kernel_filename,
>                                      &entry, NULL, NULL);
>        }
>        if (kernel_size < 0) {
>            kernel_size = load_image_targphys(kernel_filename,
>                                              KERNEL_LOAD_ADDR,
>                                              ram_size - KERNEL_LOAD_ADDR);
>            entry = KERNEL_LOAD_ADDR;
>        }
>
>        if (kernel_size < 0) {
>            qemu_log("QEMU: couldn't load the kernel '%s'\n",
>                    kernel_filename);
>            exit(1);
>        }
>    }
>
>    cpu->env.pc = entry;
> }
>
> static void openrisc_sim_init(ram_addr_t ram_size,
>                              const char *boot_device,
>                              const char *kernel_filename,
>                              const char *kernel_cmdline,
>                              const char *initrd_filename,
>                              const char *cpu_model)
> {
>   OpenRISCCPU *cpu = NULL;
>    MemoryRegion *ram;
>    int n;
>
>    if (!cpu_model) {
>        cpu_model = "or1200";
>    }
>
>    for (n = 0; n < smp_cpus; n++) {
>        cpu = cpu_openrisc_init(cpu_model);
>        if (cpu == NULL) {
>            qemu_log("Unable to find CPU defineition!\n");
>            exit(1);
>        }
>        qemu_register_reset(main_cpu_reset, cpu);
>        main_cpu_reset(cpu);
>    }
>
>    ram = g_malloc(sizeof(*ram));
>    memory_region_init_ram(ram, "openrisc.ram", ram_size);
>    vmstate_register_ram_global(ram);
>    memory_region_add_subregion(get_system_memory(), 0, ram);
>
>    cpu_openrisc_pic_init(cpu);
>    cpu_openrisc_clock_init(cpu);
>
>    serial_mm_init(get_system_memory(), 0x90000000, 0, cpu->env.irq[2],
>                   115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
>
>    if (nd_table[0].vlan) {
>        openrisc_sim_net_init(get_system_memory(), 0x92000000,
>                              0x92000400, cpu->env.irq[4], nd_table);
>    }
>
>    cpu_openrisc_load_kernel(ram_size, kernel_filename, cpu);
> }
>
>>> }
>>>
>>> static QEMUMachine openrisc_sim_machine = {
>>>    .name = "or32-sim",
>>>    .desc = "or32 simulation",
>>>    .init = openrisc_sim_init,
>>>    .max_cpus = 1,
>>>    .is_default = 1,
>>> };
>>>
>>> static void openrisc_sim_machine_init(void)
>>> {
>>>    qemu_register_machine(&openrisc_sim_machine);
>>> }
>>>
>>> machine_init(openrisc_sim_machine_init);
>>>
>>>
>>> Please review and let me the new is OK or not, please.
>>> Thank you, very much, all of you.
>>>
>>>
>>> On Wed, Jun 27, 2012 at 9:10 PM, Peter Crosthwaite
>>> <peter.crosthwaite@petalogix.com> wrote:
>>>> On Wed, Jun 27, 2012 at 11:04 PM, Andreas Färber <afaerber@suse.de> wrote:
>>>>> Am 27.06.2012 14:25, schrieb Peter Crosthwaite:
>>>>>> Hi Jia,
>>>>>>
>>>>>> On Wed, Jun 27, 2012 at 7:54 PM, Jia Liu <proljc@gmail.com> wrote:
>>>>>>> +static void openrisc_sim_init(ram_addr_t ram_size,
>>>>>>> +                              const char *boot_device,
>>>>>>> +                              const char *kernel_filename,
>>>>>>> +                              const char *kernel_cmdline,
>>>>>>> +                              const char *initrd_filename,
>>>>>>> +                              const char *cpu_model)
>>>>>>> +{
>>>>>>> +    CPUOpenRISCState *env;
>>>>>>> +    MemoryRegion *ram = g_new(MemoryRegion, 1);
>>>>>>> +
>>>>>>> +    if (!cpu_model) {
>>>>>>> +        cpu_model = "or1200";
>>>>>>> +    }
>>>>>>> +    env = cpu_init(cpu_model);
>>>>>>> +    if (!env) {
>>>>>>> +        fprintf(stderr, "Unable to find CPU definition!\n");
>>>>>>> +        exit(1);
>>>>>>> +    }
>>>>>>> +
>>>>>>> +    qemu_register_reset(main_cpu_reset, env);
>>>>>>> +    main_cpu_reset(env);
>>>>>>> +
>>>>>>
>>>>>> I think this needs rebasing. Andreas a while back abstracted back to
>>>>>> the CPU level instead for resets. Andreas can you confirm? should this
>>>>>> be changed to pass the CPU QOM object to the reset instead? cc
>>>>>> andreas.
>>>>>
>>>>> Thought I had commented that already... maybe I'm starting to confuse
>>>>> uc32 and or32? :) Yes please, cpu_or32_init() should be called and
>>>>> return an OpenRISCCPU *cpu. main_cpu_reset() should be passed the cpu,
>>>>> too. All new APIs (static helpers etc.) should use OpenRISCCPU, not
>>>>> CPUOpenRISCState.
>>>>
>>>> That rule has significant impact on patches 9-10. Andreas, you may
>>>> wish to check these out - they are psuedo device-models tightly
>>>> coupled to the cpu env.
>>>>
>>>> Regards,
>>>> Peter
>>>>
>>>> That will greatly simplify moving forward.
>>>>>
>>>>> Thanks for catching this, Peter.
>>>>>
>>>>> 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.
>
> Regards,
> Jia.
diff mbox

Patch

diff --git a/hw/openrisc/Makefile.objs b/hw/openrisc/Makefile.objs
index 1c541a5..38ff8f5 100644
--- a/hw/openrisc/Makefile.objs
+++ b/hw/openrisc/Makefile.objs
@@ -1,3 +1,3 @@ 
-obj-y = openrisc_pic.o openrisc_timer.o
+obj-y = openrisc_pic.o openrisc_sim.o openrisc_timer.o
 
 obj-y := $(addprefix ../,$(obj-y))
diff --git a/hw/openrisc_sim.c b/hw/openrisc_sim.c
new file mode 100644
index 0000000..b0c1e69
--- /dev/null
+++ b/hw/openrisc_sim.c
@@ -0,0 +1,149 @@ 
+/*
+ *  OpenRISC simulator for use as an IIS.
+ *
+ *  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 "hw.h"
+#include "openrisc_cpudev.h"
+#include "boards.h"
+#include "elf.h"
+#include "pc.h"
+#include "loader.h"
+#include "exec-memory.h"
+#include "sysemu.h"
+#include "sysbus.h"
+#include "qtest.h"
+
+#define KERNEL_LOAD_ADDR 0x100
+
+static struct _loaderparams {
+    uint64_t ram_size;
+    const char *kernel_filename;
+    const char *kernel_cmdline;
+    const char *initrd_filename;
+} loaderparams;
+
+static void main_cpu_reset(void *opaque)
+{
+    CPUOpenRISCState *env = opaque;
+    cpu_reset(ENV_GET_CPU(env));
+}
+
+static void openrisc_sim_net_init(MemoryRegion *address_space,
+                                  target_phys_addr_t base,
+                                  target_phys_addr_t descriptors,
+                                  qemu_irq irq, NICInfo *nd)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+    dev = qdev_create(NULL, "open_eth");
+    qdev_set_nic_properties(dev, nd);
+    qdev_init_nofail(dev);
+
+    s = sysbus_from_qdev(dev);
+    sysbus_connect_irq(s, 0, irq);
+    memory_region_add_subregion(address_space, base,
+                                sysbus_mmio_get_region(s, 0));
+    memory_region_add_subregion(address_space, descriptors,
+                                sysbus_mmio_get_region(s, 1));
+}
+
+static uint64_t openrisc_load_kernel(void)
+{
+    long kernel_size;
+    uint64_t elf_entry;
+    target_phys_addr_t entry;
+
+    if (loaderparams.kernel_filename && !qtest_enabled()) {
+        kernel_size = load_uimage(loaderparams.kernel_filename,
+                                  &entry, NULL, NULL);
+        if (kernel_size < 0) {
+            kernel_size = load_elf(loaderparams.kernel_filename, NULL, NULL,
+                                   &elf_entry, NULL, NULL, 1, ELF_MACHINE, 1);
+            entry = elf_entry;
+        }
+
+        if (kernel_size < 0) {
+            fprintf(stderr, "QEMU: couldn't load the kernel '%s'\n",
+                    loaderparams.kernel_filename);
+            exit(1);
+        }
+    }
+
+    return entry;
+}
+
+static void openrisc_sim_init(ram_addr_t ram_size,
+                              const char *boot_device,
+                              const char *kernel_filename,
+                              const char *kernel_cmdline,
+                              const char *initrd_filename,
+                              const char *cpu_model)
+{
+    CPUOpenRISCState *env;
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+
+    if (!cpu_model) {
+        cpu_model = "or1200";
+    }
+    env = cpu_init(cpu_model);
+    if (!env) {
+        fprintf(stderr, "Unable to find CPU definition!\n");
+        exit(1);
+    }
+
+    qemu_register_reset(main_cpu_reset, env);
+    main_cpu_reset(env);
+
+    memory_region_init_ram(ram, "openrisc.ram", ram_size);
+    memory_region_add_subregion(get_system_memory(), 0, ram);
+
+    if (kernel_filename) {
+        loaderparams.ram_size = ram_size;
+        loaderparams.kernel_filename = kernel_filename;
+        loaderparams.kernel_cmdline = kernel_cmdline;
+        env->pc = openrisc_load_kernel();
+    }
+
+    cpu_openrisc_pic_init(env);
+    cpu_openrisc_clock_init(env);
+
+    serial_mm_init(get_system_memory(), 0x90000000, 0,
+                   env->irq[2], 115200, serial_hds[0], DEVICE_NATIVE_ENDIAN);
+
+    if (nd_table[0].vlan) {
+        openrisc_sim_net_init(get_system_memory(), 0x92000000,
+                              0x92000400, env->irq[4], nd_table);
+    }
+}
+
+static QEMUMachine openrisc_sim_machine = {
+    .name = "or32-sim",
+    .desc = "or32 simulation",
+    .init = openrisc_sim_init,
+    .max_cpus = 1,
+    .is_default = 1,
+};
+
+static void openrisc_sim_machine_init(void)
+{
+    qemu_register_machine(&openrisc_sim_machine);
+}
+
+machine_init(openrisc_sim_machine_init);