All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Andreas Färber" <afaerber@suse.de>
To: Peter Crosthwaite <peter.crosthwaite@xilinx.com>,
	qemu-devel@nongnu.org, peter.maydell@linaro.org
Cc: Markus Armbruster <armbru@redhat.com>
Subject: Re: [Qemu-devel] [PATCH arm-devs v4 3/4] hw/timer: Introduce ARM A9 Global Timer.
Date: Mon, 02 Dec 2013 13:28:51 +0100	[thread overview]
Message-ID: <529C7D03.4080109@suse.de> (raw)
In-Reply-To: <4918e89476b8da916be2964ec41578b50d569a37.1385969450.git.peter.crosthwaite@xilinx.com>

Am 02.12.2013 08:36, schrieb Peter Crosthwaite:
> The ARM A9 MPCore has a timer that is global to all CPUs in the mpcore.
> The timer is shared but each CPU has a private independent comparator
> and interrupt.
> 
> Based on version contributed by Francois LEGAL.
> 
> Signed-off-by: François LEGAL <devel@thom.fr.eu.org>
> [PC changes:
>  * New commit message
>  * Re-implemented as single timer model
>  * Fixed backwards counting issue in polled mode
>  * completed VMSD fields
>  * macroified magic numbers (and headerified reg definitions)
>  * split of as device-model-only patch

"off"

>  * use bitops for 64 bit register access
>  * Fixed auto increment mode to check condition properly
>  * general cleanup (names/style etc).
> ]
> Signed-off-by: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
> ---
> Changed sinve v3:
> Add seperate CONFIG_A9_GTIMER (PMM review)
> Changed since v2 (PMM - review):
> Refactored for container embedding
> Made frequency scaler consistent with mptimer
> Fixed missing VMSD ref_counter field
> Fixed missing gtb->inc reset
> Changed Memory region names
> Changed since v1:
> Added /*< private >*/ to struct definition.
> Pulled register definitions out into a header (AF review)
> SOB Francois LEGAL with PC changes indicated.
> 
>  default-configs/arm-softmmu.mak |   1 +
>  hw/timer/Makefile.objs          |   1 +
>  hw/timer/a9gtimer.c             | 369 ++++++++++++++++++++++++++++++++++++++++
>  include/hw/timer/a9gtimer.h     |  97 +++++++++++
>  4 files changed, 468 insertions(+)
>  create mode 100644 hw/timer/a9gtimer.c
>  create mode 100644 include/hw/timer/a9gtimer.h
> 
> diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
> index a555eef..e48f102 100644
> --- a/default-configs/arm-softmmu.mak
> +++ b/default-configs/arm-softmmu.mak
> @@ -41,6 +41,7 @@ CONFIG_ARM_GIC=y
>  CONFIG_ARM_GIC_KVM=$(CONFIG_KVM)
>  CONFIG_ARM_TIMER=y
>  CONFIG_ARM_MPTIMER=y
> +CONFIG_A9_GTIMER=y
>  CONFIG_PL011=y
>  CONFIG_PL022=y
>  CONFIG_PL031=y
> diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs
> index eca5905..3ae091c 100644
> --- a/hw/timer/Makefile.objs
> +++ b/hw/timer/Makefile.objs
> @@ -1,5 +1,6 @@
>  common-obj-$(CONFIG_ARM_TIMER) += arm_timer.o
>  common-obj-$(CONFIG_ARM_MPTIMER) += arm_mptimer.o
> +common-obj-$(CONFIG_A9_GTIMER) += a9gtimer.o
>  common-obj-$(CONFIG_CADENCE) += cadence_ttc.o
>  common-obj-$(CONFIG_DS1338) += ds1338.o
>  common-obj-$(CONFIG_HPET) += hpet.o
> diff --git a/hw/timer/a9gtimer.c b/hw/timer/a9gtimer.c
> new file mode 100644
> index 0000000..0f08c67
> --- /dev/null
> +++ b/hw/timer/a9gtimer.c
> @@ -0,0 +1,369 @@
> +/*
> + * Global peripheral timer block for ARM A9MP
> + *
> + * (C) 2013 Xilinx Inc.
> + *
> + * Written by François LEGAL
> + * Written by Peter Crosthwaite <peter.crosthwaite@xilinx.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version
> + * 2 of the License, or (at your option) any later version.
> + *
> + * This program 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 General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "hw/timer/a9gtimer.h"
> +#include "qemu/timer.h"
> +#include "qemu/bitops.h"
> +#include "qemu/log.h"
> +
> +#ifndef A9_GTIMER_ERR_DEBUG
> +#define A9_GTIMER_ERR_DEBUG 0
> +#endif
> +
> +#define DB_PRINT_L(level, ...) do { \
> +    if (A9_GTIMER_ERR_DEBUG > (level)) { \
> +        fprintf(stderr,  ": %s: ", __func__); \
> +        fprintf(stderr, ## __VA_ARGS__); \
> +    } \
> +} while (0);
> +
> +#define DB_PRINT(...) DB_PRINT_L(0, ## __VA_ARGS__)
> +
> +static inline int a9_gtimer_get_current_cpu(A9GTimerState *s)
> +{
> +    if (current_cpu->cpu_index >= s->num_cpu) {
> +        hw_error("arm_mptimer: num-cpu %d but this cpu is %d!\n",

Copy&paste?

> +                 s->num_cpu, current_cpu->cpu_index);
> +    }
> +    return current_cpu->cpu_index;
> +}
> +
> +static inline uint64_t a9_gtimer_get_conv(A9GTimerState *s)
> +{
> +    uint64_t prescale = extract32(s->control, R_CONTROL_PRESCALER_SHIFT,
> +                                  R_CONTROL_PRESCALER_LEN);
> +
> +    return (prescale + 1) * 10;
> +}
> +
> +static A9GTimerUpdate a9_gtimer_get_update(A9GTimerState *s)
> +{
> +    A9GTimerUpdate ret;
> +
> +    ret.now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> +    ret.new = s->ref_counter +
> +              (ret.now - s->cpu_ref_time) / a9_gtimer_get_conv(s);
> +    return ret;
> +}
> +
> +static void a9_gtimer_update(A9GTimerState *s, bool sync)
> +{
> +
> +    A9GTimerUpdate update = a9_gtimer_get_update(s);
> +    int i;
> +    int64_t next_cdiff = 0;
> +
> +    for (i = 0; i < s->num_cpu; ++i) {
> +        A9GTimerPerCPU *gtb = &s->per_cpu[i];
> +        int64_t cdiff = 0;
> +
> +        if ((s->control & R_CONTROL_TIMER_ENABLE) &&
> +                (gtb->control & R_CONTROL_COMP_ENABLE)) {
> +            /* R2p0+, where the compare function is >= */
> +            while (gtb->compare < update.new) {
> +                DB_PRINT("Compare event happened for CPU %d\n", i);
> +                gtb->status = 1;
> +                if (gtb->control & R_CONTROL_AUTO_INCREMENT) {
> +                    DB_PRINT("Auto incrementing timer compare by %" PRId32 "\n",
> +                             gtb->inc);
> +                    gtb->compare += gtb->inc;
> +                } else {
> +                    break;
> +                }
> +            }
> +            cdiff = (int64_t)gtb->compare - (int64_t)update.new + 1;
> +            if (cdiff > 0 && (cdiff < next_cdiff || !next_cdiff)) {
> +                next_cdiff = cdiff;
> +            }
> +        }
> +
> +        qemu_set_irq(gtb->irq,
> +                     gtb->status && (gtb->control & R_CONTROL_IRQ_ENABLE));
> +    }
> +
> +    timer_del(s->timer);
> +    if (next_cdiff) {
> +        DB_PRINT("scheduling qemu_timer to fire again in %"
> +                 PRIx64 " cycles\n", next_cdiff);
> +        timer_mod(s->timer, update.now + next_cdiff * a9_gtimer_get_conv(s));
> +    }
> +
> +    if (s->control & R_CONTROL_TIMER_ENABLE) {
> +        s->counter = update.new;
> +    }
> +
> +    if (sync) {
> +        s->cpu_ref_time = update.now;
> +        s->ref_counter = s->counter;
> +    }
> +}
> +
> +static void a9_gtimer_update_no_sync(void *opaque)
> +{
> +    A9GTimerState *s = A9_GTIMER(opaque);
> +
> +    return a9_gtimer_update(s, false);
> +}
> +
> +static uint64_t a9_gtimer_read(void *opaque, hwaddr addr, unsigned size)
> +{
> +    A9GTimerPerCPU *gtb = (A9GTimerPerCPU *)opaque;
> +    A9GTimerState *s = gtb->parent;
> +    A9GTimerUpdate update;
> +    uint64_t ret = 0;
> +    int shift = 0;
> +
> +    switch (addr) {
> +    case R_COUNTER_HI:
> +        shift = 32;
> +        /* fallthrough */
> +    case R_COUNTER_LO:
> +        update = a9_gtimer_get_update(s);
> +        ret = extract64(update.new, shift, 32);
> +        break;
> +    case R_CONTROL:
> +        ret = s->control | gtb->control;
> +        break;
> +    case R_INTERRUPT_STATUS:
> +        ret = gtb->status;
> +        break;
> +    case R_COMPARATOR_HI:
> +        shift = 32;
> +        /* fallthrough */
> +    case R_COMPARATOR_LO:
> +        ret = extract64(gtb->compare, shift, 32);
> +        break;
> +    case R_AUTO_INCREMENT:
> +        ret =  gtb->inc;
> +        break;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR, "bad a9gtimer register: %x\n",
> +                      (unsigned)addr);
> +        return 0;
> +    }
> +
> +    DB_PRINT("addr:%#x data:%#08" PRIx64 "\n", (unsigned)addr, ret);
> +    return ret;
> +}
> +
> +static void a9_gtimer_write(void *opaque, hwaddr addr, uint64_t value,
> +                            unsigned size)
> +{
> +    A9GTimerPerCPU *gtb = (A9GTimerPerCPU *)opaque;
> +    A9GTimerState *s = gtb->parent;
> +    int shift = 0;
> +
> +    DB_PRINT("addr:%#x data:%#08" PRIx64 "\n", (unsigned)addr, value);
> +
> +    switch (addr) {
> +    case R_COUNTER_HI:
> +        shift = 32;
> +        /* fallthrough */
> +    case R_COUNTER_LO:
> +        /*
> +         * Keep it simple - ARM docco explicitly says to disable timer before
> +         * modding it, so dont bother trying to do all the difficult on the fly
> +         * timer modifications - (if they even work in real hardware??).
> +         */
> +        if (s->control & R_CONTROL_TIMER_ENABLE) {
> +            qemu_log_mask(LOG_GUEST_ERROR, "Cannot mod running ARM gtimer\n");
> +            return;
> +        }
> +        s->counter = deposit64(s->counter, shift, 32, value);
> +        return;
> +    case R_CONTROL:
> +        a9_gtimer_update(s, (value ^ s->control) & R_CONTROL_NEEDS_SYNC);
> +        gtb->control = value & R_CONTROL_BANKED;
> +        s->control = value & ~R_CONTROL_BANKED;
> +        break;
> +    case R_INTERRUPT_STATUS:
> +        a9_gtimer_update(s, false);
> +        gtb->status &= ~value;
> +        break;
> +    case R_COMPARATOR_HI:
> +        shift = 32;
> +        /* fallthrough */
> +    case R_COMPARATOR_LO:
> +        a9_gtimer_update(s, false);
> +        gtb->compare = deposit64(gtb->compare, shift, 32, value);
> +        break;
> +    case R_AUTO_INCREMENT:
> +        gtb->inc = value;
> +        return;
> +    default:
> +        return;
> +    }
> +
> +    a9_gtimer_update(s, false);
> +}
> +
> +/* Wrapper functions to implement the "read global timer for
> + * the current CPU" memory regions.
> + */
> +static uint64_t a9_gtimer_this_read(void *opaque, hwaddr addr,
> +                                    unsigned size)
> +{
> +    A9GTimerState *s = A9_GTIMER(opaque);
> +    int id = a9_gtimer_get_current_cpu(s);
> +
> +    /* no \n so concatenates with message from read fn */
> +    DB_PRINT("CPU:%d:", id);
> +
> +    return a9_gtimer_read(&s->per_cpu[id], addr, size);
> +}
> +
> +static void a9_gtimer_this_write(void *opaque, hwaddr addr,
> +                                 uint64_t value, unsigned size)
> +{
> +    A9GTimerState *s = A9_GTIMER(opaque);
> +    int id = a9_gtimer_get_current_cpu(s);
> +
> +    /* no \n so concatentates with message from write fn */

"concatenates"

> +    DB_PRINT("CPU:%d:", id);
> +
> +    a9_gtimer_write(&s->per_cpu[id], addr, value, size);
> +}
> +
> +static const MemoryRegionOps a9_gtimer_this_ops = {
> +    .read = a9_gtimer_this_read,
> +    .write = a9_gtimer_this_write,
> +    .valid = {
> +        .min_access_size = 4,
> +        .max_access_size = 4,
> +    },
> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +};
> +
> +static const MemoryRegionOps a9_gtimer_ops = {
> +    .read = a9_gtimer_read,
> +    .write = a9_gtimer_write,
> +    .valid = {
> +        .min_access_size = 4,
> +        .max_access_size = 4,
> +    },
> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +};
> +
> +static void a9_gtimer_reset(DeviceState *dev)
> +{
> +    A9GTimerState *s = A9_GTIMER(dev);
> +    int i;
> +
> +    s->counter = 0;
> +    s->control = 0;
> +
> +    for (i = 0; i < s->num_cpu; i++) {
> +        A9GTimerPerCPU *gtb = &s->per_cpu[i];
> +
> +        gtb->control = 0;
> +        gtb->status = 0;
> +        gtb->compare = 0;
> +        gtb->inc = 0;
> +    }
> +    a9_gtimer_update(s, false);
> +}
> +
> +static void a9_gtimer_realize(DeviceState *dev, Error **errp)
> +{
> +    A9GTimerState *s = A9_GTIMER(dev);
> +    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
> +    int i;
> +
> +    if (s->num_cpu < 1 || s->num_cpu > A9_GTIMER_MAX_CPUS) {
> +        error_setg(errp, "%s: num-cpu must be between 1 and %d\n",
> +                   __func__, A9_GTIMER_MAX_CPUS);

return; missing.

> +    }
> +
> +    memory_region_init_io(&s->iomem, OBJECT(dev), &a9_gtimer_this_ops, s,
> +                          "a9gtimer shared", 0x20);
> +    sysbus_init_mmio(sbd, &s->iomem);
> +    s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, a9_gtimer_update_no_sync, s);
> +
> +    for (i = 0; i < s->num_cpu; i++) {
> +        A9GTimerPerCPU *gtb = &s->per_cpu[i];
> +
> +        gtb->parent = s;
> +        sysbus_init_irq(sbd, &gtb->irq);
> +        memory_region_init_io(&gtb->iomem, OBJECT(dev), &a9_gtimer_ops, gtb,
> +                              "a9gtimer per cpu", 0x20);
> +        sysbus_init_mmio(sbd, &gtb->iomem);
> +    }
> +}
> +
> +static const VMStateDescription vmstate_a9_gtimer_per_cpu = {
> +    .name = "arm.cortex-a9-global-timer.percpu",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT32(control, A9GTimerPerCPU),
> +        VMSTATE_UINT64(compare, A9GTimerPerCPU),
> +        VMSTATE_UINT32(status, A9GTimerPerCPU),
> +        VMSTATE_UINT32(inc, A9GTimerPerCPU),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static const VMStateDescription vmstate_a9_gtimer = {
> +    .name = "arm.cortex-a9-global-timer",
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_TIMER(timer, A9GTimerState),
> +        VMSTATE_UINT64(counter, A9GTimerState),
> +        VMSTATE_UINT64(ref_counter, A9GTimerState),
> +        VMSTATE_UINT64(cpu_ref_time, A9GTimerState),
> +        VMSTATE_STRUCT_VARRAY_UINT32(per_cpu, A9GTimerState, num_cpu,
> +                                     1, vmstate_a9_gtimer_per_cpu,
> +                                     A9GTimerPerCPU),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static Property a9_gtimer_properties[] = {
> +    DEFINE_PROP_UINT32("num-cpu", A9GTimerState, num_cpu, 0),
> +    DEFINE_PROP_END_OF_LIST()
> +};
> +
> +static void a9_gtimer_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->realize = a9_gtimer_realize;
> +    dc->vmsd = &vmstate_a9_gtimer;
> +    dc->reset = a9_gtimer_reset;
> +    dc->no_user = 1;

There is a series from Markus waiting on my review that renames and
investigates all uses of this field. Please explain why you are using it
(in form of a comment) or drop it. There's only a numeric property
above, so likely the latter.

On a general note, please be aware that use of HWADDR_PRIx is preferred
over the (unsigned) casts I'm seeing in this patch.

Andreas

> +    dc->props = a9_gtimer_properties;
> +}
> +
> +static const TypeInfo a9_gtimer_info = {
> +    .name          = TYPE_A9_GTIMER,
> +    .parent        = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(A9GTimerState),
> +    .class_init    = a9_gtimer_class_init,
> +};
> +
> +static void a9_gtimer_register_types(void)
> +{
> +    type_register_static(&a9_gtimer_info);
> +}
> +
> +type_init(a9_gtimer_register_types)
> diff --git a/include/hw/timer/a9gtimer.h b/include/hw/timer/a9gtimer.h
> new file mode 100644
> index 0000000..b88c02a
> --- /dev/null
> +++ b/include/hw/timer/a9gtimer.h
> @@ -0,0 +1,97 @@
> +/*
> + * Global peripheral timer block for ARM A9MP
> + *
> + * (C) 2013 Xilinx Inc.
> + *
> + * Written by François LEGAL
> + * Written by Peter Crosthwaite <peter.crosthwaite@xilinx.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version
> + * 2 of the License, or (at your option) any later version.
> + *
> + * This program 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 General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef HW_TIMER_A9_GTIMER_H_H
> +#define HW_TIMER_A9_GTIMER_H_H
> +
> +#include "hw/sysbus.h"
> +
> +#define A9_GTIMER_MAX_CPUS 4
> +
> +#define TYPE_A9_GTIMER "arm.cortex-a9-global-timer"
> +#define A9_GTIMER(obj) OBJECT_CHECK(A9GTimerState, (obj), TYPE_A9_GTIMER)
> +
> +#define R_COUNTER_LO                0x00
> +#define R_COUNTER_HI                0x04
> +
> +#define R_CONTROL                   0x08
> +#define R_CONTROL_TIMER_ENABLE      (1 << 0)
> +#define R_CONTROL_COMP_ENABLE       (1 << 1)
> +#define R_CONTROL_IRQ_ENABLE        (1 << 2)
> +#define R_CONTROL_AUTO_INCREMENT    (1 << 2)
> +#define R_CONTROL_PRESCALER_SHIFT   8
> +#define R_CONTROL_PRESCALER_LEN     8
> +#define R_CONTROL_PRESCALER_MASK    (((1 << R_CONTROL_PRESCALER_LEN) - 1) << \
> +                                     R_CONTROL_PRESCALER_SHIFT)
> +
> +#define R_CONTROL_BANKED            (R_CONTROL_COMP_ENABLE | \
> +                                     R_CONTROL_IRQ_ENABLE | \
> +                                     R_CONTROL_AUTO_INCREMENT)
> +#define R_CONTROL_NEEDS_SYNC        (R_CONTROL_TIMER_ENABLE | \
> +                                     R_CONTROL_PRESCALER_MASK)
> +
> +#define R_INTERRUPT_STATUS          0x0C
> +#define R_COMPARATOR_LO             0x10
> +#define R_COMPARATOR_HI             0x14
> +#define R_AUTO_INCREMENT            0x18
> +
> +typedef struct A9GTimerPerCPU A9GTimerPerCPU;
> +typedef struct A9GTimerState A9GTimerState;
> +
> +struct A9GTimerPerCPU {
> +    A9GTimerState *parent;
> +
> +    uint32_t control; /* only per cpu banked bits valid */
> +    uint64_t compare;
> +    uint32_t status;
> +    uint32_t inc;
> +
> +    MemoryRegion iomem;
> +    qemu_irq irq; /* PPI interrupts */
> +};
> +
> +struct A9GTimerState {
> +    /*< private >*/
> +    SysBusDevice parent_obj;
> +    /*< public >*/
> +
> +    MemoryRegion iomem;
> +    /* static props */
> +    uint32_t num_cpu;
> +
> +    QEMUTimer *timer;
> +
> +    uint64_t counter; /* current timer value */
> +
> +    uint64_t ref_counter;
> +    uint64_t cpu_ref_time; /* the cpu time as of last update of ref_counter */
> +    uint32_t control; /* only non per cpu banked bits valid */
> +
> +    A9GTimerPerCPU per_cpu[A9_GTIMER_MAX_CPUS];
> +};
> +
> +typedef struct A9GTimerUpdate {
> +    uint64_t now;
> +    uint64_t new;
> +} A9GTimerUpdate;
> +
> +#endif /* #ifdef HW_TIMER_A9_GTIMER_H_H */
> 


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

  reply	other threads:[~2013-12-02 12:29 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-12-02  7:34 [Qemu-devel] [PATCH arm-devs v4 0/4] A9 global timer + mpcore trivials Peter Crosthwaite
2013-12-02  7:35 ` [Qemu-devel] [PATCH arm-devs v4 1/4] cpu/a9mpcore: rename timerbusdev variable Peter Crosthwaite
2013-12-02  7:36 ` [Qemu-devel] [PATCH arm-devs v4 2/4] cpu/a9mpcore: reorder operations/declarations Peter Crosthwaite
2013-12-02  7:36 ` [Qemu-devel] [PATCH arm-devs v4 3/4] hw/timer: Introduce ARM A9 Global Timer Peter Crosthwaite
2013-12-02 12:28   ` Andreas Färber [this message]
2013-12-02 12:36     ` Peter Maydell
2013-12-02 12:59       ` Markus Armbruster
2013-12-02 13:05     ` Peter Maydell
2013-12-02  7:37 ` [Qemu-devel] [PATCH arm-devs v4 4/4] cpu/a9mpcore: Add " Peter Crosthwaite
2013-12-02 13:08   ` Andreas Färber
2013-12-02 13:21     ` Paolo Bonzini
2013-12-02 13:56       ` Andreas Färber
2013-12-02 11:58 ` [Qemu-devel] [PATCH arm-devs v4 0/4] A9 global timer + mpcore trivials Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=529C7D03.4080109@suse.de \
    --to=afaerber@suse.de \
    --cc=armbru@redhat.com \
    --cc=peter.crosthwaite@xilinx.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.