Skip to contentSkip to conversation

Data Driven device registers & Zynq DEVCFG

PATCH Superseded Peter Crosthwaite 4 participants 14 messages Apr 5, 2013 – Apr 15, 2013

Subsystems (2)

v2 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

v2 cover Data Driven device registers & Zynq DEVCFG

Hi All. This is a new scheme i've come up with handling device registers in a data driven way. My motivation for this is to factor out a lot of the access checking that seems to be replicated in every device. See P2 commit message for further discussion.

P1 is a trivial addition to bitops.h
P2 is the main patch, adds the register definition functionality P3 is an example new device (the Xilinx Zynq devcfg) that uses this scheme. P4 adds devcfg to the Zynq machine model

This devcfg device was particularly finnicky with per-bit restrictions which prompted all this. Im also looking for a higher-than-usual modelling fidelity on the register space, with semantics defined for random reserved bits in-between otherwise consistent fields.

Heres an example of the qemu_log output for the devcfg device. This is produced by now generic sharable code:

/machine/unattached/device[44]:Addr 0x000008:CFG: write of value 00000508 /machine/unattached/device[44]:Addr 0x000080:MCTRL: write of value 00800010 /machine/unattached/device[44]:Addr 0x000010:INT_MASK: write of value ffffffff /machine/unattached/device[44]:Addr 00000000:CTRL: write of value 0c00607f

And an example of a rogue guest banging on a bad bit:

/machine/unattached/device[44]:Addr 0x000014:STATUS bits 0x000001 may not be \
written to 1

Future work: Theres a lot of overlap here with what Peter did with the ARM coprocessor definitions. We could go further and generalise ARM CP to use this or some further evolution of it. That and converting existing models to this scheme. Some device models will lose a lot of weight. Also integrate with memory API.

Changed from v1:
Added ONES macro patch
Dropped bogus former patch 1 (PMM review)
Addressed Blue, Gerd and MST comments.
Simplified to be more Memory API compatible.
Added Memory API helpers.
Please see discussion already on list and commit msgs for more detail.

Peter A. G. Crosthwaite (2):
xilinx_devcfg: Zynq devcfg device model
xilinx_zynq: added devcfg to machine model

Peter Crosthwaite (3):
bitops: Add ONES macro
register: Add Register API
register: Add Memory API glue

 Makefile.target         |    2 +-
 hw/arm/Makefile.objs    |    2 +-
 hw/arm/xilinx_zynq.c    |    8 +
 hw/xilinx_devcfg.c      |  489 +++++++++++++++++++++++++++++++++++++++++++++++
 include/exec/register.h |  147 ++++++++++++++
 include/qemu/bitops.h   |    2 +
 register.c              |  207 ++++++++++++++++++++
 7 files changed, 855 insertions(+), 2 deletions(-)
 create mode 100644 hw/xilinx_devcfg.c
 create mode 100644 include/exec/register.h
 create mode 100644 register.c
#1 lore raw

PATCH v2 1/5 bitops: Add ONES macro

Little macro that just gives you N ones (justified to LSB).

---

 include/qemu/bitops.h |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
include/qemu/bitops.h +2 -0
index affcc96..da47fc8 100644
@@ -273,4 +273,6 @@ static inline uint64_t deposit64(uint64_t value, int start, int length,
     return (value & ~mask) | ((fieldval << start) & mask);
 }
 
+#define ONES(num) ((num) == 64 ? ~0ull : (1ull << (num)) - 1)
+
 #endif
Signature · 1 line
1.7.0.4
#2 lore raw

Re: [Qemu-devel] [PATCH v2 1/5] bitops: Add ONES macro

Quoted 13 lines · Peter Crosthwaite

Little macro that just gives you N ones (justified to LSB).

---

 include/qemu/bitops.h |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
include/qemu/bitops.h +0 -0
index affcc96..da47fc8 100644

include/qemu/bitops.h static inline uint64_t deposit64(uint64_t value, int start, int length, · line 276

Quoted 4 lines
include/qemu/bitops.h +1 -0
@@ -273,4 +273,6 @@ static inline uint64_t deposit64(uint64_t value, int start, int length,
     return (value & ~mask) | ((fieldval << start) & mask);
 }
 
+#define ONES(num) ((num) == 64 ? ~0ull : (1ull << (num)) - 1)

You can avoid the ?: here (assuming you're happy to say that ONES(0) is a silly thing to ask for):

#define ONES(num) (~0ULL >> (64 - (num)))

Needs a documentation comment, anyway.

thanks
-- PMM

#3 lore raw

Re: [Qemu-devel] [PATCH v2 1/5] bitops: Add ONES macro

Hi Peter,

Quoted 17 lines · Peter Maydell
Quoted 16 lines · Peter Crosthwaite

Little macro that just gives you N ones (justified to LSB).

---

 include/qemu/bitops.h |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
include/qemu/bitops.h +0 -0
index affcc96..da47fc8 100644
@@ -273,4 +273,6 @@ static inline uint64_t deposit64(uint64_t value, int start, int length,
     return (value & ~mask) | ((fieldval << start) & mask);
 }
 
Quoted 5 lines

include/qemu/bitops.h static inline uint64_t deposit64(uint64_t value, int start, int length, · line 276

Quoted 1 line
include/qemu/bitops.h +1 -0
+#define ONES(num) ((num) == 64 ? ~0ull : (1ull << (num)) - 1)

You can avoid the ?: here (assuming you're happy to say that ONES(0) is a silly thing to ask for):

Not that silly. ONES(0) should just stay true to the contract and return 0. Otherwise prospective clients may have to guard against 0 cases in loops which is ugly:

for (i = 0; i < N; i++) {
    ....
    mask = ONES(i); /* rather than ones = i ? ones(i) : 0 */
    ....
}

But I thought about this more, and perhaps just ditch the ? anyway, and rely on the shift by 64 ending up as 0. Then the -1 should return return 64 (all) ones anyway.

Quoted 4 lines

#define ONES(num) (~0ULL >> (64 - (num)))

Needs a documentation comment, anyway.

OK

Regards,
Peter

Quoted 3 lines

thanks
-- PMM

#4 lore raw

Re: [Qemu-devel] [PATCH v2 1/5] bitops: Add ONES macro

Quoted 2 lines · Peter Crosthwaite

But I thought about this more, and perhaps just ditch the ? anyway, and rely on the shift by 64 ending up as 0.

That's undefined behaviour, please don't.

-- PMM

#5 lore raw

PATCH v2 2/5 register: Add Register API

In reply to Peter Crosthwaite

This API provides some encapsulation of registers and factors our some common functionality to common code. Bits of device state (usually MMIO registers), often have all sorts of access restrictions and semantics associated with them. This API allow you to define what those restrictions are on a bit-by-bit basis.

Helper functions are then used to access the register which observe the semantics defined by the RegisterAccessInfo struct.

Some features:
Bits can be marked as read_only (ro field)
Bits can be marked as write-1-clear (w1c field)
Bits can be marked as write only (wo)
Bits can be marked as sticky (nw0 and nw1)
Reset values can be defined (reset)
Bits can throw guest errors when written certain values (ge0, ge1) Bits can throw unimp errors when written certain values (ui0, ui1) Bits can be marked clear on read (cor)
Pre and post action callbacks can be added to read and write ops Verbose debugging info can be enabled/disabled

Useful for defining device register spaces in a data driven way. Cuts down on a lot of the verbosity and repetition in the switch-case blocks in the standard foo_mmio_read/write functions.

---
changed from v1:
Rebranded as the "Register API" - I think thats probably what it is. Near total rewrite of implementation.
De-arrayified reset (this is client/Memory APIs job).
Moved out of bitops into its own file (Blue review)
Added debug, the register pointer, and prefix to a struct (Blue Review) Made 64-bit to play friendlier with memory API (Blue review) Made backend storage uint8_t (MST review)
Added read/write callbacks (Blue review)
Added ui0, ui1 (Blue review)
Moved re-purposed width (now byte width defining actual storage size) Arrayified ge0, ge1 (ui0, ui1 too) and added .reason
Added wo field (not an April fools joke - this has genuine meaning here) Added we mask to write accessor

 Makefile.target         |    2 +-
 include/exec/register.h |  134 ++++++++++++++++++++++++++++++++++++++
 register.c              |  164 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 299 insertions(+), 1 deletions(-)
 create mode 100644 include/exec/register.h
 create mode 100644 register.c
Makefile.target +1 -1
index 2bd6d14..9c35931 100644
@@ -114,7 +114,7 @@ obj-y += hw/
 obj-$(CONFIG_FDT) += device_tree.o
 obj-$(CONFIG_KVM) += kvm-all.o
 obj-$(CONFIG_NO_KVM) += kvm-stub.o
-obj-y += memory.o savevm.o cputlb.o
+obj-y += memory.o register.o savevm.o cputlb.o
 obj-$(CONFIG_HAVE_GET_MEMORY_MAPPING) += memory_mapping.o
 obj-$(CONFIG_HAVE_CORE_DUMP) += dump.o
 obj-$(CONFIG_NO_GET_MEMORY_MAPPING) += memory_mapping-stub.o
include/exec/register.h new file +134 -0

134 lines not on this page · raw message

register.c new file +164 -0

164 lines not on this page · raw message

Signature · 1 line
1.7.0.4
#6 lore raw

Re: [Qemu-devel] [PATCH v2 2/5] register: Add Register API

Quoted 68 lines · Peter Crosthwaite

This API provides some encapsulation of registers and factors our some common functionality to common code. Bits of device state (usually MMIO registers), often have all sorts of access restrictions and semantics associated with them. This API allow you to define what those restrictions are on a bit-by-bit basis.

register.c new file +63 -0
+void register_write(RegisterInfo *reg, uint64_t val, uint64_t we)
+{
+    uint64_t old_val, new_val, test;
+    const RegisterAccessInfo *ac;
+    const RegisterAccessError *rae;
+
+    assert(reg);
+
+    ac = reg->access;
+    if (!ac || !ac->name) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: write to undefined device state "
+                      "(written value: %#" PRIx64 ")\n", reg->prefix, val);
+        return;
+    }
+
+    uint32_t no_w0_mask = ac->ro | ac->w1c | ac->nw0 | ~we;
+    uint32_t no_w1_mask = ac->ro | ac->w1c | ac->nw1 | ~we;
+
+    if (reg->debug) {
+        fprintf(stderr, "%s:%s: write of value %#" PRIx64 "\n", reg->prefix,
+                ac->name, val);
+    }
+
+    if (qemu_loglevel_mask(LOG_GUEST_ERROR)) {
+        for (rae = ac->ge1; rae && rae->mask; rae++) {
+            test = val & rae->mask;
+            if (test) {
+                register_write_log(reg, 1, test, LOG_GUEST_ERROR,
+                                   "invalid", rae->reason);
+            }
+        }
+        for (rae = ac->ge0; rae && rae->mask; rae++) {
+            test = val & rae->mask;
+            if (test) {
+                register_write_log(reg, 0, test, LOG_GUEST_ERROR,
+                                   "invalid", rae->reason);
+            }
+        }
+    }
+
+    if (qemu_loglevel_mask(LOG_UNIMP)) {
+        for (rae = ac->ui1; rae && rae->mask; rae++) {
+            test = val & rae->mask;
+            if (test) {
+                register_write_log(reg, 1, test, LOG_GUEST_ERROR,
+                                   "unimplmented", rae->reason);
+            }
+        }
+        for (rae = ac->ui0; rae && rae->mask; rae++) {
+            test = val & rae->mask;
+            if (test) {
+                register_write_log(reg, 0, test, LOG_GUEST_ERROR,
+                                   "unimplemented", rae->reason);
+            }
+        }
+    }
+
+    assert(reg->data);
+    old_val = register_read_val(reg);
+
+    new_val = val & ~(no_w1_mask & val);
+    new_val |= no_w1_mask & old_val & val;
+    new_val |= no_w0_mask & old_val & ~val;

register.c line 117

Quoted 10 lines
register.c new file +10 -0
+    new_val &= ~(val & ac->w1c);
+
+    if (ac->pre_write) {
+        new_val = ac->pre_write(reg, new_val);
+    }
+    register_write_val(reg, new_val);
+    if (ac->post_write) {
+        ac->post_write(reg, new_val);
+    }
+}

Wow, this feels pretty heavyweight for "write a register"...

-- PMM

#7 lore raw

Re: [Qemu-devel] [PATCH v2 2/5] register: Add Register API

Quoted 73 lines · Peter Maydell
Quoted 72 lines · Peter Crosthwaite

This API provides some encapsulation of registers and factors our some common functionality to common code. Bits of device state (usually MMIO registers), often have all sorts of access restrictions and semantics associated with them. This API allow you to define what those restrictions are on a bit-by-bit basis.

register.c new file +67 -0
+void register_write(RegisterInfo *reg, uint64_t val, uint64_t we)
+{
+    uint64_t old_val, new_val, test;
+    const RegisterAccessInfo *ac;
+    const RegisterAccessError *rae;
+
+    assert(reg);
+
+    ac = reg->access;
+    if (!ac || !ac->name) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: write to undefined device state "
+                      "(written value: %#" PRIx64 ")\n", reg->prefix, val);
+        return;
+    }
+
+    uint32_t no_w0_mask = ac->ro | ac->w1c | ac->nw0 | ~we;
+    uint32_t no_w1_mask = ac->ro | ac->w1c | ac->nw1 | ~we;
+
+    if (reg->debug) {
+        fprintf(stderr, "%s:%s: write of value %#" PRIx64 "\n", reg->prefix,
+                ac->name, val);
+    }
+
+    if (qemu_loglevel_mask(LOG_GUEST_ERROR)) {
+        for (rae = ac->ge1; rae && rae->mask; rae++) {
+            test = val & rae->mask;
+            if (test) {
+                register_write_log(reg, 1, test, LOG_GUEST_ERROR,
+                                   "invalid", rae->reason);
+            }
+        }
+        for (rae = ac->ge0; rae && rae->mask; rae++) {
+            test = val & rae->mask;
+            if (test) {
+                register_write_log(reg, 0, test, LOG_GUEST_ERROR,
+                                   "invalid", rae->reason);
+            }
+        }
+    }
+
+    if (qemu_loglevel_mask(LOG_UNIMP)) {
+        for (rae = ac->ui1; rae && rae->mask; rae++) {
+            test = val & rae->mask;
+            if (test) {
+                register_write_log(reg, 1, test, LOG_GUEST_ERROR,
+                                   "unimplmented", rae->reason);
+            }
+        }
+        for (rae = ac->ui0; rae && rae->mask; rae++) {
+            test = val & rae->mask;
+            if (test) {
+                register_write_log(reg, 0, test, LOG_GUEST_ERROR,
+                                   "unimplemented", rae->reason);
+            }
+        }
+    }
+
+    assert(reg->data);
+    old_val = register_read_val(reg);
+
+    new_val = val & ~(no_w1_mask & val);
+    new_val |= no_w1_mask & old_val & val;
+    new_val |= no_w0_mask & old_val & ~val;
+    new_val &= ~(val & ac->w1c);
+
+    if (ac->pre_write) {
+        new_val = ac->pre_write(reg, new_val);
Quoted 9 lines

register.c line 117

Quoted 6 lines
register.c new file +6 -0
+    }
+    register_write_val(reg, new_val);
+    if (ac->post_write) {
+        ac->post_write(reg, new_val);
+    }
+}

Wow, this feels pretty heavyweight for "write a register"...

Its a pritty fast path through if all the optionals turned off. If I was going to lighten it up, Id get rid of the reg_size and the byte loop first although that would mandate uint64_t as the data type for the backing store.

But the intended primary usage of the API is for device control and status registers, where you are generally not interested in performance, unless you are doing some form of PIO. In that case, you can opt out on a per register basis and make yourself a fast path for the critical registers (r/w fifo heads access regs etc). This is designed for developer and debugging convenience, where you have a large number or registers with a heteorgenous mix of accesses and side effects but at the same time the registers are infrequent access. This is true of most device registers.

Another solution is some sort of "lite" mode. A single check in the definition that disables a lot of this and cuts to the chase (the actual write).

Quoted 2 lines

-- PMM

#8 lore raw

Re: [Qemu-devel] [PATCH v2 2/5] register: Add Register API

Hi Peter,

Quoted 75 lines · Peter Crosthwaite
Quoted 74 lines · Peter Maydell
Quoted 73 lines · Peter Crosthwaite

This API provides some encapsulation of registers and factors our some common functionality to common code. Bits of device state (usually MMIO registers), often have all sorts of access restrictions and semantics associated with them. This API allow you to define what those restrictions are on a bit-by-bit basis.

register.c new file +68 -0
+void register_write(RegisterInfo *reg, uint64_t val, uint64_t we)
+{
+    uint64_t old_val, new_val, test;
+    const RegisterAccessInfo *ac;
+    const RegisterAccessError *rae;
+
+    assert(reg);
+
+    ac = reg->access;
+    if (!ac || !ac->name) {
+        qemu_log_mask(LOG_GUEST_ERROR, "%s: write to undefined device state "
+                      "(written value: %#" PRIx64 ")\n", reg->prefix, val);
+        return;
+    }
+
+    uint32_t no_w0_mask = ac->ro | ac->w1c | ac->nw0 | ~we;
+    uint32_t no_w1_mask = ac->ro | ac->w1c | ac->nw1 | ~we;
+
+    if (reg->debug) {
+        fprintf(stderr, "%s:%s: write of value %#" PRIx64 "\n", reg->prefix,
+                ac->name, val);
+    }
+
+    if (qemu_loglevel_mask(LOG_GUEST_ERROR)) {
+        for (rae = ac->ge1; rae && rae->mask; rae++) {
+            test = val & rae->mask;
+            if (test) {
+                register_write_log(reg, 1, test, LOG_GUEST_ERROR,
+                                   "invalid", rae->reason);
+            }
+        }
+        for (rae = ac->ge0; rae && rae->mask; rae++) {
+            test = val & rae->mask;
+            if (test) {
+                register_write_log(reg, 0, test, LOG_GUEST_ERROR,
+                                   "invalid", rae->reason);
+            }
+        }
+    }
+
+    if (qemu_loglevel_mask(LOG_UNIMP)) {
+        for (rae = ac->ui1; rae && rae->mask; rae++) {
+            test = val & rae->mask;
+            if (test) {
+                register_write_log(reg, 1, test, LOG_GUEST_ERROR,
+                                   "unimplmented", rae->reason);
+            }
+        }
+        for (rae = ac->ui0; rae && rae->mask; rae++) {
+            test = val & rae->mask;
+            if (test) {
+                register_write_log(reg, 0, test, LOG_GUEST_ERROR,
+                                   "unimplemented", rae->reason);
+            }
+        }
+    }
+
+    assert(reg->data);
+    old_val = register_read_val(reg);
+
+    new_val = val & ~(no_w1_mask & val);
+    new_val |= no_w1_mask & old_val & val;
+    new_val |= no_w0_mask & old_val & ~val;
+    new_val &= ~(val & ac->w1c);
+
+    if (ac->pre_write) {
+        new_val = ac->pre_write(reg, new_val);
+    }
Quoted 8 lines
Quoted 8 lines

register.c line 117

Quoted 5 lines
register.c new file +5 -0
+    register_write_val(reg, new_val);
+    if (ac->post_write) {
+        ac->post_write(reg, new_val);
+    }
+}

Wow, this feels pretty heavyweight for "write a register"...

I have been thinking about this more, and in the interest of getting something merged, I'm happy to work on this. I could use some specific feedback however, considering there was generally positive feedback on v1 so im guessing the objections come from the v2 added features (being the byte loop, ui, we and the hooks). Here are my current "lightening" proposals:

- Add a "ne" (no/native endianess) version to the memory api handlers which just passes the args straight through to register API, no byte reversal logic needed.
- Remove nw0 and nw1, They are reasonably rare and can be handled with the odd pre_write hook for those cases.
- Add a "lite" flag that is (automatically) computed once that takes a fast path through the read/write handlers. A reg is lite if it requires no read-modify-write (no ro, nw, ge, ui, wtc). Only the actual write and post_write handlers are executed.
- Remove the byte loops. Just switch on register size and cast to uint_XXt. Remove support for non power-of-two size registers and non-host endianess (needed for potential PCI conversion) but should make the code faster.
- Make data pointer optional. No data means register is read as reset and no write occurs (post write hook only). This make wo redundant (anyone wanting to do per-bit wo semantic uses pre-write hook).

If you care about performance of a particular reg, just add a post_write hook, set it up as native endianess, with a NULL data register, no access checks. Then its a very fast path from the memory API through to your handler.

Regards,
Peter

Quoted 22 lines

Its a pritty fast path through if all the optionals turned off. If I was going to lighten it up, Id get rid of the reg_size and the byte loop first although that would mandate uint64_t as the data type for the backing store.

But the intended primary usage of the API is for device control and status registers, where you are generally not interested in performance, unless you are doing some form of PIO. In that case, you can opt out on a per register basis and make yourself a fast path for the critical registers (r/w fifo heads access regs etc). This is designed for developer and debugging convenience, where you have a large number or registers with a heteorgenous mix of accesses and side effects but at the same time the registers are infrequent access. This is true of most device registers.

Another solution is some sort of "lite" mode. A single check in the definition that disables a lot of this and cuts to the chase (the actual write).

Quoted 2 lines

-- PMM

#9 lore raw

Re: [Qemu-devel] [PATCH v2 2/5] register: Add Register API

Hi,

Quoted 4 lines

- Add a "lite" flag that is (automatically) computed once that takes a fast path through the read/write handlers. A reg is lite if it requires no read-modify-write (no ro, nw, ge, ui, wtc). Only the actual write and post_write handlers are executed.

Sounds good to me.

Quoted 4 lines

- Remove the byte loops. Just switch on register size and cast to uint_XXt. Remove support for non power-of-two size registers and non-host endianess (needed for potential PCI conversion) but should make the code faster.

This too.

Also: you might want to pass both old and new value to the post-write hook so the handler can easily figure what has actually changed.

cheers,
Gerd

#10 lore raw

PATCH v2 3/5 register: Add Memory API glue

In reply to Peter Crosthwaite

Add memory io handlers that glue the register API to the memory API. Just translation functions at this stage. Although it does allow for devices to be created without all-in-one mmio r/w handlers.

---

 include/exec/register.h |   13 +++++++++++++
 register.c              |   43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+), 0 deletions(-)
include/exec/register.h +13 -0
index 0b05439..f30c98e 100644
@@ -13,6 +13,7 @@
 
 #include <stdint.h>
 #include <stdbool.h>
+#include "exec/memory.h"
 
 typedef struct RegisterInfo RegisterInfo;
 typedef struct RegisterAccessInfo RegisterAccessInfo;
@@ -92,6 +93,8 @@ struct RegisterAccessInfo {
  * @prefix: String prefix for log and debug messages
  *
  * @opaque: Opaque data for the register
+ *
+ * @mem: optional Memory region for the register
  */
 
 struct RegisterInfo {
@@ -105,6 +108,8 @@ struct RegisterInfo {
     const char *prefix;
 
     void *opaque;
+
+    MemoryRegion mem;
 };
 
 /**
@@ -131,4 +136,12 @@ uint64_t register_read(RegisterInfo *reg);
 
 void register_reset(RegisterInfo *reg);
 
+void register_write_memory_be(void *opaque, hwaddr addr, uint64_t value,
+                              unsigned size);
+void register_write_memory_le(void *opaque, hwaddr addr, uint64_t value,
+                              unsigned size);
+
+uint64_t register_read_memory_be(void *opaque, hwaddr addr, unsigned size);
+uint64_t register_read_memory_le(void *opaque, hwaddr addr, unsigned size);
+
 #endif
register.c +43 -0

46 lines not on this page · raw message

Signature · 1 line
1.7.0.4
#11 lore raw

Re: [Qemu-devel] [PATCH v2 3/5] register: Add Memory API glue

Il 05/04/2013 10:43, Peter Crosthwaite ha scritto:

Quoted 8 lines

Add memory io handlers that glue the register API to the memory API. Just translation functions at this stage. Although it does allow for devices to be created without all-in-one mmio r/w handlers.

---

 include/exec/register.h |   13 +++++++++++++

Please put it in include/hw/.

Putting these five in exec/ was a mistake:

#include "exec/address-spaces.h"
#include "exec/hwaddr.h"
#include "exec/ioport.h"
#include "exec/iorange.h"
#include "exec/memory.h"

Most files in hw/ should not need include/exec/.

Quoted 1 line
 register.c              |   43 +++++++++++++++++++++++++++++++++++++++++++

If my reorganization goes in before, please make it hw/core/register.c.

The next step in the reorganization would be to move memory.c to hw/core too.

Paolo

#12 lore raw

PATCH v2 4/5 xilinx_devcfg: Zynq devcfg device model

In reply to Peter Crosthwaite

From: Peter A. G. Crosthwaite <[email protected]>

Minimal device model for devcfg module of Zynq. DMA capabilities and interrupt generation supported.

---
Changed since v1:
Rebased against new version of Register API.
Use action callbacks for side effects rather than switch. Documented reasons for ge0, ge1 (Verbatim from TRM) Added ui1 definitions for unimplemented major features Removed dead lock code

 hw/arm/Makefile.objs |    2 +-
 hw/xilinx_devcfg.c   |  489 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 490 insertions(+), 1 deletions(-)
 create mode 100644 hw/xilinx_devcfg.c
hw/arm/Makefile.objs +1 -1
index f5f7d0e..29c2bd2 100644
@@ -1,4 +1,4 @@
-obj-y += zynq_slcr.o
+obj-y += zynq_slcr.o xilinx_devcfg.o
 obj-y += xilinx_spips.o
 obj-y += arm_gic.o arm_gic_common.o
 obj-y += a9scu.o
hw/xilinx_devcfg.c new file +489 -0

489 lines not on this page · raw message

Signature · 1 line
1.7.0.4
#13 lore raw

PATCH v2 5/5 xilinx_zynq: added devcfg to machine model

In reply to Peter Crosthwaite

From: Peter A. G. Crosthwaite <[email protected]>

---
Changed since v1:
Added manual parenting of devcfg node (evil but needed for early access to canonical path by devcfgs realize fn).

 hw/arm/xilinx_zynq.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)
hw/arm/xilinx_zynq.c +8 -0
index 6f36286..fb3a089 100644
@@ -220,6 +220,14 @@ static void zynq_init(QEMUMachineInitArgs *args)
         sysbus_connect_irq(busdev, n + 1, pic[dma_irqs[n] - IRQ_OFFSET]);
     }
 
+    dev = qdev_create(NULL, "xlnx.ps7-dev-cfg");
+    object_property_add_child(qdev_get_machine(), "xilinx-devcfg", OBJECT(dev),
+                              NULL);
+    qdev_init_nofail(dev);
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_connect_irq(busdev, 0, pic[40-IRQ_OFFSET]);
+    sysbus_mmio_map(busdev, 0, 0xF8007000);
+
     zynq_binfo.ram_size = ram_size;
     zynq_binfo.kernel_filename = kernel_filename;
     zynq_binfo.kernel_cmdline = kernel_cmdline;
Signature · 1 line
1.7.0.4