Fix arm sd warnings with latest kernel (bz #1091548)

Fix regression in CVE backport that affects openstack (thanks lbezdick)
This commit is contained in:
Cole Robinson 2014-04-29 14:09:00 -04:00
parent 0d3567f1ae
commit 7452f5d212
41 changed files with 1372 additions and 36 deletions

View File

@ -1,4 +1,4 @@
From 265b10ea4a26d30ef9d1e083a96b420d659a2705 Mon Sep 17 00:00:00 2001
From 78c951e761e8ce7b8503750bc0fc7ff4d70c4926 Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Fri, 28 Mar 2014 18:06:31 +0100
Subject: [PATCH] qcow2: Don't rely on free_cluster_index in
@ -35,8 +35,8 @@ Conflicts:
tests/qemu-iotests/080.out
---
block/qcow2-refcount.c | 72 ++++++++++++++++++++++++++------------------------
block/qcow2.c | 9 ++++---
2 files changed, 42 insertions(+), 39 deletions(-)
block/qcow2.c | 11 ++++----
2 files changed, 43 insertions(+), 40 deletions(-)
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 1308151..d784dd6 100644
@ -188,9 +188,18 @@ index 1308151..d784dd6 100644
}
diff --git a/block/qcow2.c b/block/qcow2.c
index 10bfaaf..6112859 100644
index 10bfaaf..5d45036 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1385,7 +1385,7 @@ static int qcow2_create2(const char *filename, int64_t total_size,
*/
BlockDriverState* bs;
QCowHeader *header;
- uint8_t* refcount_table;
+ uint64_t* refcount_table;
int ret;
ret = bdrv_create_file(filename, options);
@@ -1431,9 +1431,10 @@ static int qcow2_create2(const char *filename, int64_t total_size,
goto out;
}

View File

@ -1,4 +1,4 @@
From bcc20e42a05617dd18743d86950cdb2ad3d75602 Mon Sep 17 00:00:00 2001
From 4e2c1ea4da59e66a567f50a1d66e4cc110e5e496 Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Wed, 26 Mar 2014 13:05:49 +0100
Subject: [PATCH] qcow2: Avoid integer overflow in get_refcount (CVE-2014-0143)

View File

@ -1,4 +1,4 @@
From 26a8e469db49e98d805a502b01e1e46387a8098a Mon Sep 17 00:00:00 2001
From a8f7f240d8a02c7bebcdfd912001588c1422619f Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Wed, 26 Mar 2014 13:05:50 +0100
Subject: [PATCH] qcow2: Check new refcount table size on growth
@ -35,7 +35,7 @@ index 3e473bd..3cdcfb6 100644
uint64_t table_size = next_refcount_table_size(s, blocks_used + 1);
uint64_t last_table_size;
diff --git a/block/qcow2.c b/block/qcow2.c
index 6112859..4052c45 100644
index 5d45036..af0a45c 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -487,9 +487,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags)

View File

@ -1,4 +1,4 @@
From 85429611389df4beca593a2f2c49fde7bb26b2d4 Mon Sep 17 00:00:00 2001
From 26eabe580a600558dc45dd0fbe189c646349cf45 Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Wed, 26 Mar 2014 13:05:51 +0100
Subject: [PATCH] qcow2: Fix types in qcow2_alloc_clusters and

View File

@ -1,4 +1,4 @@
From 4acd1cde7a2d9809cb5a25039e47552831c00fb2 Mon Sep 17 00:00:00 2001
From 02b066b43aad381c755645a2cfe8779e14f2a720 Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Wed, 26 Mar 2014 13:05:52 +0100
Subject: [PATCH] qcow2: Protect against some integer overflows in bdrv_check

View File

@ -1,4 +1,4 @@
From 34fc1555df145e6cd75427240c38c5927825a4d4 Mon Sep 17 00:00:00 2001
From 42997635f38e1ba75d045c5d9771784f16ec2a8a Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Wed, 26 Mar 2014 13:05:53 +0100
Subject: [PATCH] qcow2: Fix new L1 table size check (CVE-2014-0143)

View File

@ -1,4 +1,4 @@
From 430e977c21f78dc0d2fa21c8b0cc8db0ed0936fd Mon Sep 17 00:00:00 2001
From d857c200d3f13cb812495fec48b0fb4da1bbdfe4 Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi <stefanha@redhat.com>
Date: Wed, 26 Mar 2014 13:05:54 +0100
Subject: [PATCH] dmg: coding style and indentation cleanup

View File

@ -1,4 +1,4 @@
From a4e71c7e314b03dc4dfad00db8daeb9bd3b50767 Mon Sep 17 00:00:00 2001
From 9498de028804a582535816f36abacf2f297ea592 Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi <stefanha@redhat.com>
Date: Wed, 26 Mar 2014 13:05:55 +0100
Subject: [PATCH] dmg: prevent out-of-bounds array access on terminator

View File

@ -1,4 +1,4 @@
From a3cbb678e63ee098936eee820a0bc9901d1c4406 Mon Sep 17 00:00:00 2001
From 7fe86d938be67ed6856c73985f4a1cf035a0399e Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi <stefanha@redhat.com>
Date: Wed, 26 Mar 2014 13:05:56 +0100
Subject: [PATCH] dmg: drop broken bdrv_pread() loop

View File

@ -1,4 +1,4 @@
From 4606e72cd258bcc9ae59828c47e7ed50925a6a98 Mon Sep 17 00:00:00 2001
From 62298cd0354f1dfa8fe14a611064f8fc5ed43f0c Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi <stefanha@redhat.com>
Date: Wed, 26 Mar 2014 13:05:57 +0100
Subject: [PATCH] dmg: use appropriate types when reading chunks

View File

@ -1,4 +1,4 @@
From c9e7ee21b717f0b88e8d03558e874abfcea0da3d Mon Sep 17 00:00:00 2001
From f2b6eff8aa04a6d5c6ac642e2991ddf7869bbde9 Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi <stefanha@redhat.com>
Date: Wed, 26 Mar 2014 13:05:58 +0100
Subject: [PATCH] dmg: sanitize chunk length and sectorcount (CVE-2014-0145)

View File

@ -1,4 +1,4 @@
From f9a7348f91b3d5fc9256d39b513d97ae74a4d601 Mon Sep 17 00:00:00 2001
From 0d669d4204fd80a65142aadc5363de811634ed05 Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi <stefanha@redhat.com>
Date: Wed, 26 Mar 2014 13:05:59 +0100
Subject: [PATCH] dmg: use uint64_t consistently for sectors and lengths

View File

@ -1,4 +1,4 @@
From 2e43f4147e40b8584d9816ec65a58fd80cded06b Mon Sep 17 00:00:00 2001
From e033dfba1292a0d345aaad7bc955ddc004d97c84 Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi <stefanha@redhat.com>
Date: Wed, 26 Mar 2014 13:06:00 +0100
Subject: [PATCH] dmg: prevent chunk buffer overflow (CVE-2014-0145)

View File

@ -1,4 +1,4 @@
From 176e7263b7b5bffba72675f3821a21904e9e4ab1 Mon Sep 17 00:00:00 2001
From f880e4459cd8ab58817730983b0cdaa514844f59 Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Wed, 26 Mar 2014 13:06:02 +0100
Subject: [PATCH] block: Limit request size (CVE-2014-0143)

View File

@ -1,4 +1,4 @@
From 56ffaa11b81f1a38282f2e78e8248fe24d4be37a Mon Sep 17 00:00:00 2001
From 342d5cf06f79a6d1de9575e8fb99ae714b43371c Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Wed, 26 Mar 2014 13:06:03 +0100
Subject: [PATCH] qcow2: Fix copy_sectors() with VM state

View File

@ -1,4 +1,4 @@
From a0188429fb211a2e6c54a4589fb516156caa6cba Mon Sep 17 00:00:00 2001
From e2871c69c209fe1df4478a82682d82c444c7136f Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Wed, 26 Mar 2014 13:06:04 +0100
Subject: [PATCH] qcow2: Fix NULL dereference in qcow2_open() error path
@ -23,7 +23,7 @@ Conflicts:
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/block/qcow2.c b/block/qcow2.c
index 4052c45..151cde8 100644
index af0a45c..c9beb01 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -515,9 +515,6 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags)

View File

@ -1,4 +1,4 @@
From c85b5240d01ae594864bb5c3f353cd8cf6333c3e Mon Sep 17 00:00:00 2001
From 87e8497708f3aec3f065aed5096b4ac32b01f17e Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Wed, 26 Mar 2014 13:06:05 +0100
Subject: [PATCH] qcow2: Fix L1 allocation size in qcow2_snapshot_load_tmp()

View File

@ -1,4 +1,4 @@
From ec5f34cfe586f6761d490e8e3b394f98fead3cf6 Mon Sep 17 00:00:00 2001
From 9e4cc665c88e8dd6c1986c49ccdc66ce93e9571c Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Wed, 26 Mar 2014 13:06:06 +0100
Subject: [PATCH] qcow2: Check maximum L1 size in qcow2_snapshot_load_tmp()
@ -37,7 +37,7 @@ index dc8736a..d2c956c 100644
new_l1_table = g_malloc0(align_offset(new_l1_bytes, 512));
diff --git a/block/qcow2.c b/block/qcow2.c
index 151cde8..253d8c0 100644
index c9beb01..5dfd5ec 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -516,9 +516,7 @@ static int qcow2_open(BlockDriverState *bs, QDict *options, int flags)

View File

@ -1,4 +1,4 @@
From b4cdeb9eb047ca5faedb853564fe560e383bda93 Mon Sep 17 00:00:00 2001
From 51b8dca866a1b77a9803ee3b56e059f8e7795dd8 Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Wed, 26 Mar 2014 13:06:07 +0100
Subject: [PATCH] qcow2: Limit snapshot table size

View File

@ -1,4 +1,4 @@
From 2a1cf454ea9a9fb4a6a7ad0fa51becd2090279a9 Mon Sep 17 00:00:00 2001
From 7b9628e6facd00f8ab8a042dd52dba377aceb080 Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Wed, 26 Mar 2014 13:06:08 +0100
Subject: [PATCH] parallels: Fix catalog size integer overflow (CVE-2014-0143)

View File

@ -1,4 +1,4 @@
From 100635f1b07d0a3c2ea4045fa374c0ce0cd176bf Mon Sep 17 00:00:00 2001
From 09c235dc7edf8c360a92f7d004468ed2d380d5e5 Mon Sep 17 00:00:00 2001
From: Kevin Wolf <kwolf@redhat.com>
Date: Wed, 26 Mar 2014 13:06:09 +0100
Subject: [PATCH] parallels: Sanity check for s->tracks (CVE-2014-0142)

View File

@ -1,4 +1,4 @@
From f1af654ef6ff248d17514f3bfd4681c884e8c3f5 Mon Sep 17 00:00:00 2001
From 9694b35ea442e1ac2bcb72abe4f7dcc5f0542028 Mon Sep 17 00:00:00 2001
From: "Michael S. Tsirkin" <mst@redhat.com>
Date: Fri, 11 Apr 2014 15:18:08 +0300
Subject: [PATCH] virtio-net: fix guest-triggerable buffer overrun

View File

@ -1,4 +1,4 @@
From bf10c8ab124164a3c47ee7e225df27f444191d26 Mon Sep 17 00:00:00 2001
From 08b35da4cbdbb1e1ab3aec27ab5ea7c9801a90e9 Mon Sep 17 00:00:00 2001
From: Dmitry Fleytman <dmitry@daynix.com>
Date: Fri, 4 Apr 2014 12:45:19 +0300
Subject: [PATCH] vmxnet3: validate interrupt indices coming from guest

View File

@ -1,4 +1,4 @@
From c45d9cbc1e915c9ed4c9c4ff9c12e3fb60cf7428 Mon Sep 17 00:00:00 2001
From da02c5b666de7dc52a97d9d9c914763285318f50 Mon Sep 17 00:00:00 2001
From: Dmitry Fleytman <dmitry@daynix.com>
Date: Fri, 4 Apr 2014 12:45:20 +0300
Subject: [PATCH] vmxnet3: validate queues configuration coming from guest

View File

@ -1,4 +1,4 @@
From 35dde61029a4c84b34f15cebc04b939f0e54f870 Mon Sep 17 00:00:00 2001
From acea806434d8d17ec72fd0cc091fd78370ae53f7 Mon Sep 17 00:00:00 2001
From: Dmitry Fleytman <dmitry@daynix.com>
Date: Fri, 4 Apr 2014 12:45:21 +0300
Subject: [PATCH] vmxnet3: validate interrupt indices read on migration

View File

@ -1,4 +1,4 @@
From b052d97f6c26ab7a24de40c3486a465816504016 Mon Sep 17 00:00:00 2001
From 0b10529e68cce027735be048044a414379f27568 Mon Sep 17 00:00:00 2001
From: Dmitry Fleytman <dmitry@daynix.com>
Date: Fri, 4 Apr 2014 12:45:22 +0300
Subject: [PATCH] vmxnet3: validate queues configuration read on migration

View File

@ -1,4 +1,4 @@
From 1eea31fa88d954546c627ea9c43a1c2fd3222cf6 Mon Sep 17 00:00:00 2001
From 282af5229f9eb38a322034289648619c4c780fd0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Beno=C3=AEt=20Canet?= <benoit.canet@irqsave.net>
Date: Sat, 12 Apr 2014 22:59:50 +0200
Subject: [PATCH] ide: Correct improper smart self test counter reset in ide

View File

@ -1,4 +1,4 @@
From 29952434a3c7b41137241b6905cf4df2f43a357d Mon Sep 17 00:00:00 2001
From 436055f9403c0134cdd333a9c3acef0c394d2102 Mon Sep 17 00:00:00 2001
From: Peter Crosthwaite <peter.crosthwaite@xilinx.com>
Date: Mon, 10 Feb 2014 22:49:35 -0800
Subject: [PATCH] char/serial: Fix emptyness check

View File

@ -1,4 +1,4 @@
From d1f1edc49f537fe9043fad52e06d6829cbadabe1 Mon Sep 17 00:00:00 2001
From dde12083417266a1a723c9a491c26258f837963f Mon Sep 17 00:00:00 2001
From: Don Slutz <dslutz@verizon.com>
Date: Tue, 18 Mar 2014 12:29:34 -0400
Subject: [PATCH] char/serial: Fix emptyness handling

View File

@ -0,0 +1,35 @@
From ccf50e25b0c111f58be8c2084220410dd2a7e22a Mon Sep 17 00:00:00 2001
From: Christoffer Dall <christoffer.dall@linaro.org>
Date: Fri, 20 Sep 2013 20:35:06 +0100
Subject: [PATCH] vmstate: Add uint32 2D-array support
Add support for saving VMState of 2D arrays of uint32 values.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit a1b1d277cdaac98f25be249e7819aac781a35530)
---
include/migration/vmstate.h | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
index 1c31b5d..e5538c7 100644
--- a/include/migration/vmstate.h
+++ b/include/migration/vmstate.h
@@ -633,9 +633,15 @@ extern const VMStateInfo vmstate_info_bitmap;
#define VMSTATE_UINT32_ARRAY_V(_f, _s, _n, _v) \
VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_uint32, uint32_t)
+#define VMSTATE_UINT32_2DARRAY_V(_f, _s, _n1, _n2, _v) \
+ VMSTATE_2DARRAY(_f, _s, _n1, _n2, _v, vmstate_info_uint32, uint32_t)
+
#define VMSTATE_UINT32_ARRAY(_f, _s, _n) \
VMSTATE_UINT32_ARRAY_V(_f, _s, _n, 0)
+#define VMSTATE_UINT32_2DARRAY(_f, _s, _n1, _n2) \
+ VMSTATE_UINT32_2DARRAY_V(_f, _s, _n1, _n2, 0)
+
#define VMSTATE_UINT64_ARRAY_V(_f, _s, _n, _v) \
VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_uint64, uint64_t)

View File

@ -0,0 +1,313 @@
From b7ad87a31916871d523a15981c658a45a6e44b40 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andreas=20F=C3=A4rber?= <afaerber@suse.de>
Date: Tue, 23 Jul 2013 03:37:49 +0200
Subject: [PATCH] arm_gic: Extract headers hw/intc/arm_gic{,_common}.h
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Rename NCPU to GIC_NCPU and move GICState away from gic_internal.h.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Andreas Färber <afaerber@suse.de>
(cherry picked from commit 83728796ad3f2ce7d6162c1cb894528b12915646)
---
hw/intc/arm_gic_common.c | 18 ++++----
hw/intc/gic_internal.h | 80 +---------------------------------
include/hw/intc/arm_gic.h | 42 ++++++++++++++++++
include/hw/intc/arm_gic_common.h | 92 ++++++++++++++++++++++++++++++++++++++++
4 files changed, 145 insertions(+), 87 deletions(-)
create mode 100644 include/hw/intc/arm_gic.h
create mode 100644 include/hw/intc/arm_gic_common.h
diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c
index 709b5c2..c765850 100644
--- a/hw/intc/arm_gic_common.c
+++ b/hw/intc/arm_gic_common.c
@@ -64,17 +64,17 @@ static const VMStateDescription vmstate_gic = {
.post_load = gic_post_load,
.fields = (VMStateField[]) {
VMSTATE_BOOL(enabled, GICState),
- VMSTATE_BOOL_ARRAY(cpu_enabled, GICState, NCPU),
+ VMSTATE_BOOL_ARRAY(cpu_enabled, GICState, GIC_NCPU),
VMSTATE_STRUCT_ARRAY(irq_state, GICState, GIC_MAXIRQ, 1,
vmstate_gic_irq_state, gic_irq_state),
VMSTATE_UINT8_ARRAY(irq_target, GICState, GIC_MAXIRQ),
- VMSTATE_UINT8_2DARRAY(priority1, GICState, GIC_INTERNAL, NCPU),
+ VMSTATE_UINT8_2DARRAY(priority1, GICState, GIC_INTERNAL, GIC_NCPU),
VMSTATE_UINT8_ARRAY(priority2, GICState, GIC_MAXIRQ - GIC_INTERNAL),
- VMSTATE_UINT16_2DARRAY(last_active, GICState, GIC_MAXIRQ, NCPU),
- VMSTATE_UINT16_ARRAY(priority_mask, GICState, NCPU),
- VMSTATE_UINT16_ARRAY(running_irq, GICState, NCPU),
- VMSTATE_UINT16_ARRAY(running_priority, GICState, NCPU),
- VMSTATE_UINT16_ARRAY(current_pending, GICState, NCPU),
+ VMSTATE_UINT16_2DARRAY(last_active, GICState, GIC_MAXIRQ, GIC_NCPU),
+ VMSTATE_UINT16_ARRAY(priority_mask, GICState, GIC_NCPU),
+ VMSTATE_UINT16_ARRAY(running_irq, GICState, GIC_NCPU),
+ VMSTATE_UINT16_ARRAY(running_priority, GICState, GIC_NCPU),
+ VMSTATE_UINT16_ARRAY(current_pending, GICState, GIC_NCPU),
VMSTATE_END_OF_LIST()
}
};
@@ -84,9 +84,9 @@ static void arm_gic_common_realize(DeviceState *dev, Error **errp)
GICState *s = ARM_GIC_COMMON(dev);
int num_irq = s->num_irq;
- if (s->num_cpu > NCPU) {
+ if (s->num_cpu > GIC_NCPU) {
error_setg(errp, "requested %u CPUs exceeds GIC maximum %d",
- s->num_cpu, NCPU);
+ s->num_cpu, GIC_NCPU);
return;
}
s->num_irq += GIC_BASE_IRQ;
diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h
index 1426437..3989fd1 100644
--- a/hw/intc/gic_internal.h
+++ b/hw/intc/gic_internal.h
@@ -21,16 +21,9 @@
#ifndef QEMU_ARM_GIC_INTERNAL_H
#define QEMU_ARM_GIC_INTERNAL_H
-#include "hw/sysbus.h"
+#include "hw/intc/arm_gic.h"
-/* Maximum number of possible interrupts, determined by the GIC architecture */
-#define GIC_MAXIRQ 1020
-/* First 32 are private to each CPU (SGIs and PPIs). */
-#define GIC_INTERNAL 32
-/* Maximum number of possible CPU interfaces, determined by GIC architecture */
-#define NCPU 8
-
-#define ALL_CPU_MASK ((unsigned)(((1 << NCPU) - 1)))
+#define ALL_CPU_MASK ((unsigned)(((1 << GIC_NCPU) - 1)))
/* The NVIC has 16 internal vectors. However these are not exposed
through the normal GIC interface. */
@@ -59,48 +52,6 @@
s->priority2[(irq) - GIC_INTERNAL])
#define GIC_TARGET(irq) s->irq_target[irq]
-typedef struct gic_irq_state {
- /* The enable bits are only banked for per-cpu interrupts. */
- uint8_t enabled;
- uint8_t pending;
- uint8_t active;
- uint8_t level;
- bool model; /* 0 = N:N, 1 = 1:N */
- bool trigger; /* nonzero = edge triggered. */
-} gic_irq_state;
-
-typedef struct GICState {
- /*< private >*/
- SysBusDevice parent_obj;
- /*< public >*/
-
- qemu_irq parent_irq[NCPU];
- bool enabled;
- bool cpu_enabled[NCPU];
-
- gic_irq_state irq_state[GIC_MAXIRQ];
- uint8_t irq_target[GIC_MAXIRQ];
- uint8_t priority1[GIC_INTERNAL][NCPU];
- uint8_t priority2[GIC_MAXIRQ - GIC_INTERNAL];
- uint16_t last_active[GIC_MAXIRQ][NCPU];
-
- uint16_t priority_mask[NCPU];
- uint16_t running_irq[NCPU];
- uint16_t running_priority[NCPU];
- uint16_t current_pending[NCPU];
-
- uint32_t num_cpu;
-
- MemoryRegion iomem; /* Distributor */
- /* This is just so we can have an opaque pointer which identifies
- * both this GIC and which CPU interface we should be accessing.
- */
- struct GICState *backref[NCPU];
- MemoryRegion cpuiomem[NCPU+1]; /* CPU interfaces */
- uint32_t num_irq;
- uint32_t revision;
-} GICState;
-
/* The special cases for the revision property: */
#define REV_11MPCORE 0
#define REV_NVIC 0xffffffff
@@ -111,31 +62,4 @@ void gic_complete_irq(GICState *s, int cpu, int irq);
void gic_update(GICState *s);
void gic_init_irqs_and_distributor(GICState *s, int num_irq);
-#define TYPE_ARM_GIC_COMMON "arm_gic_common"
-#define ARM_GIC_COMMON(obj) \
- OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC_COMMON)
-#define ARM_GIC_COMMON_CLASS(klass) \
- OBJECT_CLASS_CHECK(ARMGICCommonClass, (klass), TYPE_ARM_GIC_COMMON)
-#define ARM_GIC_COMMON_GET_CLASS(obj) \
- OBJECT_GET_CLASS(ARMGICCommonClass, (obj), TYPE_ARM_GIC_COMMON)
-
-typedef struct ARMGICCommonClass {
- SysBusDeviceClass parent_class;
- void (*pre_save)(GICState *s);
- void (*post_load)(GICState *s);
-} ARMGICCommonClass;
-
-#define TYPE_ARM_GIC "arm_gic"
-#define ARM_GIC(obj) \
- OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC)
-#define ARM_GIC_CLASS(klass) \
- OBJECT_CLASS_CHECK(ARMGICClass, (klass), TYPE_ARM_GIC)
-#define ARM_GIC_GET_CLASS(obj) \
- OBJECT_GET_CLASS(ARMGICClass, (obj), TYPE_ARM_GIC)
-
-typedef struct ARMGICClass {
- ARMGICCommonClass parent_class;
- DeviceRealize parent_realize;
-} ARMGICClass;
-
#endif /* !QEMU_ARM_GIC_INTERNAL_H */
diff --git a/include/hw/intc/arm_gic.h b/include/hw/intc/arm_gic.h
new file mode 100644
index 0000000..0971e37
--- /dev/null
+++ b/include/hw/intc/arm_gic.h
@@ -0,0 +1,42 @@
+/*
+ * ARM GIC support
+ *
+ * Copyright (c) 2012 Linaro Limited
+ * Written by Peter Maydell
+ *
+ * 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_ARM_GIC_H
+#define HW_ARM_GIC_H
+
+#include "arm_gic_common.h"
+
+#define TYPE_ARM_GIC "arm_gic"
+#define ARM_GIC(obj) \
+ OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC)
+#define ARM_GIC_CLASS(klass) \
+ OBJECT_CLASS_CHECK(ARMGICClass, (klass), TYPE_ARM_GIC)
+#define ARM_GIC_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(ARMGICClass, (obj), TYPE_ARM_GIC)
+
+typedef struct ARMGICClass {
+ /*< private >*/
+ ARMGICCommonClass parent_class;
+ /*< public >*/
+
+ DeviceRealize parent_realize;
+} ARMGICClass;
+
+#endif
diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h
new file mode 100644
index 0000000..4f381bd
--- /dev/null
+++ b/include/hw/intc/arm_gic_common.h
@@ -0,0 +1,92 @@
+/*
+ * ARM GIC support
+ *
+ * Copyright (c) 2012 Linaro Limited
+ * Written by Peter Maydell
+ *
+ * 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_ARM_GIC_COMMON_H
+#define HW_ARM_GIC_COMMON_H
+
+#include "hw/sysbus.h"
+
+/* Maximum number of possible interrupts, determined by the GIC architecture */
+#define GIC_MAXIRQ 1020
+/* First 32 are private to each CPU (SGIs and PPIs). */
+#define GIC_INTERNAL 32
+/* Maximum number of possible CPU interfaces, determined by GIC architecture */
+#define GIC_NCPU 8
+
+typedef struct gic_irq_state {
+ /* The enable bits are only banked for per-cpu interrupts. */
+ uint8_t enabled;
+ uint8_t pending;
+ uint8_t active;
+ uint8_t level;
+ bool model; /* 0 = N:N, 1 = 1:N */
+ bool trigger; /* nonzero = edge triggered. */
+} gic_irq_state;
+
+typedef struct GICState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
+ qemu_irq parent_irq[GIC_NCPU];
+ bool enabled;
+ bool cpu_enabled[GIC_NCPU];
+
+ gic_irq_state irq_state[GIC_MAXIRQ];
+ uint8_t irq_target[GIC_MAXIRQ];
+ uint8_t priority1[GIC_INTERNAL][GIC_NCPU];
+ uint8_t priority2[GIC_MAXIRQ - GIC_INTERNAL];
+ uint16_t last_active[GIC_MAXIRQ][GIC_NCPU];
+
+ uint16_t priority_mask[GIC_NCPU];
+ uint16_t running_irq[GIC_NCPU];
+ uint16_t running_priority[GIC_NCPU];
+ uint16_t current_pending[GIC_NCPU];
+
+ uint32_t num_cpu;
+
+ MemoryRegion iomem; /* Distributor */
+ /* This is just so we can have an opaque pointer which identifies
+ * both this GIC and which CPU interface we should be accessing.
+ */
+ struct GICState *backref[GIC_NCPU];
+ MemoryRegion cpuiomem[GIC_NCPU + 1]; /* CPU interfaces */
+ uint32_t num_irq;
+ uint32_t revision;
+} GICState;
+
+#define TYPE_ARM_GIC_COMMON "arm_gic_common"
+#define ARM_GIC_COMMON(obj) \
+ OBJECT_CHECK(GICState, (obj), TYPE_ARM_GIC_COMMON)
+#define ARM_GIC_COMMON_CLASS(klass) \
+ OBJECT_CLASS_CHECK(ARMGICCommonClass, (klass), TYPE_ARM_GIC_COMMON)
+#define ARM_GIC_COMMON_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(ARMGICCommonClass, (obj), TYPE_ARM_GIC_COMMON)
+
+typedef struct ARMGICCommonClass {
+ /*< private >*/
+ SysBusDeviceClass parent_class;
+ /*< public >*/
+
+ void (*pre_save)(GICState *s);
+ void (*post_load)(GICState *s);
+} ARMGICCommonClass;
+
+#endif

View File

@ -0,0 +1,125 @@
From f81cfc1c2ec7e20c86656784b28f27b46868f71e Mon Sep 17 00:00:00 2001
From: Christoffer Dall <christoffer.dall@linaro.org>
Date: Fri, 20 Dec 2013 22:09:32 -0800
Subject: [PATCH] arm_gic: Rename GIC_X_TRIGGER to GIC_X_EDGE_TRIGGER
TRIGGER can really mean mean anything (e.g. was it triggered, is it
level-triggered, is it edge-triggered, etc.). Rename to EDGE_TRIGGER to
make the code comprehensible without looking up the data structure.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Message-id: 1387606179-22709-2-git-send-email-christoffer.dall@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 04050c5c6aa6f9c086a63a30b182b996fb2d3d02)
---
hw/intc/arm_gic.c | 12 ++++++------
hw/intc/arm_gic_common.c | 4 ++--
hw/intc/gic_internal.h | 6 +++---
include/hw/intc/arm_gic_common.h | 2 +-
4 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index d431b7a..27c258a 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -128,7 +128,7 @@ static void gic_set_irq(void *opaque, int irq, int level)
if (level) {
GIC_SET_LEVEL(irq, cm);
- if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq, cm)) {
+ if (GIC_TEST_EDGE_TRIGGER(irq) || GIC_TEST_ENABLED(irq, cm)) {
DPRINTF("Set %d pending mask %x\n", irq, target);
GIC_SET_PENDING(irq, target);
}
@@ -188,7 +188,7 @@ void gic_complete_irq(GICState *s, int cpu, int irq)
return; /* No active IRQ. */
/* Mark level triggered interrupts as pending if they are still
raised. */
- if (!GIC_TEST_TRIGGER(irq) && GIC_TEST_ENABLED(irq, cm)
+ if (!GIC_TEST_EDGE_TRIGGER(irq) && GIC_TEST_ENABLED(irq, cm)
&& GIC_TEST_LEVEL(irq, cm) && (GIC_TARGET(irq) & cm) != 0) {
DPRINTF("Set %d pending mask %x\n", irq, cm);
GIC_SET_PENDING(irq, cm);
@@ -311,7 +311,7 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset)
for (i = 0; i < 4; i++) {
if (GIC_TEST_MODEL(irq + i))
res |= (1 << (i * 2));
- if (GIC_TEST_TRIGGER(irq + i))
+ if (GIC_TEST_EDGE_TRIGGER(irq + i))
res |= (2 << (i * 2));
}
} else if (offset < 0xfe0) {
@@ -386,7 +386,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
/* If a raised level triggered IRQ enabled then mark
is as pending. */
if (GIC_TEST_LEVEL(irq + i, mask)
- && !GIC_TEST_TRIGGER(irq + i)) {
+ && !GIC_TEST_EDGE_TRIGGER(irq + i)) {
DPRINTF("Set %d pending mask %x\n", irq + i, mask);
GIC_SET_PENDING(irq + i, mask);
}
@@ -478,9 +478,9 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
GIC_CLEAR_MODEL(irq + i);
}
if (value & (2 << (i * 2))) {
- GIC_SET_TRIGGER(irq + i);
+ GIC_SET_EDGE_TRIGGER(irq + i);
} else {
- GIC_CLEAR_TRIGGER(irq + i);
+ GIC_CLEAR_EDGE_TRIGGER(irq + i);
}
}
} else {
diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c
index c765850..710607b 100644
--- a/hw/intc/arm_gic_common.c
+++ b/hw/intc/arm_gic_common.c
@@ -51,7 +51,7 @@ static const VMStateDescription vmstate_gic_irq_state = {
VMSTATE_UINT8(active, gic_irq_state),
VMSTATE_UINT8(level, gic_irq_state),
VMSTATE_BOOL(model, gic_irq_state),
- VMSTATE_BOOL(trigger, gic_irq_state),
+ VMSTATE_BOOL(edge_trigger, gic_irq_state),
VMSTATE_END_OF_LIST()
}
};
@@ -126,7 +126,7 @@ static void arm_gic_common_reset(DeviceState *dev)
}
for (i = 0; i < 16; i++) {
GIC_SET_ENABLED(i, ALL_CPU_MASK);
- GIC_SET_TRIGGER(i);
+ GIC_SET_EDGE_TRIGGER(i);
}
if (s->num_cpu == 1) {
/* For uniprocessor GICs all interrupts always target the sole CPU */
diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h
index 3989fd1..efac78d 100644
--- a/hw/intc/gic_internal.h
+++ b/hw/intc/gic_internal.h
@@ -44,9 +44,9 @@
#define GIC_SET_LEVEL(irq, cm) s->irq_state[irq].level = (cm)
#define GIC_CLEAR_LEVEL(irq, cm) s->irq_state[irq].level &= ~(cm)
#define GIC_TEST_LEVEL(irq, cm) ((s->irq_state[irq].level & (cm)) != 0)
-#define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = true
-#define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = false
-#define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger
+#define GIC_SET_EDGE_TRIGGER(irq) s->irq_state[irq].edge_trigger = true
+#define GIC_CLEAR_EDGE_TRIGGER(irq) s->irq_state[irq].edge_trigger = false
+#define GIC_TEST_EDGE_TRIGGER(irq) (s->irq_state[irq].edge_trigger)
#define GIC_GET_PRIORITY(irq, cpu) (((irq) < GIC_INTERNAL) ? \
s->priority1[irq][cpu] : \
s->priority2[(irq) - GIC_INTERNAL])
diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h
index 4f381bd..0d232df 100644
--- a/include/hw/intc/arm_gic_common.h
+++ b/include/hw/intc/arm_gic_common.h
@@ -37,7 +37,7 @@ typedef struct gic_irq_state {
uint8_t active;
uint8_t level;
bool model; /* 0 = N:N, 1 = 1:N */
- bool trigger; /* nonzero = edge triggered. */
+ bool edge_trigger; /* true: edge-triggered, false: level-triggered */
} gic_irq_state;
typedef struct GICState {

View File

@ -0,0 +1,63 @@
From 517ca103f039a560487d416359ef4c9338cbd833 Mon Sep 17 00:00:00 2001
From: Christoffer Dall <christoffer.dall@linaro.org>
Date: Fri, 20 Dec 2013 22:09:33 -0800
Subject: [PATCH] hw: arm_gic: Introduce gic_set_priority function
To make the code slightly cleaner to look at and make the save/restore
code easier to understand, introduce this function to set the priority of
interrupts.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Message-id: 1387606179-22709-3-git-send-email-christoffer.dall@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 9df90ad078ec782d1339bd6879b6ea117f9759f7)
---
hw/intc/arm_gic.c | 15 ++++++++++-----
hw/intc/gic_internal.h | 1 +
2 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index 27c258a..6c59650 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -168,6 +168,15 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu)
return new_irq;
}
+void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val)
+{
+ if (irq < GIC_INTERNAL) {
+ s->priority1[irq][cpu] = val;
+ } else {
+ s->priority2[(irq) - GIC_INTERNAL] = val;
+ }
+}
+
void gic_complete_irq(GICState *s, int cpu, int irq)
{
int update = 0;
@@ -443,11 +452,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
irq = (offset - 0x400) + GIC_BASE_IRQ;
if (irq >= s->num_irq)
goto bad_reg;
- if (irq < GIC_INTERNAL) {
- s->priority1[irq][cpu] = value;
- } else {
- s->priority2[irq - GIC_INTERNAL] = value;
- }
+ gic_set_priority(s, cpu, irq, value);
} else if (offset < 0xc00) {
/* Interrupt CPU Target. RAZ/WI on uniprocessor GICs, with the
* annoying exception of the 11MPCore's GIC.
diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h
index efac78d..8c02d58 100644
--- a/hw/intc/gic_internal.h
+++ b/hw/intc/gic_internal.h
@@ -61,5 +61,6 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu);
void gic_complete_irq(GICState *s, int cpu, int irq);
void gic_update(GICState *s);
void gic_init_irqs_and_distributor(GICState *s, int num_irq);
+void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val);
#endif /* !QEMU_ARM_GIC_INTERNAL_H */

View File

@ -0,0 +1,71 @@
From 20b9341d38dc1882aef9fea3dcd3f4981c1c61b4 Mon Sep 17 00:00:00 2001
From: Christoffer Dall <christoffer.dall@linaro.org>
Date: Fri, 31 Jan 2014 14:47:38 +0000
Subject: [PATCH] arm_gic: Introduce define for GIC_NR_SGIS
Instead of hardcoding 16 various places in the code, use a define to
make it more clear what is going on.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 41ab7b55108e2699e7c2e77788465cb52a0b2c08)
---
hw/intc/arm_gic.c | 17 +++++++++++------
include/hw/intc/arm_gic_common.h | 1 +
2 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index 6c59650..0ce11ac 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -380,8 +380,10 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;
if (irq >= s->num_irq)
goto bad_reg;
- if (irq < 16)
- value = 0xff;
+ if (irq < GIC_NR_SGIS) {
+ value = 0xff;
+ }
+
for (i = 0; i < 8; i++) {
if (value & (1 << i)) {
int mask =
@@ -406,8 +408,10 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;
if (irq >= s->num_irq)
goto bad_reg;
- if (irq < 16)
- value = 0;
+ if (irq < GIC_NR_SGIS) {
+ value = 0;
+ }
+
for (i = 0; i < 8; i++) {
if (value & (1 << i)) {
int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
@@ -423,8 +427,9 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;
if (irq >= s->num_irq)
goto bad_reg;
- if (irq < 16)
- irq = 0;
+ if (irq < GIC_NR_SGIS) {
+ irq = 0;
+ }
for (i = 0; i < 8; i++) {
if (value & (1 << i)) {
diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h
index 0d232df..8a2aa00 100644
--- a/include/hw/intc/arm_gic_common.h
+++ b/include/hw/intc/arm_gic_common.h
@@ -27,6 +27,7 @@
#define GIC_MAXIRQ 1020
/* First 32 are private to each CPU (SGIs and PPIs). */
#define GIC_INTERNAL 32
+#define GIC_NR_SGIS 16
/* Maximum number of possible CPU interfaces, determined by GIC architecture */
#define GIC_NCPU 8

View File

@ -0,0 +1,40 @@
From 0b838da99dfef17beaa843219d59c0646d857b2f Mon Sep 17 00:00:00 2001
From: Christoffer Dall <christoffer.dall@linaro.org>
Date: Fri, 31 Jan 2014 14:47:38 +0000
Subject: [PATCH] arm_gic: Fix GICD_ICPENDR and GICD_ISPENDR writes
Fix two bugs that would allow changing the state of SGIs through the
ICPENDR and ISPENDRs.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 5b0adce156216fb24dcc5f1683e8b686f3793fff)
---
hw/intc/arm_gic.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index 0ce11ac..62153fd 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -428,7 +428,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
if (irq >= s->num_irq)
goto bad_reg;
if (irq < GIC_NR_SGIS) {
- irq = 0;
+ value = 0;
}
for (i = 0; i < 8; i++) {
@@ -441,6 +441,10 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;
if (irq >= s->num_irq)
goto bad_reg;
+ if (irq < GIC_NR_SGIS) {
+ value = 0;
+ }
+
for (i = 0; i < 8; i++) {
/* ??? This currently clears the pending bit for all CPUs, even
for per-CPU interrupts. It's unclear whether this is the

View File

@ -0,0 +1,197 @@
From 46d5faeb5f937680b60109ba31a80e2d9065c800 Mon Sep 17 00:00:00 2001
From: Christoffer Dall <christoffer.dall@linaro.org>
Date: Mon, 18 Nov 2013 20:32:00 -0800
Subject: [PATCH] arm_gic: Fix GIC pending behavior
The existing implementation of the pending behavior in gic_set_irq,
gic_complete_irq, and the distributor pending set/clear registers does
not follow the semantics of the GICv2.0 specs, but may implement the
11MPCore support. Therefore, maintain the existing semantics for
11MPCore and v7M NVIC and change the behavior to be in accordance with
the GICv2.0 specs for "generic implementations" (s->revision == 1 ||
s->revision == 2).
Generic implementations distinguish between setting a level-triggered
interrupt pending through writes to the GICD_ISPENDR and when hardware
raises the interrupt line. Writing to the GICD_ICPENDR will not cause
the interrupt to become non-pending if the line is still active, and
conversely, if the line is deactivated but the interrupt is marked as
pending through a write to GICD_ISPENDR, the interrupt remains pending.
Handle this situation in the GIC_TEST_PENDING (which now becomes a
static inline named gic_test_pending) and let the 'pending' field
correspond only to the latched state of the D-flip flop in the GICv2.0
specs Figure 4-10.
The following changes are added:
gic_test_pending:
Make this a static inline and split out the 11MPCore from the generic
behavior. For the generic behavior, consider interrupts pending if:
((s->irq_state[irq].pending & (cm) != 0) ||
(!GIC_TEST_EDGE_TRIGGER(irq) && GIC_TEST_LEVEL(irq, cm))
gic_set_irq:
Split out the 11MPCore from the generic behavior. For the generic
behavior, always GIC_SET_LEVEL() on positive level, but only
GIC_SET_PENDING for edge-triggered interrupts and always simply
GIC_CLEAR_LEVEL() on negative level.
gic_complete_irq:
Only resample the line for line-triggered interrupts on an 11MPCore.
Generic implementations will sample the line directly in
gic_test_pending().
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 8d999995e45c1002aa11f269c98f2e93e6f8c42a)
---
hw/intc/arm_gic.c | 64 ++++++++++++++++++++++++++++++++++++--------------
hw/intc/gic_internal.h | 16 ++++++++++++-
2 files changed, 62 insertions(+), 18 deletions(-)
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index 62153fd..11fe3c4 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -66,7 +66,7 @@ void gic_update(GICState *s)
best_prio = 0x100;
best_irq = 1023;
for (irq = 0; irq < s->num_irq; irq++) {
- if (GIC_TEST_ENABLED(irq, cm) && GIC_TEST_PENDING(irq, cm)) {
+ if (GIC_TEST_ENABLED(irq, cm) && gic_test_pending(s, irq, cm)) {
if (GIC_GET_PRIORITY(irq, cpu) < best_prio) {
best_prio = GIC_GET_PRIORITY(irq, cpu);
best_irq = irq;
@@ -89,14 +89,43 @@ void gic_set_pending_private(GICState *s, int cpu, int irq)
{
int cm = 1 << cpu;
- if (GIC_TEST_PENDING(irq, cm))
+ if (gic_test_pending(s, irq, cm)) {
return;
+ }
DPRINTF("Set %d pending cpu %d\n", irq, cpu);
GIC_SET_PENDING(irq, cm);
gic_update(s);
}
+static void gic_set_irq_11mpcore(GICState *s, int irq, int level,
+ int cm, int target)
+{
+ if (level) {
+ GIC_SET_LEVEL(irq, cm);
+ if (GIC_TEST_EDGE_TRIGGER(irq) || GIC_TEST_ENABLED(irq, cm)) {
+ DPRINTF("Set %d pending mask %x\n", irq, target);
+ GIC_SET_PENDING(irq, target);
+ }
+ } else {
+ GIC_CLEAR_LEVEL(irq, cm);
+ }
+}
+
+static void gic_set_irq_generic(GICState *s, int irq, int level,
+ int cm, int target)
+{
+ if (level) {
+ GIC_SET_LEVEL(irq, cm);
+ DPRINTF("Set %d pending mask %x\n", irq, target);
+ if (GIC_TEST_EDGE_TRIGGER(irq)) {
+ GIC_SET_PENDING(irq, target);
+ }
+ } else {
+ GIC_CLEAR_LEVEL(irq, cm);
+ }
+}
+
/* Process a change in an external IRQ input. */
static void gic_set_irq(void *opaque, int irq, int level)
{
@@ -126,15 +155,12 @@ static void gic_set_irq(void *opaque, int irq, int level)
return;
}
- if (level) {
- GIC_SET_LEVEL(irq, cm);
- if (GIC_TEST_EDGE_TRIGGER(irq) || GIC_TEST_ENABLED(irq, cm)) {
- DPRINTF("Set %d pending mask %x\n", irq, target);
- GIC_SET_PENDING(irq, target);
- }
+ if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
+ gic_set_irq_11mpcore(s, irq, level, cm, target);
} else {
- GIC_CLEAR_LEVEL(irq, cm);
+ gic_set_irq_generic(s, irq, level, cm, target);
}
+
gic_update(s);
}
@@ -195,14 +221,18 @@ void gic_complete_irq(GICState *s, int cpu, int irq)
}
if (s->running_irq[cpu] == 1023)
return; /* No active IRQ. */
- /* Mark level triggered interrupts as pending if they are still
- raised. */
- if (!GIC_TEST_EDGE_TRIGGER(irq) && GIC_TEST_ENABLED(irq, cm)
- && GIC_TEST_LEVEL(irq, cm) && (GIC_TARGET(irq) & cm) != 0) {
- DPRINTF("Set %d pending mask %x\n", irq, cm);
- GIC_SET_PENDING(irq, cm);
- update = 1;
+
+ if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
+ /* Mark level triggered interrupts as pending if they are still
+ raised. */
+ if (!GIC_TEST_EDGE_TRIGGER(irq) && GIC_TEST_ENABLED(irq, cm)
+ && GIC_TEST_LEVEL(irq, cm) && (GIC_TARGET(irq) & cm) != 0) {
+ DPRINTF("Set %d pending mask %x\n", irq, cm);
+ GIC_SET_PENDING(irq, cm);
+ update = 1;
+ }
}
+
if (irq != s->running_irq[cpu]) {
/* Complete an IRQ that is not currently running. */
int tmp = s->running_irq[cpu];
@@ -273,7 +303,7 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset)
res = 0;
mask = (irq < GIC_INTERNAL) ? cm : ALL_CPU_MASK;
for (i = 0; i < 8; i++) {
- if (GIC_TEST_PENDING(irq + i, mask)) {
+ if (gic_test_pending(s, irq + i, mask)) {
res |= (1 << i);
}
}
diff --git a/hw/intc/gic_internal.h b/hw/intc/gic_internal.h
index 8c02d58..92a6f7a 100644
--- a/hw/intc/gic_internal.h
+++ b/hw/intc/gic_internal.h
@@ -34,7 +34,6 @@
#define GIC_TEST_ENABLED(irq, cm) ((s->irq_state[irq].enabled & (cm)) != 0)
#define GIC_SET_PENDING(irq, cm) s->irq_state[irq].pending |= (cm)
#define GIC_CLEAR_PENDING(irq, cm) s->irq_state[irq].pending &= ~(cm)
-#define GIC_TEST_PENDING(irq, cm) ((s->irq_state[irq].pending & (cm)) != 0)
#define GIC_SET_ACTIVE(irq, cm) s->irq_state[irq].active |= (cm)
#define GIC_CLEAR_ACTIVE(irq, cm) s->irq_state[irq].active &= ~(cm)
#define GIC_TEST_ACTIVE(irq, cm) ((s->irq_state[irq].active & (cm)) != 0)
@@ -63,4 +62,19 @@ void gic_update(GICState *s);
void gic_init_irqs_and_distributor(GICState *s, int num_irq);
void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val);
+static inline bool gic_test_pending(GICState *s, int irq, int cm)
+{
+ if (s->revision == REV_NVIC || s->revision == REV_11MPCORE) {
+ return s->irq_state[irq].pending & cm;
+ } else {
+ /* Edge-triggered interrupts are marked pending on a rising edge, but
+ * level-triggered interrupts are either considered pending when the
+ * level is active or if software has explicitly written to
+ * GICD_ISPENDR to set the state pending.
+ */
+ return (s->irq_state[irq].pending & cm) ||
+ (!GIC_TEST_EDGE_TRIGGER(irq) && GIC_TEST_LEVEL(irq, cm));
+ }
+}
+
#endif /* !QEMU_ARM_GIC_INTERNAL_H */

View File

@ -0,0 +1,218 @@
From ab5509221ef27a2a394de5df48fa2fc674aa60e2 Mon Sep 17 00:00:00 2001
From: Christoffer Dall <christoffer.dall@linaro.org>
Date: Mon, 18 Nov 2013 20:32:00 -0800
Subject: [PATCH] arm_gic: Keep track of SGI sources
Right now the arm gic emulation doesn't keep track of the source of an
SGI (which apparently Linux guests don't use, or they're fine with
assuming CPU 0 always).
Add the necessary matrix on the GICState structure and maintain the data
when setting and clearing the pending state of an IRQ and make the state
visible to the guest.
Note that we always choose to present the source as the lowest-numbered
CPU in case multiple cores have signalled the same SGI number to a core
on the system.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 40d225009efe17cad647b4b7424b77a3ace232f1)
---
hw/intc/arm_gic.c | 98 +++++++++++++++++++++++++++++++++++-----
hw/intc/arm_gic_common.c | 5 +-
include/hw/intc/arm_gic_common.h | 7 +++
3 files changed, 96 insertions(+), 14 deletions(-)
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index 11fe3c4..29f98be 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -151,6 +151,8 @@ static void gic_set_irq(void *opaque, int irq, int level)
target = cm;
}
+ assert(irq >= GIC_NR_SGIS);
+
if (level == GIC_TEST_LEVEL(irq, cm)) {
return;
}
@@ -177,21 +179,48 @@ static void gic_set_running_irq(GICState *s, int cpu, int irq)
uint32_t gic_acknowledge_irq(GICState *s, int cpu)
{
- int new_irq;
+ int ret, irq, src;
int cm = 1 << cpu;
- new_irq = s->current_pending[cpu];
- if (new_irq == 1023
- || GIC_GET_PRIORITY(new_irq, cpu) >= s->running_priority[cpu]) {
+ irq = s->current_pending[cpu];
+ if (irq == 1023
+ || GIC_GET_PRIORITY(irq, cpu) >= s->running_priority[cpu]) {
DPRINTF("ACK no pending IRQ\n");
return 1023;
}
- s->last_active[new_irq][cpu] = s->running_irq[cpu];
- /* Clear pending flags for both level and edge triggered interrupts.
- Level triggered IRQs will be reasserted once they become inactive. */
- GIC_CLEAR_PENDING(new_irq, GIC_TEST_MODEL(new_irq) ? ALL_CPU_MASK : cm);
- gic_set_running_irq(s, cpu, new_irq);
- DPRINTF("ACK %d\n", new_irq);
- return new_irq;
+ s->last_active[irq][cpu] = s->running_irq[cpu];
+
+ if (s->revision == REV_11MPCORE) {
+ /* Clear pending flags for both level and edge triggered interrupts.
+ * Level triggered IRQs will be reasserted once they become inactive.
+ */
+ GIC_CLEAR_PENDING(irq, GIC_TEST_MODEL(irq) ? ALL_CPU_MASK : cm);
+ ret = irq;
+ } else {
+ if (irq < GIC_NR_SGIS) {
+ /* Lookup the source CPU for the SGI and clear this in the
+ * sgi_pending map. Return the src and clear the overall pending
+ * state on this CPU if the SGI is not pending from any CPUs.
+ */
+ assert(s->sgi_pending[irq][cpu] != 0);
+ src = ctz32(s->sgi_pending[irq][cpu]);
+ s->sgi_pending[irq][cpu] &= ~(1 << src);
+ if (s->sgi_pending[irq][cpu] == 0) {
+ GIC_CLEAR_PENDING(irq, GIC_TEST_MODEL(irq) ? ALL_CPU_MASK : cm);
+ }
+ ret = irq | ((src & 0x7) << 10);
+ } else {
+ /* Clear pending state for both level and edge triggered
+ * interrupts. (level triggered interrupts with an active line
+ * remain pending, see gic_test_pending)
+ */
+ GIC_CLEAR_PENDING(irq, GIC_TEST_MODEL(irq) ? ALL_CPU_MASK : cm);
+ ret = irq;
+ }
+ }
+
+ gic_set_running_irq(s, cpu, irq);
+ DPRINTF("ACK %d\n", irq);
+ return ret;
}
void gic_set_priority(GICState *s, int cpu, int irq, uint8_t val)
@@ -353,6 +382,22 @@ static uint32_t gic_dist_readb(void *opaque, hwaddr offset)
if (GIC_TEST_EDGE_TRIGGER(irq + i))
res |= (2 << (i * 2));
}
+ } else if (offset < 0xf10) {
+ goto bad_reg;
+ } else if (offset < 0xf30) {
+ if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
+ goto bad_reg;
+ }
+
+ if (offset < 0xf20) {
+ /* GICD_CPENDSGIRn */
+ irq = (offset - 0xf10);
+ } else {
+ irq = (offset - 0xf20);
+ /* GICD_SPENDSGIRn */
+ }
+
+ res = s->sgi_pending[irq][cpu];
} else if (offset < 0xfe0) {
goto bad_reg;
} else /* offset >= 0xfe0 */ {
@@ -527,9 +572,31 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
GIC_CLEAR_EDGE_TRIGGER(irq + i);
}
}
- } else {
+ } else if (offset < 0xf10) {
/* 0xf00 is only handled for 32-bit writes. */
goto bad_reg;
+ } else if (offset < 0xf20) {
+ /* GICD_CPENDSGIRn */
+ if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
+ goto bad_reg;
+ }
+ irq = (offset - 0xf10);
+
+ s->sgi_pending[irq][cpu] &= ~value;
+ if (s->sgi_pending[irq][cpu] == 0) {
+ GIC_CLEAR_PENDING(irq, 1 << cpu);
+ }
+ } else if (offset < 0xf30) {
+ /* GICD_SPENDSGIRn */
+ if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
+ goto bad_reg;
+ }
+ irq = (offset - 0xf20);
+
+ GIC_SET_PENDING(irq, 1 << cpu);
+ s->sgi_pending[irq][cpu] |= value;
+ } else {
+ goto bad_reg;
}
gic_update(s);
return;
@@ -553,6 +620,7 @@ static void gic_dist_writel(void *opaque, hwaddr offset,
int cpu;
int irq;
int mask;
+ int target_cpu;
cpu = gic_get_current_cpu(s);
irq = value & 0x3ff;
@@ -572,6 +640,12 @@ static void gic_dist_writel(void *opaque, hwaddr offset,
break;
}
GIC_SET_PENDING(irq, mask);
+ target_cpu = ctz32(mask);
+ while (target_cpu < GIC_NCPU) {
+ s->sgi_pending[irq][target_cpu] |= (1 << cpu);
+ mask &= ~(1 << target_cpu);
+ target_cpu = ctz32(mask);
+ }
gic_update(s);
return;
}
diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c
index 710607b..f4c7f14 100644
--- a/hw/intc/arm_gic_common.c
+++ b/hw/intc/arm_gic_common.c
@@ -58,8 +58,8 @@ static const VMStateDescription vmstate_gic_irq_state = {
static const VMStateDescription vmstate_gic = {
.name = "arm_gic",
- .version_id = 4,
- .minimum_version_id = 4,
+ .version_id = 5,
+ .minimum_version_id = 5,
.pre_save = gic_pre_save,
.post_load = gic_post_load,
.fields = (VMStateField[]) {
@@ -71,6 +71,7 @@ static const VMStateDescription vmstate_gic = {
VMSTATE_UINT8_2DARRAY(priority1, GICState, GIC_INTERNAL, GIC_NCPU),
VMSTATE_UINT8_ARRAY(priority2, GICState, GIC_MAXIRQ - GIC_INTERNAL),
VMSTATE_UINT16_2DARRAY(last_active, GICState, GIC_MAXIRQ, GIC_NCPU),
+ VMSTATE_UINT8_2DARRAY(sgi_pending, GICState, GIC_NR_SGIS, GIC_NCPU),
VMSTATE_UINT16_ARRAY(priority_mask, GICState, GIC_NCPU),
VMSTATE_UINT16_ARRAY(running_irq, GICState, GIC_NCPU),
VMSTATE_UINT16_ARRAY(running_priority, GICState, GIC_NCPU),
diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h
index 8a2aa00..d2e0c2f 100644
--- a/include/hw/intc/arm_gic_common.h
+++ b/include/hw/intc/arm_gic_common.h
@@ -55,6 +55,13 @@ typedef struct GICState {
uint8_t priority1[GIC_INTERNAL][GIC_NCPU];
uint8_t priority2[GIC_MAXIRQ - GIC_INTERNAL];
uint16_t last_active[GIC_MAXIRQ][GIC_NCPU];
+ /* For each SGI on the target CPU, we store 8 bits
+ * indicating which source CPUs have made this SGI
+ * pending on the target CPU. These correspond to
+ * the bytes in the GIC_SPENDSGIR* registers as
+ * read by the target CPU.
+ */
+ uint8_t sgi_pending[GIC_NR_SGIS][GIC_NCPU];
uint16_t priority_mask[GIC_NCPU];
uint16_t running_irq[GIC_NCPU];

View File

@ -0,0 +1,100 @@
From ca14b4d8ba787af99a77322f16636c9b11d053fe Mon Sep 17 00:00:00 2001
From: Christoffer Dall <christoffer.dall@linaro.org>
Date: Thu, 12 Sep 2013 22:18:20 -0700
Subject: [PATCH] arm_gic: Support setting/getting binary point reg
Add a binary_point field to the gic emulation structure and support
setting/getting this register now when we have it. We don't actually
support interrupt grouping yet, oh well.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit aa7d461ae9dd79d35999f4710743cdf9dec88cef)
---
hw/intc/arm_gic.c | 12 +++++++++---
hw/intc/arm_gic_common.c | 6 ++++--
include/hw/intc/arm_gic_common.h | 7 +++++++
3 files changed, 20 insertions(+), 5 deletions(-)
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index 29f98be..d31892d 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -669,14 +669,15 @@ static uint32_t gic_cpu_read(GICState *s, int cpu, int offset)
case 0x04: /* Priority mask */
return s->priority_mask[cpu];
case 0x08: /* Binary Point */
- /* ??? Not implemented. */
- return 0;
+ return s->bpr[cpu];
case 0x0c: /* Acknowledge */
return gic_acknowledge_irq(s, cpu);
case 0x14: /* Running Priority */
return s->running_priority[cpu];
case 0x18: /* Highest Pending Interrupt */
return s->current_pending[cpu];
+ case 0x1c: /* Aliased Binary Point */
+ return s->abpr[cpu];
default:
qemu_log_mask(LOG_GUEST_ERROR,
"gic_cpu_read: Bad offset %x\n", (int)offset);
@@ -695,10 +696,15 @@ static void gic_cpu_write(GICState *s, int cpu, int offset, uint32_t value)
s->priority_mask[cpu] = (value & 0xff);
break;
case 0x08: /* Binary Point */
- /* ??? Not implemented. */
+ s->bpr[cpu] = (value & 0x7);
break;
case 0x10: /* End Of Interrupt */
return gic_complete_irq(s, cpu, value & 0x3ff);
+ case 0x1c: /* Aliased Binary Point */
+ if (s->revision >= 2) {
+ s->abpr[cpu] = (value & 0x7);
+ }
+ break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"gic_cpu_write: Bad offset %x\n", (int)offset);
diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c
index f4c7f14..7966985 100644
--- a/hw/intc/arm_gic_common.c
+++ b/hw/intc/arm_gic_common.c
@@ -58,8 +58,8 @@ static const VMStateDescription vmstate_gic_irq_state = {
static const VMStateDescription vmstate_gic = {
.name = "arm_gic",
- .version_id = 5,
- .minimum_version_id = 5,
+ .version_id = 6,
+ .minimum_version_id = 6,
.pre_save = gic_pre_save,
.post_load = gic_post_load,
.fields = (VMStateField[]) {
@@ -76,6 +76,8 @@ static const VMStateDescription vmstate_gic = {
VMSTATE_UINT16_ARRAY(running_irq, GICState, GIC_NCPU),
VMSTATE_UINT16_ARRAY(running_priority, GICState, GIC_NCPU),
VMSTATE_UINT16_ARRAY(current_pending, GICState, GIC_NCPU),
+ VMSTATE_UINT8_ARRAY(bpr, GICState, GIC_NCPU),
+ VMSTATE_UINT8_ARRAY(abpr, GICState, GIC_NCPU),
VMSTATE_END_OF_LIST()
}
};
diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h
index d2e0c2f..983c3cf 100644
--- a/include/hw/intc/arm_gic_common.h
+++ b/include/hw/intc/arm_gic_common.h
@@ -68,6 +68,13 @@ typedef struct GICState {
uint16_t running_priority[GIC_NCPU];
uint16_t current_pending[GIC_NCPU];
+ /* We present the GICv2 without security extensions to a guest and
+ * therefore the guest can configure the GICC_CTLR to configure group 1
+ * binary point in the abpr.
+ */
+ uint8_t bpr[GIC_NCPU];
+ uint8_t abpr[GIC_NCPU];
+
uint32_t num_cpu;
MemoryRegion iomem; /* Distributor */

View File

@ -0,0 +1,105 @@
From 7700d225b357c66a6949834f069ea3949890119b Mon Sep 17 00:00:00 2001
From: Christoffer Dall <christoffer.dall@linaro.org>
Date: Mon, 18 Nov 2013 19:26:33 -0800
Subject: [PATCH] arm_gic: Add GICC_APRn state to the GICState
The GICC_APRn registers are not currently supported by the ARM GIC v2.0
emulation. This patch adds the missing state.
Note that we also change the number of APRs to use a define GIC_NR_APRS
based on the maximum number of preemption levels. This patch also adds
RAZ/WI accessors for the four registers on the emulated CPU interface.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit a9d477c4e3d614409a48d12f34624c2dd9f1ec2d)
---
hw/intc/arm_gic.c | 5 +++++
hw/intc/arm_gic_common.c | 5 +++--
include/hw/intc/arm_gic_common.h | 19 +++++++++++++++++++
3 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index d31892d..9ca3f03 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -678,6 +678,8 @@ static uint32_t gic_cpu_read(GICState *s, int cpu, int offset)
return s->current_pending[cpu];
case 0x1c: /* Aliased Binary Point */
return s->abpr[cpu];
+ case 0xd0: case 0xd4: case 0xd8: case 0xdc:
+ return s->apr[(offset - 0xd0) / 4][cpu];
default:
qemu_log_mask(LOG_GUEST_ERROR,
"gic_cpu_read: Bad offset %x\n", (int)offset);
@@ -705,6 +707,9 @@ static void gic_cpu_write(GICState *s, int cpu, int offset, uint32_t value)
s->abpr[cpu] = (value & 0x7);
}
break;
+ case 0xd0: case 0xd4: case 0xd8: case 0xdc:
+ qemu_log_mask(LOG_UNIMP, "Writing APR not implemented\n");
+ break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"gic_cpu_write: Bad offset %x\n", (int)offset);
diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c
index 7966985..ec6286b 100644
--- a/hw/intc/arm_gic_common.c
+++ b/hw/intc/arm_gic_common.c
@@ -58,8 +58,8 @@ static const VMStateDescription vmstate_gic_irq_state = {
static const VMStateDescription vmstate_gic = {
.name = "arm_gic",
- .version_id = 6,
- .minimum_version_id = 6,
+ .version_id = 7,
+ .minimum_version_id = 7,
.pre_save = gic_pre_save,
.post_load = gic_post_load,
.fields = (VMStateField[]) {
@@ -78,6 +78,7 @@ static const VMStateDescription vmstate_gic = {
VMSTATE_UINT16_ARRAY(current_pending, GICState, GIC_NCPU),
VMSTATE_UINT8_ARRAY(bpr, GICState, GIC_NCPU),
VMSTATE_UINT8_ARRAY(abpr, GICState, GIC_NCPU),
+ VMSTATE_UINT32_2DARRAY(apr, GICState, GIC_NR_APRS, GIC_NCPU),
VMSTATE_END_OF_LIST()
}
};
diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h
index 983c3cf..89384c2 100644
--- a/include/hw/intc/arm_gic_common.h
+++ b/include/hw/intc/arm_gic_common.h
@@ -31,6 +31,9 @@
/* Maximum number of possible CPU interfaces, determined by GIC architecture */
#define GIC_NCPU 8
+#define MAX_NR_GROUP_PRIO 128
+#define GIC_NR_APRS (MAX_NR_GROUP_PRIO / 32)
+
typedef struct gic_irq_state {
/* The enable bits are only banked for per-cpu interrupts. */
uint8_t enabled;
@@ -75,6 +78,22 @@ typedef struct GICState {
uint8_t bpr[GIC_NCPU];
uint8_t abpr[GIC_NCPU];
+ /* The APR is implementation defined, so we choose a layout identical to
+ * the KVM ABI layout for QEMU's implementation of the gic:
+ * If an interrupt for preemption level X is active, then
+ * APRn[X mod 32] == 0b1, where n = X / 32
+ * otherwise the bit is clear.
+ *
+ * TODO: rewrite the interrupt acknowlege/complete routines to use
+ * the APR registers to track the necessary information to update
+ * s->running_priority[] on interrupt completion (ie completely remove
+ * last_active[][] and running_irq[]). This will be necessary if we ever
+ * want to support TCG<->KVM migration, or TCG guests which can
+ * do power management involving powering down and restarting
+ * the GIC.
+ */
+ uint32_t apr[GIC_NR_APRS][GIC_NCPU];
+
uint32_t num_cpu;
MemoryRegion iomem; /* Distributor */

View File

@ -0,0 +1,32 @@
From beadb779fa7edda184961c62cd18bff7848b8d27 Mon Sep 17 00:00:00 2001
From: Peter Maydell <peter.maydell@linaro.org>
Date: Thu, 20 Feb 2014 10:35:48 +0000
Subject: [PATCH] hw/intc/arm_gic: Fix NVIC assertion failure
Commit 40d225009ef accidentally changed the behaviour of
gic_acknowledge_irq() for the NVIC. The NVIC doesn't have SGIs,
so this meant we hit an assertion:
gic_acknowledge_irq: Assertion `s->sgi_pending[irq][cpu] != 0' failed.
Return NVIC acknowledge-irq to its previous behaviour, like 11MPCore.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
(cherry picked from commit 873169022aa58daabd10979002f8009c7e5f3f05)
---
hw/intc/arm_gic.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index 9ca3f03..4e0628c 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -189,7 +189,7 @@ uint32_t gic_acknowledge_irq(GICState *s, int cpu)
}
s->last_active[irq][cpu] = s->running_irq[cpu];
- if (s->revision == REV_11MPCORE) {
+ if (s->revision == REV_11MPCORE || s->revision == REV_NVIC) {
/* Clear pending flags for both level and edge triggered interrupts.
* Level triggered IRQs will be reasserted once they become inactive.
*/

View File

@ -139,7 +139,7 @@
Summary: QEMU is a FAST! processor emulator
Name: qemu
Version: 1.6.2
Release: 3%{?dist}
Release: 4%{?dist}
Epoch: 2
License: GPLv2+ and LGPLv2+ and BSD
Group: Development/Tools
@ -299,6 +299,18 @@ Patch0206: 0206-ide-Correct-improper-smart-self-test-counter-reset-i.patch
# Fix guest startup crashes from autotest (bz #1081610)
Patch0207: 0207-char-serial-Fix-emptyness-check.patch
Patch0208: 0208-char-serial-Fix-emptyness-handling.patch
# Fix arm sd warnings with latest kernel (bz #1091548)
Patch0209: 0209-vmstate-Add-uint32-2D-array-support.patch
Patch0210: 0210-arm_gic-Extract-headers-hw-intc-arm_gic-_common-.h.patch
Patch0211: 0211-arm_gic-Rename-GIC_X_TRIGGER-to-GIC_X_EDGE_TRIGGER.patch
Patch0212: 0212-hw-arm_gic-Introduce-gic_set_priority-function.patch
Patch0213: 0213-arm_gic-Introduce-define-for-GIC_NR_SGIS.patch
Patch0214: 0214-arm_gic-Fix-GICD_ICPENDR-and-GICD_ISPENDR-writes.patch
Patch0215: 0215-arm_gic-Fix-GIC-pending-behavior.patch
Patch0216: 0216-arm_gic-Keep-track-of-SGI-sources.patch
Patch0217: 0217-arm_gic-Support-setting-getting-binary-point-reg.patch
Patch0218: 0218-arm_gic-Add-GICC_APRn-state-to-the-GICState.patch
Patch0219: 0219-hw-intc-arm_gic-Fix-NVIC-assertion-failure.patch
BuildRequires: SDL-devel
BuildRequires: zlib-devel
@ -930,6 +942,18 @@ CAC emulation development files.
# Fix guest startup crashes from autotest (bz #1081610)
%patch0207 -p1
%patch0208 -p1
# Fix arm sd warnings with latest kernel (bz #1091548)
%patch0209 -p1
%patch0210 -p1
%patch0211 -p1
%patch0212 -p1
%patch0213 -p1
%patch0214 -p1
%patch0215 -p1
%patch0216 -p1
%patch0217 -p1
%patch0218 -p1
%patch0219 -p1
%build
@ -1637,6 +1661,10 @@ getent passwd qemu >/dev/null || \
%endif
%changelog
* Tue Apr 29 2014 Cole Robinson <crobinso@redhat.com> - 2:1.6.2-4
- Fix arm sd warnings with latest kernel (bz #1091548)
- Fix regression in CVE backport that affects openstack (thanks lbezdick)
* Fri Apr 25 2014 Cole Robinson <crobinso@redhat.com> - 2:1.6.2-3
- Fix guest startup crashes from autotest (bz #1081610)