qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH 06/17] lm32: interrupt controller model


From: Blue Swirl
Subject: Re: [Qemu-devel] [PATCH 06/17] lm32: interrupt controller model
Date: Fri, 11 Feb 2011 23:49:59 +0200

On Fri, Feb 11, 2011 at 1:11 AM, Michael Walle <address@hidden> wrote:
> This patch adds the interrupt controller of the lm32. Because the PIC is
> accessed through special control registers and opcodes, there are callbacks
> from the lm32 translation code to this model.
>
> Signed-off-by: Michael Walle <address@hidden>
> ---
>  hw/lm32_pic.c     |  191 
> +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  hw/lm32_pic.h     |   10 +++
>  hw/lm32_pic_cpu.c |   37 ++++++++++
>  trace-events      |    9 +++
>  4 files changed, 247 insertions(+), 0 deletions(-)
>  create mode 100644 hw/lm32_pic.c
>  create mode 100644 hw/lm32_pic.h
>  create mode 100644 hw/lm32_pic_cpu.c
>
> diff --git a/hw/lm32_pic.c b/hw/lm32_pic.c
> new file mode 100644
> index 0000000..dbef535
> --- /dev/null
> +++ b/hw/lm32_pic.c
> @@ -0,0 +1,191 @@
> +/*
> + *  LatticeMico32 CPU interrupt controller logic.
> + *
> + *  Copyright (c) 2010 Michael Walle <address@hidden>
> + *
> + * 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 <assert.h>
> +
> +#include "hw.h"
> +#include "pc.h"
> +#include "monitor.h"
> +#include "sysbus.h"
> +#include "trace.h"
> +#include "lm32_pic.h"
> +
> +struct LM32PicState {
> +    SysBusDevice busdev;
> +    qemu_irq parent_irq;
> +    uint32_t im;        /* interrupt mask */
> +    uint32_t ip;        /* interrupt pending */
> +    uint32_t irq_state;
> +
> +    /* statistics */
> +    uint32_t stats_irq_count[32];
> +};
> +typedef struct LM32PicState LM32PicState;
> +
> +static LM32PicState *pic;
> +void pic_info(Monitor *mon)
> +{
> +    if (pic == NULL) {
> +        return;
> +    }
> +
> +    monitor_printf(mon, "lm32-pic: im=%08x ip=%08x irq_state=%08x\n",
> +            pic->im, pic->ip, pic->irq_state);
> +}
> +
> +void irq_info(Monitor *mon)
> +{
> +    int i;
> +    uint32_t count;
> +
> +    if (pic == NULL) {
> +        return;
> +    }
> +
> +    monitor_printf(mon, "IRQ statistics:\n");
> +    for (i = 0; i < 32; i++) {
> +        count = pic->stats_irq_count[i];
> +        if (count > 0) {
> +            monitor_printf(mon, "%2d: %u\n", i, count);
> +        }
> +    }
> +}
> +
> +static void update_irq(LM32PicState *s)
> +{
> +    s->ip |= s->irq_state;
> +
> +    if (s->ip & s->im) {
> +        trace_lm32_pic_raise_irq();
> +        qemu_irq_raise(s->parent_irq);
> +    } else {
> +        trace_lm32_pic_lower_irq();
> +        qemu_irq_lower(s->parent_irq);
> +    }
> +}
> +
> +static void irq_handler(void *opaque, int irq, int level)
> +{
> +    LM32PicState *s = opaque;
> +
> +    assert(irq < 32);
> +    trace_lm32_pic_interrupt(irq, level);
> +
> +    if (level) {
> +        s->irq_state |= (1 << irq);
> +        s->stats_irq_count[irq]++;
> +    } else {
> +        s->irq_state &= ~(1 << irq);
> +    }
> +
> +    update_irq(s);
> +}
> +
> +void lm32_pic_set_im(CPUState *env, uint32_t im)

Again, this and the functions below should be reworked so that
CPUState is not passed to a device.

> +{
> +    LM32PicState *s = env->pic_env;
> +
> +    trace_lm32_pic_set_im(im);
> +    s->im = im;
> +
> +    update_irq(s);
> +}
> +
> +void lm32_pic_set_ip(CPUState *env, uint32_t ip)
> +{
> +    LM32PicState *s = env->pic_env;
> +
> +    trace_lm32_pic_set_ip(ip);
> +
> +    /* ack interrupt */
> +    s->ip &= ~ip;
> +
> +    update_irq(s);
> +}
> +
> +uint32_t lm32_pic_get_im(CPUState *env)
> +{
> +    LM32PicState *s = env->pic_env;
> +
> +    trace_lm32_pic_get_im(s->im);
> +    return s->im;
> +}
> +
> +uint32_t lm32_pic_get_ip(CPUState *env)
> +{
> +    LM32PicState *s = env->pic_env;
> +
> +    trace_lm32_pic_get_ip(s->ip);
> +    return s->ip;
> +}
> +
> +static void pic_reset(void *opaque)
> +{
> +    LM32PicState *s = opaque;
> +    int i;
> +
> +    s->im = 0;
> +    s->ip = 0;
> +    s->irq_state = 0;
> +    for (i = 0; i < 32; i++) {
> +        s->stats_irq_count[i] = 0;
> +    }
> +    qemu_irq_lower(s->parent_irq);

Remove.

> +}
> +
> +static int lm32_pic_init(SysBusDevice *dev)
> +{
> +    LM32PicState *s = FROM_SYSBUS(typeof(*s), dev);
> +
> +    qdev_init_gpio_in(&dev->qdev, irq_handler, 32);
> +    sysbus_init_irq(dev, &s->parent_irq);
> +    qemu_register_reset(pic_reset, s);

qdev reset field

> +
> +    pic = s;
> +
> +    return 0;
> +}
> +
> +static const VMStateDescription vmstate_lm32_pic = {
> +    .name = "lm32-pic",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .minimum_version_id_old = 1,
> +    .fields      = (VMStateField[]) {
> +        VMSTATE_UINT32(im, LM32PicState),
> +        VMSTATE_UINT32(ip, LM32PicState),
> +        VMSTATE_UINT32(irq_state, LM32PicState),
> +        VMSTATE_UINT32_ARRAY(stats_irq_count, LM32PicState, 32),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static SysBusDeviceInfo lm32_pic_info = {
> +    .init = lm32_pic_init,
> +    .qdev.name = "lm32-pic",
> +    .qdev.size = sizeof(LM32PicState),
> +    .qdev.vmsd  = &vmstate_lm32_pic,
> +};
> +
> +static void lm32_pic_register(void)
> +{
> +    sysbus_register_withprop(&lm32_pic_info);
> +}
> +
> +device_init(lm32_pic_register)
> diff --git a/hw/lm32_pic.h b/hw/lm32_pic.h
> new file mode 100644
> index 0000000..ce39ac7
> --- /dev/null
> +++ b/hw/lm32_pic.h
> @@ -0,0 +1,10 @@
> +#ifndef __LM32_PIC

QEMU_HW_LM32_PIC_H

> +#define __LM32_PIC
> +
> +#include "qemu-common.h"
> +
> +uint32_t lm32_pic_get_ip(CPUState *env);
> +uint32_t lm32_pic_get_im(CPUState *env);
> +void lm32_pic_set_ip(CPUState *env, uint32_t ip);
> +void lm32_pic_set_im(CPUState *env, uint32_t im);
> +#endif
> diff --git a/hw/lm32_pic_cpu.c b/hw/lm32_pic_cpu.c
> new file mode 100644
> index 0000000..8bbeccc
> --- /dev/null
> +++ b/hw/lm32_pic_cpu.c
> @@ -0,0 +1,37 @@
> +/*
> + *  LatticeMico32 CPU interrupt wrapper logic.
> + *
> + *  Copyright (c) 2010 Michael Walle <address@hidden>
> + *
> + * 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"
> +
> +static void lm32_pic_cpu_handler(void *opaque, int irq, int level)
> +{
> +    CPUState *env = (CPUState *)opaque;

Useless cast in C.

> +
> +    if (level) {
> +        cpu_interrupt(env, CPU_INTERRUPT_HARD);
> +    } else {
> +        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
> +    }
> +}
> +
> +qemu_irq *lm32_pic_init_cpu(CPUState *env);

Belongs to a header.

> +qemu_irq *lm32_pic_init_cpu(CPUState *env)
> +{
> +    return qemu_allocate_irqs(lm32_pic_cpu_handler, env, 1);
> +}

The whole file does not seem very useful. I'd merge this to board file instead.

> diff --git a/trace-events b/trace-events
> index e6138ea..557375e 100644
> --- a/trace-events
> +++ b/trace-events
> @@ -254,3 +254,12 @@ disable spice_vmc_write(ssize_t out, int len) "spice 
> wrottn %lu of requested %zd
>  disable spice_vmc_read(int bytes, int len) "spice read %lu of requested %zd"
>  disable spice_vmc_register_interface(void *scd) "spice vmc registered 
> interface %p"
>  disable spice_vmc_unregister_interface(void *scd) "spice vmc unregistered 
> interface %p"
> +
> +# hw/lm32_pic.c
> +disable lm32_pic_raise_irq(void) "Raise CPU interrupt"
> +disable lm32_pic_lower_irq(void) "Lower CPU interrupt"
> +disable lm32_pic_interrupt(int irq, int level) "Set IRQ%d %d"
> +disable lm32_pic_set_im(uint32_t im) "im 0x%08x"
> +disable lm32_pic_set_ip(uint32_t ip) "ip 0x%08x"
> +disable lm32_pic_get_im(uint32_t im) "im 0x%08x"
> +disable lm32_pic_get_ip(uint32_t ip) "ip 0x%08x"
> --
> 1.7.2.3
>
>
>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]