[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [Patch] ARM: Add an L2 cache controller to KZM
From: |
Peter Chubb |
Subject: |
Re: [Qemu-devel] [Patch] ARM: Add an L2 cache controller to KZM |
Date: |
Wed, 07 Aug 2013 12:21:46 +1000 |
User-agent: |
Wanderlust/2.15.9 (Almost Unreal) SEMI-EPG/1.14.7 (Harue) FLIM/1.14.9 (Gojō) APEL/10.8 EasyPG/1.0.0 Emacs/23.4 (x86_64-pc-linux-gnu) MULE/6.0 (HANACHIRUSATO) |
OK, this is what I've come up with. Dunno whether it's right or not
-- the object model is decoupled from the memory model, so there's no
straightforward way to override just a few of the registers.
At this stage this is just for comment, as I don't really have that
much of a clue about how the object/class hierarchy is meant to work.
---
hw/arm/kzm.c | 3 +
hw/misc/arm_l2x0.c | 129 ++++++++++++++++++++++++++++++++++++++---------------
2 files changed, 96 insertions(+), 36 deletions(-)
Index: qemu/hw/arm/kzm.c
===================================================================
--- qemu.orig/hw/arm/kzm.c 2013-08-07 11:21:48.864692846 +1000
+++ qemu/hw/arm/kzm.c 2013-08-07 11:22:40.292983604 +1000
@@ -33,6 +33,7 @@
* 0x1fffc000-0x1fffffff RAM EMULATED
* 0x20000000-0x2fffffff Reserved IGNORED
* 0x30000000-0x7fffffff I.MX31 Internal Register Space
+ * 0x30000000-0x30000fff L2 Cache Controller PARTIALLY EMULATED
* 0x43f00000 IO_AREA0
* 0x43f90000 UART1 EMULATED
* 0x43f94000 UART2 EMULATED
@@ -134,6 +135,8 @@ static void kzm_init(QEMUMachineInitArgs
DEVICE_NATIVE_ENDIAN);
}
+ sysbus_create_varargs("imx_l2cc", 0x30000000, NULL);
+
kzm_binfo.ram_size = ram_size;
kzm_binfo.kernel_filename = kernel_filename;
kzm_binfo.kernel_cmdline = kernel_cmdline;
Index: qemu/hw/misc/arm_l2x0.c
===================================================================
--- qemu.orig/hw/misc/arm_l2x0.c 2013-08-07 11:21:48.864692846 +1000
+++ qemu/hw/misc/arm_l2x0.c 2013-08-07 11:21:48.860692824 +1000
@@ -21,7 +21,9 @@
#include "hw/sysbus.h"
/* L2C-310 r3p2 */
-#define CACHE_ID 0x410000c8
+#define PL310_CACHE_ID 0x410000c8
+/* L2CC from Freescale */
+#define IMX_PL2CC_CACHE_ID 0xD5000041
#define TYPE_ARM_L2X0 "l2x0"
#define ARM_L2X0(obj) OBJECT_CHECK(L2x0State, (obj), TYPE_ARM_L2X0)
@@ -30,6 +32,7 @@ typedef struct L2x0State {
SysBusDevice parent_obj;
MemoryRegion iomem;
+ uint32_t cache_id;
uint32_t cache_type;
uint32_t ctrl;
uint32_t aux_ctrl;
@@ -66,7 +69,7 @@ static uint64_t l2x0_priv_read(void *opa
}
switch (offset) {
case 0:
- return CACHE_ID;
+ return s->cache_id;
case 0x4:
/* aux_ctrl values affect cache_type values */
cache_data = (s->aux_ctrl & (7 << 17)) >> 15;
@@ -78,23 +81,25 @@ static uint64_t l2x0_priv_read(void *opa
return s->aux_ctrl;
case 0x108:
return s->tag_ctrl;
- case 0x10C:
- return s->data_ctrl;
- case 0xC00:
- return s->filter_start;
- case 0xC04:
- return s->filter_end;
case 0xF40:
return 0;
- case 0xF60:
- return 0;
- case 0xF80:
- return 0;
- default:
- qemu_log_mask(LOG_GUEST_ERROR,
- "l2x0_priv_read: Bad offset %x\n", (int)offset);
- break;
}
+ if (s->cache_id == PL310_CACHE_ID) {
+ switch (offset) {
+ case 0x10C:
+ return s->data_ctrl;
+ case 0xC00:
+ return s->filter_start;
+ case 0xC04:
+ return s->filter_end;
+ case 0xF60:
+ return 0;
+ case 0xF80:
+ return 0;
+ }
+ }
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "l2x0_priv_read: Bad offset %x\n", (int)offset);
return 0;
}
@@ -107,6 +112,7 @@ static void l2x0_priv_write(void *opaque
/* ignore */
return;
}
+
switch (offset) {
case 0x100:
s->ctrl = value & 1;
@@ -114,29 +120,32 @@ static void l2x0_priv_write(void *opaque
case 0x104:
s->aux_ctrl = value;
break;
- case 0x108:
- s->tag_ctrl = value;
- break;
- case 0x10C:
- s->data_ctrl = value;
- break;
- case 0xC00:
- s->filter_start = value;
- break;
- case 0xC04:
- s->filter_end = value;
- break;
case 0xF40:
return;
- case 0xF60:
- return;
- case 0xF80:
- return;
- default:
- qemu_log_mask(LOG_GUEST_ERROR,
- "l2x0_priv_write: Bad offset %x\n", (int)offset);
- break;
}
+
+ if (s->cache_id == PL310_CACHE_ID) {
+ switch (offset) {
+ case 0x108:
+ s->tag_ctrl = value;
+ break;
+ case 0x10C:
+ s->data_ctrl = value;
+ break;
+ case 0xC00:
+ s->filter_start = value;
+ break;
+ case 0xC04:
+ s->filter_end = value;
+ break;
+ case 0xF60:
+ return;
+ case 0xF80:
+ return;
+ }
+ }
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "l2x0_priv_write: Bad offset %x\n", (int)offset);
}
static void l2x0_priv_reset(DeviceState *dev)
@@ -184,16 +193,64 @@ static void l2x0_class_init(ObjectClass
dc->reset = l2x0_priv_reset;
}
+static void l2x0_init(Object *obj)
+{
+ L2x0State *s = ARM_L2X0(obj);
+
+ s->cache_id = PL310_CACHE_ID;
+}
+
static const TypeInfo l2x0_info = {
.name = TYPE_ARM_L2X0,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(L2x0State),
+ .instance_init = l2x0_init,
.class_init = l2x0_class_init,
};
+/********************************
+ * The i.MX31 L2CC is a subset of the PL310 implemented above.
+ */
+
+static void imx_l2cc_init(Object *obj) {
+ L2x0State *s = ARM_L2X0(obj);
+
+ s->cache_id = IMX_PL2CC_CACHE_ID;
+}
+
+
+static void imx_l2cc_priv_reset(DeviceState *dev)
+{
+ L2x0State *s = ARM_L2X0(dev);
+
+ s->ctrl = 0;
+ s->aux_ctrl = 0xE4020FFF;
+}
+
+
+/*
+ * I assume the parent class's init function has already been called.
+ */
+static void imx_l2cc_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->reset = imx_l2cc_priv_reset;
+}
+
+
+static const TypeInfo imx_l2cc_info = {
+ .name = "imx_l2cc",
+ .parent = TYPE_ARM_L2X0,
+ .instance_init = imx_l2cc_init,
+ .class_init = imx_l2cc_class_init,
+};
+
+
static void l2x0_register_types(void)
{
type_register_static(&l2x0_info);
+ type_register_static(&imx_l2cc_info);
}
type_init(l2x0_register_types)