Re: [PATCH] hw/core/qdev: Increase qdev_realize() kindness

2020-07-05 Thread Markus Armbruster
Paolo Bonzini  writes:

> Are we sure that qdev_realize is never called with user-provided input? If

The only way to call qdev_realize() with a user-provided bus is -device
/ device_add via qdev_device_add().  qdev_device_add() carefully checks
the user-provided bus before passing it to qdev_realize().

> it's a programming error, the call chain will end up passing &error_abort
> anyway, won't it?

Correct.

>
> Paolo
>
> Il dom 5 lug 2020, 12:05 Philippe Mathieu-Daudé  ha
> scritto:
>
>> On 7/5/20 7:46 AM, Paolo Bonzini wrote:
>> > On 20/06/20 17:38, Philippe Mathieu-Daudé wrote:
>> >> -} else {
>> >> -assert(!DEVICE_GET_CLASS(dev)->bus_type);
>> >> +} else if (DEVICE_GET_CLASS(dev)->bus_type) {
>> >> +error_report("%s: Unexpected bus '%s' for device '%s'",
>> >> + __func__, DEVICE_GET_CLASS(dev)->bus_type,
>> >> + object_get_typename(OBJECT(dev)));
>> >> +abort();
>> >>  }
>> >>
>> >
>> > Since there is an errp, should we use it and be even kinder?
>>
>> This is a programming error, not an user triggerable condition,
>> so I'm not sure. IOW this must not happen, but if it does, then
>> the error message helps the developer to notice the problem without
>> having to use gdb.

I don't bother with reporting impossible errors nicely.  Statement, not
objection.




[PATCH] ram: add support for dirty page tracking

2020-07-05 Thread Bingsong Si
In production, the VM with insentive memory activity maybe failed to migrate,
because of the change of memory in the VM greater than the throughtput of the
network interface, and we want to identify it before migration.

1. dirty tracking start:
virsh qemu-monitor-command  --hmp dirty_track

2. wait some time, stop dirty tracking:
virsh qemu-monitor-command  --hmp dirty_track_stop
Dirty rate: 607 pages/s

Signed-off-by: Bingsong Si 
---
 hmp-commands.hx   | 26 +++
 include/monitor/hmp.h |  2 ++
 migration/migration.c |  5 +++
 migration/ram.c   | 65 
 migration/ram.h   |  5 +++
 migration/savevm.c| 77 +++
 migration/savevm.h|  2 ++
 7 files changed, 182 insertions(+)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 60f395c276..05a688286b 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1819,6 +1819,32 @@ SRST
   Set QOM property *property* of object at location *path* to value *value*
 ERST
 
+{
+.name   = "dirty_track",
+.args_type  = "",
+.params = "",
+.help   = "track dirty pages rate",
+.cmd= hmp_dirty_track,
+},
+
+SRST
+``dirty_track``
+  Track dirty pages rate.
+ERST
+
+{
+.name   = "dirty_track_stop",
+.args_type  = "",
+.params = "",
+.help   = "stop current dirty pages track",
+.cmd= hmp_dirty_track_stop,
+},
+
+SRST
+``dirty_track_stop``
+  Stop current dirty pages track.
+ERST
+
 {
 .name   = "info",
 .args_type  = "item:s?",
diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h
index c986cfd28b..c139fe8758 100644
--- a/include/monitor/hmp.h
+++ b/include/monitor/hmp.h
@@ -130,5 +130,7 @@ void hmp_hotpluggable_cpus(Monitor *mon, const QDict 
*qdict);
 void hmp_info_vm_generation_id(Monitor *mon, const QDict *qdict);
 void hmp_info_memory_size_summary(Monitor *mon, const QDict *qdict);
 void hmp_info_sev(Monitor *mon, const QDict *qdict);
+void hmp_dirty_track(Monitor *mon, const QDict *qdict);
+void hmp_dirty_track_stop(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/migration/migration.c b/migration/migration.c
index 481a590f72..5550afafe6 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -1964,6 +1964,11 @@ static bool migrate_prepare(MigrationState *s, bool blk, 
bool blk_inc,
 {
 Error *local_err = NULL;
 
+if (dirty_track_is_running()) {
+error_setg(errp, "There is a dirty tracking process in progress");
+return false;
+}
+
 if (resume) {
 if (s->state != MIGRATION_STATUS_POSTCOPY_PAUSED) {
 error_setg(errp, "Cannot resume if there is no "
diff --git a/migration/ram.c b/migration/ram.c
index 5554a7d2d8..64c50b31cc 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -3782,6 +3782,71 @@ static int ram_resume_prepare(MigrationState *s, void 
*opaque)
 return 0;
 }
 
+void dirty_track_init(void)
+{
+RAMBlock *block;
+
+if (ram_bytes_total()) {
+RAMBLOCK_FOREACH_NOT_IGNORED(block) {
+unsigned long pages = block->max_length >> TARGET_PAGE_BITS;
+
+block->bmap = bitmap_new(pages);
+bitmap_set(block->bmap, 0, pages);
+}
+}
+ram_state = g_new0(RAMState, 1);
+ram_state->migration_dirty_pages = 0;
+memory_global_dirty_log_start();
+}
+
+uint64_t dirty_track_dirty_pages(void)
+{
+return ram_state->migration_dirty_pages;
+}
+
+void dirty_track_sync(void)
+{
+RAMBlock *block = NULL;
+unsigned long offset = 0;
+
+memory_global_dirty_log_sync();
+rcu_read_lock();
+RAMBLOCK_FOREACH_NOT_IGNORED(block) {
+   ramblock_sync_dirty_bitmap(ram_state, block);
+}
+rcu_read_unlock();
+
+rcu_read_lock();
+block = QLIST_FIRST_RCU(&ram_list.blocks);
+
+while (block) {
+offset = migration_bitmap_find_dirty(ram_state, block, offset);
+
+if (offset << TARGET_PAGE_BITS >= block->used_length) {
+offset = 0;
+block = QLIST_NEXT_RCU(block, next);
+} else {
+test_and_clear_bit(offset, block->bmap);
+}
+}
+
+rcu_read_unlock();
+}
+
+void dirty_track_cleanup(void)
+{
+RAMBlock *block;
+
+memory_global_dirty_log_stop();
+RAMBLOCK_FOREACH_NOT_IGNORED(block) {
+g_free(block->bmap);
+block->bmap = NULL;
+}
+
+g_free(ram_state);
+ram_state = NULL;
+}
+
 static SaveVMHandlers savevm_ram_handlers = {
 .save_setup = ram_save_setup,
 .save_live_iterate = ram_save_iterate,
diff --git a/migration/ram.h b/migration/ram.h
index 2eeaacfa13..104c48285c 100644
--- a/migration/ram.h
+++ b/migration/ram.h
@@ -69,4 +69,9 @@ void colo_flush_ram_cache(void);
 void colo_release_ram_cache(void);
 void colo_incoming_start_dirty_log(void);
 
+void dirty_track_init(void);
+uint64_t dirty_track_dirty_pages(void);
+void dirty_track_sync(void);
+void d

[PATCH v3 18/18] hw/block/nvme: bump supported version to v1.3

2020-07-05 Thread Klaus Jensen
From: Klaus Jensen 

Bump the supported NVM Express version to v1.3.

Signed-off-by: Klaus Jensen 
Reviewed-by: Maxim Levitsky 
Reviewed-by: Dmitry Fomichev 
---
 hw/block/nvme.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index e3984157926b..eda3fedb84e3 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -57,6 +57,7 @@
 #define NVME_MAX_IOQPAIRS 0x
 #define NVME_REG_SIZE 0x1000
 #define NVME_DB_SIZE  4
+#define NVME_SPEC_VER 0x00010300
 #define NVME_CMB_BIR 2
 #define NVME_PMR_BIR 2
 #define NVME_TEMPERATURE 0x143
@@ -2152,6 +2153,7 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice 
*pci_dev)
 id->ieee[0] = 0x00;
 id->ieee[1] = 0x02;
 id->ieee[2] = 0xb3;
+id->ver = cpu_to_le32(NVME_SPEC_VER);
 id->oacs = cpu_to_le16(0);
 
 /*
@@ -2198,7 +2200,7 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice 
*pci_dev)
 NVME_CAP_SET_CSS(n->bar.cap, 1);
 NVME_CAP_SET_MPSMAX(n->bar.cap, 4);
 
-n->bar.vs = 0x00010200;
+n->bar.vs = NVME_SPEC_VER;
 n->bar.intmc = n->bar.intms = 0;
 }
 
-- 
2.27.0




[PATCH v3 13/18] hw/block/nvme: make sure ncqr and nsqr is valid

2020-07-05 Thread Klaus Jensen
From: Klaus Jensen 

0x is not an allowed value for NCQR and NSQR in Set Features on
Number of Queues.

Signed-off-by: Klaus Jensen 
Acked-by: Keith Busch 
Reviewed-by: Maxim Levitsky 
Reviewed-by: Dmitry Fomichev 
---
 hw/block/nvme.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index df8b786e4875..37e4fd8dfce1 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -1295,6 +1295,14 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeCmd 
*cmd, NvmeRequest *req)
 blk_set_enable_write_cache(n->conf.blk, dw11 & 1);
 break;
 case NVME_NUMBER_OF_QUEUES:
+/*
+ * NVMe v1.3, Section 5.21.1.7: 0x is not an allowed value for NCQR
+ * and NSQR.
+ */
+if ((dw11 & 0x) == 0x || ((dw11 >> 16) & 0x) == 0x) {
+return NVME_INVALID_FIELD | NVME_DNR;
+}
+
 trace_pci_nvme_setfeat_numq((dw11 & 0x) + 1,
 ((dw11 >> 16) & 0x) + 1,
 n->params.max_ioqpairs,
-- 
2.27.0




[PATCH v3 09/18] hw/block/nvme: move NvmeFeatureVal into hw/block/nvme.h

2020-07-05 Thread Klaus Jensen
From: Klaus Jensen 

The NvmeFeatureVal does not belong with the spec-related data structures
in include/block/nvme.h that is shared between the block-level nvme
driver and the emulated nvme device.

Move it into the nvme device specific header file as it is the only
user of the structure. Also, remove the unused members.

Signed-off-by: Klaus Jensen 
Reviewed-by: Dmitry Fomichev 
---
 hw/block/nvme.h  |  8 
 include/block/nvme.h | 17 -
 2 files changed, 8 insertions(+), 17 deletions(-)

diff --git a/hw/block/nvme.h b/hw/block/nvme.h
index 1837233617bb..b93067c9e4a1 100644
--- a/hw/block/nvme.h
+++ b/hw/block/nvme.h
@@ -79,6 +79,14 @@ static inline uint8_t nvme_ns_lbads(NvmeNamespace *ns)
 #define NVME(obj) \
 OBJECT_CHECK(NvmeCtrl, (obj), TYPE_NVME)
 
+typedef struct NvmeFeatureVal {
+struct {
+uint16_t temp_thresh_hi;
+uint16_t temp_thresh_low;
+};
+uint32_tasync_config;
+} NvmeFeatureVal;
+
 typedef struct NvmeCtrl {
 PCIDeviceparent_obj;
 MemoryRegion iomem;
diff --git a/include/block/nvme.h b/include/block/nvme.h
index 2101292ed5e8..0dce15af6bcf 100644
--- a/include/block/nvme.h
+++ b/include/block/nvme.h
@@ -865,23 +865,6 @@ enum NvmeIdCtrlLpa {
 #define NVME_CTRL_SGLS_MPTR_SGL(0x1 << 19)
 #define NVME_CTRL_SGLS_ADDR_OFFSET (0x1 << 20)
 
-typedef struct NvmeFeatureVal {
-uint32_tarbitration;
-uint32_tpower_mgmt;
-struct {
-uint16_t temp_thresh_hi;
-uint16_t temp_thresh_low;
-};
-uint32_terr_rec;
-uint32_tvolatile_wc;
-uint32_tnum_queues;
-uint32_tint_coalescing;
-uint32_t*int_vector_config;
-uint32_twrite_atomicity;
-uint32_tasync_config;
-uint32_tsw_prog_marker;
-} NvmeFeatureVal;
-
 #define NVME_ARB_AB(arb)(arb & 0x7)
 #define NVME_ARB_LPW(arb)   ((arb >> 8) & 0xff)
 #define NVME_ARB_MPW(arb)   ((arb >> 16) & 0xff)
-- 
2.27.0




[PATCH v3 15/18] hw/block/nvme: reject invalid nsid values in active namespace id list

2020-07-05 Thread Klaus Jensen
From: Klaus Jensen 

Reject the nsid broadcast value (0x) and 0xfffe in the
Active Namespace ID list.

Signed-off-by: Klaus Jensen 
---
 hw/block/nvme.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index fc58f3d76530..af39126cd8d1 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -992,6 +992,16 @@ static uint16_t nvme_identify_nslist(NvmeCtrl *n, 
NvmeIdentify *c)
 
 trace_pci_nvme_identify_nslist(min_nsid);
 
+/*
+ * Both 0x (NVME_NSID_BROADCAST) and 0xfffe are invalid values
+ * since the Active Namespace ID List should return namespaces with ids
+ * *higher* than the NSID specified in the command. This is also specified
+ * in the spec (NVM Express v1.3d, Section 5.15.4).
+ */
+if (min_nsid >= NVME_NSID_BROADCAST - 1) {
+return NVME_INVALID_NSID | NVME_DNR;
+}
+
 list = g_malloc0(data_len);
 for (i = 0; i < n->num_namespaces; i++) {
 if (i < min_nsid) {
-- 
2.27.0




[PATCH v3 08/18] hw/block/nvme: add support for the asynchronous event request command

2020-07-05 Thread Klaus Jensen
From: Klaus Jensen 

Add support for the Asynchronous Event Request command. Required for
compliance with NVMe revision 1.3d. See NVM Express 1.3d, Section 5.2
("Asynchronous Event Request command").

Mostly imported from Keith's qemu-nvme tree. Modified with a max number
of queued events (controllable with the aer_max_queued device
parameter). The spec states that the controller *should* retain
events, so we do best effort here.

Signed-off-by: Klaus Jensen 
Signed-off-by: Klaus Jensen 
Acked-by: Keith Busch 
Reviewed-by: Maxim Levitsky 
Reviewed-by: Dmitry Fomichev 
---
 hw/block/nvme.c   | 180 --
 hw/block/nvme.h   |  10 ++-
 hw/block/trace-events |   9 +++
 include/block/nvme.h  |   8 +-
 4 files changed, 198 insertions(+), 9 deletions(-)

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 7cb3787638f6..80c7285bc1cf 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -356,6 +356,85 @@ static void nvme_enqueue_req_completion(NvmeCQueue *cq, 
NvmeRequest *req)
 timer_mod(cq->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 500);
 }
 
+static void nvme_process_aers(void *opaque)
+{
+NvmeCtrl *n = opaque;
+NvmeAsyncEvent *event, *next;
+
+trace_pci_nvme_process_aers(n->aer_queued);
+
+QTAILQ_FOREACH_SAFE(event, &n->aer_queue, entry, next) {
+NvmeRequest *req;
+NvmeAerResult *result;
+
+/* can't post cqe if there is nothing to complete */
+if (!n->outstanding_aers) {
+trace_pci_nvme_no_outstanding_aers();
+break;
+}
+
+/* ignore if masked (cqe posted, but event not cleared) */
+if (n->aer_mask & (1 << event->result.event_type)) {
+trace_pci_nvme_aer_masked(event->result.event_type, n->aer_mask);
+continue;
+}
+
+QTAILQ_REMOVE(&n->aer_queue, event, entry);
+n->aer_queued--;
+
+n->aer_mask |= 1 << event->result.event_type;
+n->outstanding_aers--;
+
+req = n->aer_reqs[n->outstanding_aers];
+
+result = (NvmeAerResult *) &req->cqe.result;
+result->event_type = event->result.event_type;
+result->event_info = event->result.event_info;
+result->log_page = event->result.log_page;
+g_free(event);
+
+req->status = NVME_SUCCESS;
+
+trace_pci_nvme_aer_post_cqe(result->event_type, result->event_info,
+result->log_page);
+
+nvme_enqueue_req_completion(&n->admin_cq, req);
+}
+}
+
+static void nvme_enqueue_event(NvmeCtrl *n, uint8_t event_type,
+   uint8_t event_info, uint8_t log_page)
+{
+NvmeAsyncEvent *event;
+
+trace_pci_nvme_enqueue_event(event_type, event_info, log_page);
+
+if (n->aer_queued == n->params.aer_max_queued) {
+trace_pci_nvme_enqueue_event_noqueue(n->aer_queued);
+return;
+}
+
+event = g_new(NvmeAsyncEvent, 1);
+event->result = (NvmeAerResult) {
+.event_type = event_type,
+.event_info = event_info,
+.log_page   = log_page,
+};
+
+QTAILQ_INSERT_TAIL(&n->aer_queue, event, entry);
+n->aer_queued++;
+
+nvme_process_aers(n);
+}
+
+static void nvme_clear_events(NvmeCtrl *n, uint8_t event_type)
+{
+n->aer_mask &= ~(1 << event_type);
+if (!QTAILQ_EMPTY(&n->aer_queue)) {
+nvme_process_aers(n);
+}
+}
+
 static void nvme_rw_cb(void *opaque, int ret)
 {
 NvmeRequest *req = opaque;
@@ -606,8 +685,9 @@ static uint16_t nvme_create_sq(NvmeCtrl *n, NvmeCmd *cmd)
 return NVME_SUCCESS;
 }
 
-static uint16_t nvme_smart_info(NvmeCtrl *n, NvmeCmd *cmd, uint32_t buf_len,
-uint64_t off, NvmeRequest *req)
+static uint16_t nvme_smart_info(NvmeCtrl *n, NvmeCmd *cmd, uint8_t rae,
+uint32_t buf_len, uint64_t off,
+NvmeRequest *req)
 {
 uint64_t prp1 = le64_to_cpu(cmd->dptr.prp1);
 uint64_t prp2 = le64_to_cpu(cmd->dptr.prp2);
@@ -655,6 +735,10 @@ static uint16_t nvme_smart_info(NvmeCtrl *n, NvmeCmd *cmd, 
uint32_t buf_len,
 smart.power_on_hours[0] =
 cpu_to_le64current_ms - n->starttime_ms) / 1000) / 60) / 60);
 
+if (!rae) {
+nvme_clear_events(n, NVME_AER_TYPE_SMART);
+}
+
 return nvme_dma_read_prp(n, (uint8_t *) &smart + off, trans_len, prp1,
  prp2);
 }
@@ -681,14 +765,19 @@ static uint16_t nvme_fw_log_info(NvmeCtrl *n, NvmeCmd 
*cmd, uint32_t buf_len,
  prp2);
 }
 
-static uint16_t nvme_error_info(NvmeCtrl *n, NvmeCmd *cmd, uint32_t buf_len,
-uint64_t off, NvmeRequest *req)
+static uint16_t nvme_error_info(NvmeCtrl *n, NvmeCmd *cmd, uint8_t rae,
+uint32_t buf_len, uint64_t off,
+NvmeRequest *req)
 {
 uint32_t trans_len;
 uint64_t prp1 = le64_to_cpu(cmd->dptr.prp1);
 uint64_t prp2

[PATCH v3 14/18] hw/block/nvme: support identify namespace descriptor list

2020-07-05 Thread Klaus Jensen
From: Klaus Jensen 

Since we are not providing the NGUID or EUI64 fields, we must support
the Namespace UUID. We do not have any way of storing a persistent
unique identifier, so conjure up a UUID that is just the namespace id.

Signed-off-by: Klaus Jensen 
Reviewed-by: Dmitry Fomichev 
---
 hw/block/nvme.c   | 41 +
 hw/block/trace-events |  1 +
 2 files changed, 42 insertions(+)

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 37e4fd8dfce1..fc58f3d76530 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -1007,6 +1007,45 @@ static uint16_t nvme_identify_nslist(NvmeCtrl *n, 
NvmeIdentify *c)
 return ret;
 }
 
+static uint16_t nvme_identify_ns_descr_list(NvmeCtrl *n, NvmeIdentify *c)
+{
+uint32_t nsid = le32_to_cpu(c->nsid);
+uint64_t prp1 = le64_to_cpu(c->prp1);
+uint64_t prp2 = le64_to_cpu(c->prp2);
+
+uint8_t list[NVME_IDENTIFY_DATA_SIZE];
+
+struct data {
+struct {
+NvmeIdNsDescr hdr;
+uint8_t v[16];
+} uuid;
+};
+
+struct data *ns_descrs = (struct data *)list;
+
+trace_pci_nvme_identify_ns_descr_list(nsid);
+
+if (unlikely(nsid == 0 || nsid > n->num_namespaces)) {
+trace_pci_nvme_err_invalid_ns(nsid, n->num_namespaces);
+return NVME_INVALID_NSID | NVME_DNR;
+}
+
+memset(list, 0x0, sizeof(list));
+
+/*
+ * Because the NGUID and EUI64 fields are 0 in the Identify Namespace data
+ * structure, a Namespace UUID (nidt = 0x3) must be reported in the
+ * Namespace Identification Descriptor. Add a very basic Namespace UUID
+ * here.
+ */
+ns_descrs->uuid.hdr.nidt = NVME_NIDT_UUID;
+ns_descrs->uuid.hdr.nidl = NVME_NIDT_UUID_LEN;
+stl_be_p(&ns_descrs->uuid.v, nsid);
+
+return nvme_dma_read_prp(n, list, NVME_IDENTIFY_DATA_SIZE, prp1, prp2);
+}
+
 static uint16_t nvme_identify(NvmeCtrl *n, NvmeCmd *cmd)
 {
 NvmeIdentify *c = (NvmeIdentify *)cmd;
@@ -1018,6 +1057,8 @@ static uint16_t nvme_identify(NvmeCtrl *n, NvmeCmd *cmd)
 return nvme_identify_ctrl(n, c);
 case NVME_ID_CNS_NS_ACTIVE_LIST:
 return nvme_identify_nslist(n, c);
+case NVME_ID_CNS_NS_DESCR_LIST:
+return nvme_identify_ns_descr_list(n, c);
 default:
 trace_pci_nvme_err_invalid_identify_cns(le32_to_cpu(c->cns));
 return NVME_INVALID_FIELD | NVME_DNR;
diff --git a/hw/block/trace-events b/hw/block/trace-events
index 4a4ef34071df..7b7303cab1dd 100644
--- a/hw/block/trace-events
+++ b/hw/block/trace-events
@@ -45,6 +45,7 @@ pci_nvme_del_cq(uint16_t cqid) "deleted completion queue, 
cqid=%"PRIu16""
 pci_nvme_identify_ctrl(void) "identify controller"
 pci_nvme_identify_ns(uint32_t ns) "nsid %"PRIu32""
 pci_nvme_identify_nslist(uint32_t ns) "nsid %"PRIu32""
+pci_nvme_identify_ns_descr_list(uint32_t ns) "nsid %"PRIu32""
 pci_nvme_get_log(uint16_t cid, uint8_t lid, uint8_t lsp, uint8_t rae, uint32_t 
len, uint64_t off) "cid %"PRIu16" lid 0x%"PRIx8" lsp 0x%"PRIx8" rae 0x%"PRIx8" 
len %"PRIu32" off %"PRIu64""
 pci_nvme_getfeat(uint16_t cid, uint8_t fid, uint8_t sel, uint32_t cdw11) "cid 
%"PRIu16" fid 0x%"PRIx8" sel 0x%"PRIx8" cdw11 0x%"PRIx32""
 pci_nvme_setfeat(uint16_t cid, uint8_t fid, uint8_t save, uint32_t cdw11) "cid 
%"PRIu16" fid 0x%"PRIx8" save 0x%"PRIx8" cdw11 0x%"PRIx32""
-- 
2.27.0




[PATCH v3 01/18] hw/block/nvme: bump spec data structures to v1.3

2020-07-05 Thread Klaus Jensen
From: Klaus Jensen 

Add missing fields in the Identify Controller and Identify Namespace
data structures to bring them in line with NVMe v1.3.

This also adds data structures and defines for SGL support which
requires a couple of trivial changes to the nvme block driver as well.

Signed-off-by: Klaus Jensen 
Acked-by: Fam Zheng 
Reviewed-by: Maxim Levitsky 
---
 block/nvme.c |  18 ++---
 hw/block/nvme.c  |  12 ++--
 include/block/nvme.h | 156 ++-
 3 files changed, 154 insertions(+), 32 deletions(-)

diff --git a/block/nvme.c b/block/nvme.c
index 374e26891573..c1c4c07ac6cc 100644
--- a/block/nvme.c
+++ b/block/nvme.c
@@ -518,7 +518,7 @@ static void nvme_identify(BlockDriverState *bs, int 
namespace, Error **errp)
 error_setg(errp, "Cannot map buffer for DMA");
 goto out;
 }
-cmd.prp1 = cpu_to_le64(iova);
+cmd.dptr.prp1 = cpu_to_le64(iova);
 
 if (nvme_cmd_sync(bs, s->queues[0], &cmd)) {
 error_setg(errp, "Failed to identify controller");
@@ -629,7 +629,7 @@ static bool nvme_add_io_queue(BlockDriverState *bs, Error 
**errp)
 }
 cmd = (NvmeCmd) {
 .opcode = NVME_ADM_CMD_CREATE_CQ,
-.prp1 = cpu_to_le64(q->cq.iova),
+.dptr.prp1 = cpu_to_le64(q->cq.iova),
 .cdw10 = cpu_to_le32(((queue_size - 1) << 16) | (n & 0x)),
 .cdw11 = cpu_to_le32(0x3),
 };
@@ -640,7 +640,7 @@ static bool nvme_add_io_queue(BlockDriverState *bs, Error 
**errp)
 }
 cmd = (NvmeCmd) {
 .opcode = NVME_ADM_CMD_CREATE_SQ,
-.prp1 = cpu_to_le64(q->sq.iova),
+.dptr.prp1 = cpu_to_le64(q->sq.iova),
 .cdw10 = cpu_to_le32(((queue_size - 1) << 16) | (n & 0x)),
 .cdw11 = cpu_to_le32(0x1 | (n << 16)),
 };
@@ -988,16 +988,16 @@ try_map:
 case 0:
 abort();
 case 1:
-cmd->prp1 = pagelist[0];
-cmd->prp2 = 0;
+cmd->dptr.prp1 = pagelist[0];
+cmd->dptr.prp2 = 0;
 break;
 case 2:
-cmd->prp1 = pagelist[0];
-cmd->prp2 = pagelist[1];
+cmd->dptr.prp1 = pagelist[0];
+cmd->dptr.prp2 = pagelist[1];
 break;
 default:
-cmd->prp1 = pagelist[0];
-cmd->prp2 = cpu_to_le64(req->prp_list_iova + sizeof(uint64_t));
+cmd->dptr.prp1 = pagelist[0];
+cmd->dptr.prp2 = cpu_to_le64(req->prp_list_iova + sizeof(uint64_t));
 break;
 }
 trace_nvme_cmd_map_qiov(s, cmd, req, qiov, entries);
diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 1aee042d4cb2..71b388aa0e20 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -397,8 +397,8 @@ static uint16_t nvme_rw(NvmeCtrl *n, NvmeNamespace *ns, 
NvmeCmd *cmd,
 NvmeRwCmd *rw = (NvmeRwCmd *)cmd;
 uint32_t nlb  = le32_to_cpu(rw->nlb) + 1;
 uint64_t slba = le64_to_cpu(rw->slba);
-uint64_t prp1 = le64_to_cpu(rw->prp1);
-uint64_t prp2 = le64_to_cpu(rw->prp2);
+uint64_t prp1 = le64_to_cpu(rw->dptr.prp1);
+uint64_t prp2 = le64_to_cpu(rw->dptr.prp2);
 
 uint8_t lba_index  = NVME_ID_NS_FLBAS_INDEX(ns->id_ns.flbas);
 uint8_t data_shift = ns->id_ns.lbaf[lba_index].ds;
@@ -795,8 +795,8 @@ static inline uint64_t nvme_get_timestamp(const NvmeCtrl *n)
 
 static uint16_t nvme_get_feature_timestamp(NvmeCtrl *n, NvmeCmd *cmd)
 {
-uint64_t prp1 = le64_to_cpu(cmd->prp1);
-uint64_t prp2 = le64_to_cpu(cmd->prp2);
+uint64_t prp1 = le64_to_cpu(cmd->dptr.prp1);
+uint64_t prp2 = le64_to_cpu(cmd->dptr.prp2);
 
 uint64_t timestamp = nvme_get_timestamp(n);
 
@@ -834,8 +834,8 @@ static uint16_t nvme_set_feature_timestamp(NvmeCtrl *n, 
NvmeCmd *cmd)
 {
 uint16_t ret;
 uint64_t timestamp;
-uint64_t prp1 = le64_to_cpu(cmd->prp1);
-uint64_t prp2 = le64_to_cpu(cmd->prp2);
+uint64_t prp1 = le64_to_cpu(cmd->dptr.prp1);
+uint64_t prp2 = le64_to_cpu(cmd->dptr.prp2);
 
 ret = nvme_dma_write_prp(n, (uint8_t *)×tamp,
 sizeof(timestamp), prp1, prp2);
diff --git a/include/block/nvme.h b/include/block/nvme.h
index 1720ee1d5158..2a80d2a7ed89 100644
--- a/include/block/nvme.h
+++ b/include/block/nvme.h
@@ -377,15 +377,53 @@ enum NvmePmrmscMask {
 #define NVME_PMRMSC_SET_CBA(pmrmsc, val)   \
 (pmrmsc |= (uint64_t)(val & PMRMSC_CBA_MASK) << PMRMSC_CBA_SHIFT)
 
+enum NvmeSglDescriptorType {
+NVME_SGL_DESCR_TYPE_DATA_BLOCK  = 0x0,
+NVME_SGL_DESCR_TYPE_BIT_BUCKET  = 0x1,
+NVME_SGL_DESCR_TYPE_SEGMENT = 0x2,
+NVME_SGL_DESCR_TYPE_LAST_SEGMENT= 0x3,
+NVME_SGL_DESCR_TYPE_KEYED_DATA_BLOCK= 0x4,
+
+NVME_SGL_DESCR_TYPE_VENDOR_SPECIFIC = 0xf,
+};
+
+enum NvmeSglDescriptorSubtype {
+NVME_SGL_DESCR_SUBTYPE_ADDRESS = 0x0,
+};
+
+typedef struct NvmeSglDescriptor {
+uint64_t addr;
+uint32_t len;
+uint8_t  rsvd[3];
+uint8_t  type;
+} NvmeSglDescriptor;
+
+#define NVME_SGL_TYPE(type) ((type >> 4) & 0xf)
+#define NVME_SGL_SUBTYPE(type)  (type & 0xf)
+
+typ

[PATCH v3 16/18] hw/block/nvme: enforce valid queue creation sequence

2020-07-05 Thread Klaus Jensen
From: Klaus Jensen 

Support returning Command Sequence Error if Set Features on Number of
Queues is called after queues have been created.

Signed-off-by: Klaus Jensen 
Reviewed-by: Maxim Levitsky 
Reviewed-by: Dmitry Fomichev 
---
 hw/block/nvme.c | 12 
 hw/block/nvme.h |  1 +
 2 files changed, 13 insertions(+)

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index af39126cd8d1..07d58aa945f2 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -946,6 +946,13 @@ static uint16_t nvme_create_cq(NvmeCtrl *n, NvmeCmd *cmd)
 cq = g_malloc0(sizeof(*cq));
 nvme_init_cq(cq, n, prp1, cqid, vector, qsize + 1,
 NVME_CQ_FLAGS_IEN(qflags));
+
+/*
+ * It is only required to set qs_created when creating a completion queue;
+ * creating a submission queue without a matching completion queue will
+ * fail.
+ */
+n->qs_created = true;
 return NVME_SUCCESS;
 }
 
@@ -1346,6 +1353,10 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeCmd 
*cmd, NvmeRequest *req)
 blk_set_enable_write_cache(n->conf.blk, dw11 & 1);
 break;
 case NVME_NUMBER_OF_QUEUES:
+if (n->qs_created) {
+return NVME_CMD_SEQ_ERROR | NVME_DNR;
+}
+
 /*
  * NVMe v1.3, Section 5.21.1.7: 0x is not an allowed value for NCQR
  * and NSQR.
@@ -1478,6 +1489,7 @@ static void nvme_clear_ctrl(NvmeCtrl *n)
 
 n->aer_queued = 0;
 n->outstanding_aers = 0;
+n->qs_created = false;
 
 blk_flush(n->conf.blk);
 n->bar.cc = 0;
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
index b93067c9e4a1..0b6a8ae66559 100644
--- a/hw/block/nvme.h
+++ b/hw/block/nvme.h
@@ -95,6 +95,7 @@ typedef struct NvmeCtrl {
 BlockConfconf;
 NvmeParams   params;
 
+boolqs_created;
 uint32_tpage_size;
 uint16_tpage_bits;
 uint16_tmax_prp_ents;
-- 
2.27.0




[PATCH v3 17/18] hw/block/nvme: provide the mandatory subnqn field

2020-07-05 Thread Klaus Jensen
From: Klaus Jensen 

The SUBNQN field is mandatory in NVM Express 1.3.

Signed-off-by: Klaus Jensen 
---
 hw/block/nvme.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 07d58aa945f2..e3984157926b 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -2141,6 +2141,7 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice 
*pci_dev)
 {
 NvmeIdCtrl *id = &n->id_ctrl;
 uint8_t *pci_conf = pci_dev->config;
+char *subnqn;
 
 id->vid = cpu_to_le16(pci_get_word(pci_conf + PCI_VENDOR_ID));
 id->ssvid = cpu_to_le16(pci_get_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID));
@@ -2179,6 +2180,10 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice 
*pci_dev)
 id->oncs = cpu_to_le16(NVME_ONCS_WRITE_ZEROS | NVME_ONCS_TIMESTAMP |
NVME_ONCS_FEATURES);
 
+subnqn = g_strdup_printf("nqn.2019-08.org.qemu:%s", n->params.serial);
+strpadcpy((char *)id->subnqn, sizeof(id->subnqn), subnqn, '\0');
+g_free(subnqn);
+
 id->psd[0].mp = cpu_to_le16(0x9c4);
 id->psd[0].enlat = cpu_to_le32(0x10);
 id->psd[0].exlat = cpu_to_le32(0x4);
-- 
2.27.0




[PATCH v3 11/18] hw/block/nvme: add remaining mandatory controller parameters

2020-07-05 Thread Klaus Jensen
From: Klaus Jensen 

Add support for any remaining mandatory controller operating parameters
(features).

Signed-off-by: Klaus Jensen 
Reviewed-by: Dmitry Fomichev 
---
 hw/block/nvme.c   | 56 ++-
 hw/block/trace-events |  2 ++
 include/block/nvme.h  | 10 +++-
 3 files changed, 61 insertions(+), 7 deletions(-)

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 8fce2ebf69e7..2d85e853403f 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -71,6 +71,20 @@
 " in %s: " fmt "\n", __func__, ## __VA_ARGS__); \
 } while (0)
 
+static const bool nvme_feature_support[NVME_FID_MAX] = {
+[NVME_ARBITRATION]  = true,
+[NVME_POWER_MANAGEMENT] = true,
+[NVME_TEMPERATURE_THRESHOLD]= true,
+[NVME_ERROR_RECOVERY]   = true,
+[NVME_VOLATILE_WRITE_CACHE] = true,
+[NVME_NUMBER_OF_QUEUES] = true,
+[NVME_INTERRUPT_COALESCING] = true,
+[NVME_INTERRUPT_VECTOR_CONF]= true,
+[NVME_WRITE_ATOMICITY]  = true,
+[NVME_ASYNCHRONOUS_EVENT_CONF]  = true,
+[NVME_TIMESTAMP]= true,
+};
+
 static void nvme_process_sq(void *opaque);
 
 static uint16_t nvme_cid(NvmeRequest *req)
@@ -1070,8 +1084,20 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd 
*cmd, NvmeRequest *req)
 uint32_t dw10 = le32_to_cpu(cmd->cdw10);
 uint32_t dw11 = le32_to_cpu(cmd->cdw11);
 uint32_t result;
+uint8_t fid = NVME_GETSETFEAT_FID(dw10);
+uint16_t iv;
 
-switch (dw10) {
+static const uint32_t nvme_feature_default[NVME_FID_MAX] = {
+[NVME_ARBITRATION] = NVME_ARB_AB_NOLIMIT,
+};
+
+trace_pci_nvme_getfeat(nvme_cid(req), fid, dw11);
+
+if (!nvme_feature_support[fid]) {
+return NVME_INVALID_FIELD | NVME_DNR;
+}
+
+switch (fid) {
 case NVME_TEMPERATURE_THRESHOLD:
 result = 0;
 
@@ -1101,6 +1127,18 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd 
*cmd, NvmeRequest *req)
 result = (n->params.max_ioqpairs - 1) |
 ((n->params.max_ioqpairs - 1) << 16);
 trace_pci_nvme_getfeat_numq(result);
+break;
+case NVME_INTERRUPT_VECTOR_CONF:
+iv = dw11 & 0x;
+if (iv >= n->params.max_ioqpairs + 1) {
+return NVME_INVALID_FIELD | NVME_DNR;
+}
+
+result = iv;
+if (iv == n->admin_cq.vector) {
+result |= NVME_INTVC_NOCOALESCING;
+}
+
 break;
 case NVME_ASYNCHRONOUS_EVENT_CONF:
 result = n->features.async_config;
@@ -1108,8 +1146,8 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd 
*cmd, NvmeRequest *req)
 case NVME_TIMESTAMP:
 return nvme_get_feature_timestamp(n, cmd);
 default:
-trace_pci_nvme_err_invalid_getfeat(dw10);
-return NVME_INVALID_FIELD | NVME_DNR;
+result = nvme_feature_default[fid];
+break;
 }
 
 req->cqe.result = cpu_to_le32(result);
@@ -1138,8 +1176,15 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeCmd 
*cmd, NvmeRequest *req)
 {
 uint32_t dw10 = le32_to_cpu(cmd->cdw10);
 uint32_t dw11 = le32_to_cpu(cmd->cdw11);
+uint8_t fid = NVME_GETSETFEAT_FID(dw10);
 
-switch (dw10) {
+trace_pci_nvme_setfeat(nvme_cid(req), fid, dw11);
+
+if (!nvme_feature_support[fid]) {
+return NVME_INVALID_FIELD | NVME_DNR;
+}
+
+switch (fid) {
 case NVME_TEMPERATURE_THRESHOLD:
 if (NVME_TEMP_TMPSEL(dw11) != NVME_TEMP_TMPSEL_COMPOSITE) {
 break;
@@ -1186,8 +1231,7 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeCmd 
*cmd, NvmeRequest *req)
 case NVME_TIMESTAMP:
 return nvme_set_feature_timestamp(n, cmd);
 default:
-trace_pci_nvme_err_invalid_setfeat(dw10);
-return NVME_INVALID_FIELD | NVME_DNR;
+return NVME_FEAT_NOT_CHANGEABLE | NVME_DNR;
 }
 return NVME_SUCCESS;
 }
diff --git a/hw/block/trace-events b/hw/block/trace-events
index 091af16ca7d7..42e62f4649f8 100644
--- a/hw/block/trace-events
+++ b/hw/block/trace-events
@@ -46,6 +46,8 @@ pci_nvme_identify_ctrl(void) "identify controller"
 pci_nvme_identify_ns(uint32_t ns) "nsid %"PRIu32""
 pci_nvme_identify_nslist(uint32_t ns) "nsid %"PRIu32""
 pci_nvme_get_log(uint16_t cid, uint8_t lid, uint8_t lsp, uint8_t rae, uint32_t 
len, uint64_t off) "cid %"PRIu16" lid 0x%"PRIx8" lsp 0x%"PRIx8" rae 0x%"PRIx8" 
len %"PRIu32" off %"PRIu64""
+pci_nvme_getfeat(uint16_t cid, uint8_t fid, uint32_t cdw11) "cid %"PRIu16" fid 
0x%"PRIx8" cdw11 0x%"PRIx32""
+pci_nvme_setfeat(uint16_t cid, uint8_t fid, uint32_t cdw11) "cid %"PRIu16" fid 
0x%"PRIx8" cdw11 0x%"PRIx32""
 pci_nvme_getfeat_vwcache(const char* result) "get feature volatile write 
cache, result=%s"
 pci_nvme_getfeat_numq(int result) "get feature number of queues, result=%d"
 pci_nvme_setfeat_numq(int reqcq, int reqsq, int gotcq, int gotsq) "requested 
cq_count=%d sq_count=%d, responding with cq_count=%d sq_count=%d"
diff --git a/incl

[PATCH v3 06/18] hw/block/nvme: mark fw slot 1 as read-only

2020-07-05 Thread Klaus Jensen
From: Klaus Jensen 

Mark firmware slot 1 as read-only and only support that slot.

Signed-off-by: Klaus Jensen 
Reviewed-by: Dmitry Fomichev 
---
 hw/block/nvme.c  | 3 ++-
 include/block/nvme.h | 4 
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index a330ccf91620..b6bc75eb61a2 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -62,6 +62,7 @@
 #define NVME_TEMPERATURE 0x143
 #define NVME_TEMPERATURE_WARNING 0x157
 #define NVME_TEMPERATURE_CRITICAL 0x175
+#define NVME_NUM_FW_SLOTS 1
 
 #define NVME_GUEST_ERR(trace, fmt, ...) \
 do { \
@@ -1666,7 +1667,7 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice 
*pci_dev)
  * inconsequential.
  */
 id->acl = 3;
-id->frmw = 7 << 1;
+id->frmw = (NVME_NUM_FW_SLOTS << 1) | NVME_FRMW_SLOT1_RO;
 id->lpa = 1 << 0;
 
 /* recommended default value (~70 C) */
diff --git a/include/block/nvme.h b/include/block/nvme.h
index d2c457695b38..d639e8bbee92 100644
--- a/include/block/nvme.h
+++ b/include/block/nvme.h
@@ -842,6 +842,10 @@ enum NvmeIdCtrlOncs {
 NVME_ONCS_TIMESTAMP = 1 << 6,
 };
 
+enum NvmeIdCtrlFrmw {
+NVME_FRMW_SLOT1_RO = 1 << 0,
+};
+
 #define NVME_CTRL_SQES_MIN(sqes) ((sqes) & 0xf)
 #define NVME_CTRL_SQES_MAX(sqes) (((sqes) >> 4) & 0xf)
 #define NVME_CTRL_CQES_MIN(cqes) ((cqes) & 0xf)
-- 
2.27.0




[PATCH v3 10/18] hw/block/nvme: flush write cache when disabled

2020-07-05 Thread Klaus Jensen
From: Klaus Jensen 

If the write cache is disabled with a Set Features command, flush it if
currently enabled.

Signed-off-by: Klaus Jensen 
Reviewed-by: Dmitry Fomichev 
---
 hw/block/nvme.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 80c7285bc1cf..8fce2ebf69e7 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -1166,6 +1166,10 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeCmd 
*cmd, NvmeRequest *req)
 
 break;
 case NVME_VOLATILE_WRITE_CACHE:
+if (!(dw11 & 0x1) && blk_enable_write_cache(n->conf.blk)) {
+blk_flush(n->conf.blk);
+}
+
 blk_set_enable_write_cache(n->conf.blk, dw11 & 1);
 break;
 case NVME_NUMBER_OF_QUEUES:
-- 
2.27.0




[PATCH v3 12/18] hw/block/nvme: support the get/set features select and save fields

2020-07-05 Thread Klaus Jensen
From: Klaus Jensen 

Since the device does not have any persistent state storage, no
features are "saveable" and setting the Save (SV) field in any Set
Features command will result in a Feature Identifier Not Saveable status
code.

Similarly, if the Select (SEL) field is set to request saved values, the
devices will (as it should) return the default values instead.

Since this also introduces "Supported Capabilities", the nsid field is
now also checked for validity wrt. the feature being get/set'ed.

Signed-off-by: Klaus Jensen 
---
 hw/block/nvme.c   | 103 +-
 hw/block/trace-events |   4 +-
 include/block/nvme.h  |  27 ++-
 3 files changed, 119 insertions(+), 15 deletions(-)

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 2d85e853403f..df8b786e4875 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -85,6 +85,14 @@ static const bool nvme_feature_support[NVME_FID_MAX] = {
 [NVME_TIMESTAMP]= true,
 };
 
+static const uint32_t nvme_feature_cap[NVME_FID_MAX] = {
+[NVME_TEMPERATURE_THRESHOLD]= NVME_FEAT_CAP_CHANGE,
+[NVME_VOLATILE_WRITE_CACHE] = NVME_FEAT_CAP_CHANGE,
+[NVME_NUMBER_OF_QUEUES] = NVME_FEAT_CAP_CHANGE,
+[NVME_ASYNCHRONOUS_EVENT_CONF]  = NVME_FEAT_CAP_CHANGE,
+[NVME_TIMESTAMP]= NVME_FEAT_CAP_CHANGE,
+};
+
 static void nvme_process_sq(void *opaque);
 
 static uint16_t nvme_cid(NvmeRequest *req)
@@ -1083,20 +1091,47 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd 
*cmd, NvmeRequest *req)
 {
 uint32_t dw10 = le32_to_cpu(cmd->cdw10);
 uint32_t dw11 = le32_to_cpu(cmd->cdw11);
+uint32_t nsid = le32_to_cpu(cmd->nsid);
 uint32_t result;
 uint8_t fid = NVME_GETSETFEAT_FID(dw10);
+NvmeGetFeatureSelect sel = NVME_GETFEAT_SELECT(dw10);
 uint16_t iv;
 
 static const uint32_t nvme_feature_default[NVME_FID_MAX] = {
 [NVME_ARBITRATION] = NVME_ARB_AB_NOLIMIT,
 };
 
-trace_pci_nvme_getfeat(nvme_cid(req), fid, dw11);
+trace_pci_nvme_getfeat(nvme_cid(req), fid, sel, dw11);
 
 if (!nvme_feature_support[fid]) {
 return NVME_INVALID_FIELD | NVME_DNR;
 }
 
+if (nvme_feature_cap[fid] & NVME_FEAT_CAP_NS) {
+if (!nsid || nsid > n->num_namespaces) {
+/*
+ * The Reservation Notification Mask and Reservation Persistence
+ * features require a status code of Invalid Field in Command when
+ * NSID is 0x. Since the device does not support those
+ * features we can always return Invalid Namespace or Format as we
+ * should do for all other features.
+ */
+return NVME_INVALID_NSID | NVME_DNR;
+}
+}
+
+switch (sel) {
+case NVME_GETFEAT_SELECT_CURRENT:
+break;
+case NVME_GETFEAT_SELECT_SAVED:
+/* no features are saveable by the controller; fallthrough */
+case NVME_GETFEAT_SELECT_DEFAULT:
+goto defaults;
+case NVME_GETFEAT_SELECT_CAP:
+result = nvme_feature_cap[fid];
+goto out;
+}
+
 switch (fid) {
 case NVME_TEMPERATURE_THRESHOLD:
 result = 0;
@@ -1106,22 +1141,45 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd 
*cmd, NvmeRequest *req)
  * return 0 for all other sensors.
  */
 if (NVME_TEMP_TMPSEL(dw11) != NVME_TEMP_TMPSEL_COMPOSITE) {
-break;
+goto out;
 }
 
 switch (NVME_TEMP_THSEL(dw11)) {
 case NVME_TEMP_THSEL_OVER:
 result = n->features.temp_thresh_hi;
-break;
+goto out;
 case NVME_TEMP_THSEL_UNDER:
 result = n->features.temp_thresh_low;
-break;
+goto out;
 }
 
-break;
+return NVME_INVALID_FIELD | NVME_DNR;
 case NVME_VOLATILE_WRITE_CACHE:
 result = blk_enable_write_cache(n->conf.blk);
 trace_pci_nvme_getfeat_vwcache(result ? "enabled" : "disabled");
+goto out;
+case NVME_ASYNCHRONOUS_EVENT_CONF:
+result = n->features.async_config;
+goto out;
+case NVME_TIMESTAMP:
+return nvme_get_feature_timestamp(n, cmd);
+default:
+break;
+}
+
+defaults:
+switch (fid) {
+case NVME_TEMPERATURE_THRESHOLD:
+result = 0;
+
+if (NVME_TEMP_TMPSEL(dw11) != NVME_TEMP_TMPSEL_COMPOSITE) {
+break;
+}
+
+if (NVME_TEMP_THSEL(dw11) == NVME_TEMP_THSEL_OVER) {
+result = NVME_TEMPERATURE_WARNING;
+}
+
 break;
 case NVME_NUMBER_OF_QUEUES:
 result = (n->params.max_ioqpairs - 1) |
@@ -1140,16 +1198,12 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd 
*cmd, NvmeRequest *req)
 }
 
 break;
-case NVME_ASYNCHRONOUS_EVENT_CONF:
-result = n->features.async_config;
-break;
-case NVME_TIMESTAMP:
-return nvme_get_feature_timestamp(n, cmd);
 default:
 

[PATCH v3 05/18] hw/block/nvme: add temperature threshold feature

2020-07-05 Thread Klaus Jensen
From: Klaus Jensen 

It might seem weird to implement this feature for an emulated device,
but it is mandatory to support and the feature is useful for testing
asynchronous event request support, which will be added in a later
patch.

Signed-off-by: Klaus Jensen 
Acked-by: Keith Busch 
Reviewed-by: Maxim Levitsky 
---
 hw/block/nvme.c  | 48 
 hw/block/nvme.h  |  1 +
 include/block/nvme.h |  5 -
 3 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 415d3b036897..a330ccf91620 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -59,6 +59,9 @@
 #define NVME_DB_SIZE  4
 #define NVME_CMB_BIR 2
 #define NVME_PMR_BIR 2
+#define NVME_TEMPERATURE 0x143
+#define NVME_TEMPERATURE_WARNING 0x157
+#define NVME_TEMPERATURE_CRITICAL 0x175
 
 #define NVME_GUEST_ERR(trace, fmt, ...) \
 do { \
@@ -841,9 +844,31 @@ static uint16_t nvme_get_feature_timestamp(NvmeCtrl *n, 
NvmeCmd *cmd)
 static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req)
 {
 uint32_t dw10 = le32_to_cpu(cmd->cdw10);
+uint32_t dw11 = le32_to_cpu(cmd->cdw11);
 uint32_t result;
 
 switch (dw10) {
+case NVME_TEMPERATURE_THRESHOLD:
+result = 0;
+
+/*
+ * The controller only implements the Composite Temperature sensor, so
+ * return 0 for all other sensors.
+ */
+if (NVME_TEMP_TMPSEL(dw11) != NVME_TEMP_TMPSEL_COMPOSITE) {
+break;
+}
+
+switch (NVME_TEMP_THSEL(dw11)) {
+case NVME_TEMP_THSEL_OVER:
+result = n->features.temp_thresh_hi;
+break;
+case NVME_TEMP_THSEL_UNDER:
+result = n->features.temp_thresh_low;
+break;
+}
+
+break;
 case NVME_VOLATILE_WRITE_CACHE:
 result = blk_enable_write_cache(n->conf.blk);
 trace_pci_nvme_getfeat_vwcache(result ? "enabled" : "disabled");
@@ -888,6 +913,23 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeCmd 
*cmd, NvmeRequest *req)
 uint32_t dw11 = le32_to_cpu(cmd->cdw11);
 
 switch (dw10) {
+case NVME_TEMPERATURE_THRESHOLD:
+if (NVME_TEMP_TMPSEL(dw11) != NVME_TEMP_TMPSEL_COMPOSITE) {
+break;
+}
+
+switch (NVME_TEMP_THSEL(dw11)) {
+case NVME_TEMP_THSEL_OVER:
+n->features.temp_thresh_hi = NVME_TEMP_TMPTH(dw11);
+break;
+case NVME_TEMP_THSEL_UNDER:
+n->features.temp_thresh_low = NVME_TEMP_TMPTH(dw11);
+break;
+default:
+return NVME_INVALID_FIELD | NVME_DNR;
+}
+
+break;
 case NVME_VOLATILE_WRITE_CACHE:
 blk_set_enable_write_cache(n->conf.blk, dw11 & 1);
 break;
@@ -1468,6 +1510,7 @@ static void nvme_init_state(NvmeCtrl *n)
 n->namespaces = g_new0(NvmeNamespace, n->num_namespaces);
 n->sq = g_new0(NvmeSQueue *, n->params.max_ioqpairs + 1);
 n->cq = g_new0(NvmeCQueue *, n->params.max_ioqpairs + 1);
+n->features.temp_thresh_hi = NVME_TEMPERATURE_WARNING;
 }
 
 static void nvme_init_blk(NvmeCtrl *n, Error **errp)
@@ -1625,6 +1668,11 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice 
*pci_dev)
 id->acl = 3;
 id->frmw = 7 << 1;
 id->lpa = 1 << 0;
+
+/* recommended default value (~70 C) */
+id->wctemp = cpu_to_le16(NVME_TEMPERATURE_WARNING);
+id->cctemp = cpu_to_le16(NVME_TEMPERATURE_CRITICAL);
+
 id->sqes = (0x6 << 4) | 0x6;
 id->cqes = (0x4 << 4) | 0x4;
 id->nn = cpu_to_le32(n->num_namespaces);
diff --git a/hw/block/nvme.h b/hw/block/nvme.h
index 1d30c0bca283..e3a2c907e210 100644
--- a/hw/block/nvme.h
+++ b/hw/block/nvme.h
@@ -107,6 +107,7 @@ typedef struct NvmeCtrl {
 NvmeSQueue  admin_sq;
 NvmeCQueue  admin_cq;
 NvmeIdCtrl  id_ctrl;
+NvmeFeatureVal  features;
 } NvmeCtrl;
 
 /* calculate the number of LBAs that the namespace can accomodate */
diff --git a/include/block/nvme.h b/include/block/nvme.h
index 2a80d2a7ed89..d2c457695b38 100644
--- a/include/block/nvme.h
+++ b/include/block/nvme.h
@@ -860,7 +860,10 @@ enum NvmeIdCtrlOncs {
 typedef struct NvmeFeatureVal {
 uint32_tarbitration;
 uint32_tpower_mgmt;
-uint32_ttemp_thresh;
+struct {
+uint16_t temp_thresh_hi;
+uint16_t temp_thresh_low;
+};
 uint32_terr_rec;
 uint32_tvolatile_wc;
 uint32_tnum_queues;
-- 
2.27.0




[PATCH v3 02/18] hw/block/nvme: fix missing endian conversion

2020-07-05 Thread Klaus Jensen
From: Klaus Jensen 

Fix a missing cpu_to conversion by moving conversion to just before
returning instead.

Signed-off-by: Klaus Jensen 
Suggested-by: Philippe Mathieu-Daudé 
---
 hw/block/nvme.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 71b388aa0e20..766cd5b33bb1 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -815,8 +815,8 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd *cmd, 
NvmeRequest *req)
 trace_pci_nvme_getfeat_vwcache(result ? "enabled" : "disabled");
 break;
 case NVME_NUMBER_OF_QUEUES:
-result = cpu_to_le32((n->params.max_ioqpairs - 1) |
- ((n->params.max_ioqpairs - 1) << 16));
+result = (n->params.max_ioqpairs - 1) |
+((n->params.max_ioqpairs - 1) << 16);
 trace_pci_nvme_getfeat_numq(result);
 break;
 case NVME_TIMESTAMP:
@@ -826,7 +826,7 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeCmd *cmd, 
NvmeRequest *req)
 return NVME_INVALID_FIELD | NVME_DNR;
 }
 
-req->cqe.result = result;
+req->cqe.result = cpu_to_le32(result);
 return NVME_SUCCESS;
 }
 
-- 
2.27.0




[PATCH v3 04/18] hw/block/nvme: add support for the abort command

2020-07-05 Thread Klaus Jensen
From: Klaus Jensen 

Required for compliance with NVMe revision 1.3d. See NVM Express 1.3d,
Section 5.1 ("Abort command").

The Abort command is a best effort command; for now, the device always
fails to abort the given command.

Signed-off-by: Klaus Jensen 
Signed-off-by: Klaus Jensen 
Acked-by: Keith Busch 
Reviewed-by: Maxim Levitsky 
Reviewed-by: Dmitry Fomichev 
---
 hw/block/nvme.c | 27 +++
 1 file changed, 27 insertions(+)

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 09ef54d771c4..415d3b036897 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -775,6 +775,18 @@ static uint16_t nvme_identify(NvmeCtrl *n, NvmeCmd *cmd)
 }
 }
 
+static uint16_t nvme_abort(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req)
+{
+uint16_t sqid = le32_to_cpu(cmd->cdw10) & 0x;
+
+req->cqe.result = 1;
+if (nvme_check_sqid(n, sqid)) {
+return NVME_INVALID_FIELD | NVME_DNR;
+}
+
+return NVME_SUCCESS;
+}
+
 static inline void nvme_set_timestamp(NvmeCtrl *n, uint64_t ts)
 {
 trace_pci_nvme_setfeat_timestamp(ts);
@@ -911,6 +923,8 @@ static uint16_t nvme_admin_cmd(NvmeCtrl *n, NvmeCmd *cmd, 
NvmeRequest *req)
 return nvme_create_cq(n, cmd);
 case NVME_ADM_CMD_IDENTIFY:
 return nvme_identify(n, cmd);
+case NVME_ADM_CMD_ABORT:
+return nvme_abort(n, cmd, req);
 case NVME_ADM_CMD_SET_FEATURES:
 return nvme_set_feature(n, cmd, req);
 case NVME_ADM_CMD_GET_FEATURES:
@@ -1596,6 +1610,19 @@ static void nvme_init_ctrl(NvmeCtrl *n, PCIDevice 
*pci_dev)
 id->ieee[1] = 0x02;
 id->ieee[2] = 0xb3;
 id->oacs = cpu_to_le16(0);
+
+/*
+ * Because the controller always completes the Abort command immediately,
+ * there can never be more than one concurrently executing Abort command,
+ * so this value is never used for anything. Note that there can easily be
+ * many Abort commands in the queues, but they are not considered
+ * "executing" until processed by nvme_abort.
+ *
+ * The specification recommends a value of 3 for Abort Command Limit (four
+ * concurrently outstanding Abort commands), so lets use that though it is
+ * inconsequential.
+ */
+id->acl = 3;
 id->frmw = 7 << 1;
 id->lpa = 1 << 0;
 id->sqes = (0x6 << 4) | 0x6;
-- 
2.27.0




[PATCH v3 00/18] hw/block/nvme: bump to v1.3

2020-07-05 Thread Klaus Jensen
From: Klaus Jensen 

This adds mandatory features of NVM Express v1.3 to the emulated NVMe
device.


v3:
  * hw/block/nvme: additional tracing
- Reverse logic in nvme_cid(). (Philippe)
- Move nvme_cid() and nvme_sqid() to source file. (Philippe)
  * hw/block/nvme: fix missing endian conversion
- Move this patch to very early in the series and fix the bug properly as
  suggested by Philippe. Then let the change trickle down through
  the series. (Philippe)
  * hw/block/nvme: add remaining mandatory controller parameters
- Move the nvme_feature_{support,default} arrays to the source file.
  (Philippe)
- Add a NVME_FID_MAX constant. (Philippe)
  * hw/block/nvme: support the get/set features select and save fields
- Move the nvme_feature_cap array to the source file. (Philippe)
  * hw/block/nvme: reject invalid nsid values in active namespace id list
- Rework the condition and add a comment and reference to the spec.
  (Philippe)
  * hw/block/nvme: provide the mandatory subnqn field
- Change to use strpadcpy(). (Philippe)

  Had to clear some R-b's due to functional changes.

  Missing review: 2, 3, 7, 12, 16, 17


v2:
  * hw/block/nvme: bump spec data structures to v1.3
- Shorten some constants. (Dmitry)
  * hw/block/nvme: add temperature threshold feature
- Remove unused temp_thresh member. (Dmitry)
  * hw/block/nvme: add support for the get log page command
- Change the temperature field in the NvmeSmartLog struct to be an
  uint16_t and handle wierd alignment by adding QEMU_PACKED to the
  struct. (Dmitry)
  * hw/block/nvme: add remaining mandatory controller parameters
- Fix spelling. (Dmitry)
  * hw/block/nvme: support the get/set features select and save fields
- Fix bad logic causing temperature thresholds to always report
  defaults. (Dmitry)
  * hw/block/nvme: reject invalid nsid values in active namespace id list
- Added patch; reject the 0xfffe and 0x nsid values.


$ git-backport-diff -u for-master/bump-to-v1.3-v2 -r upstream/master... -S
Key:
[] : patches are identical
[] : number of functional differences between upstream/downstream patch
[down] : patch is downstream-only
The flags [FC] indicate (F)unctional and (C)ontextual differences, respectively

001/18:[] [--] 'hw/block/nvme: bump spec data structures to v1.3'
002/18:[0008] [FC] 'hw/block/nvme: fix missing endian conversion'
003/18:[0028] [FC] 'hw/block/nvme: additional tracing'
004/18:[] [--] 'hw/block/nvme: add support for the abort command'
005/18:[0004] [FC] 'hw/block/nvme: add temperature threshold feature'
006/18:[] [--] 'hw/block/nvme: mark fw slot 1 as read-only'
007/18:[] [--] 'hw/block/nvme: add support for the get log page command'
008/18:[0002] [FC] 'hw/block/nvme: add support for the asynchronous event 
request command'
009/18:[] [--] 'hw/block/nvme: move NvmeFeatureVal into hw/block/nvme.h'
010/18:[] [--] 'hw/block/nvme: flush write cache when disabled'
011/18:[0044] [FC] 'hw/block/nvme: add remaining mandatory controller 
parameters'
012/18:[0024] [FC] 'hw/block/nvme: support the get/set features select and save 
fields'
013/18:[] [--] 'hw/block/nvme: make sure ncqr and nsqr is valid'
014/18:[] [--] 'hw/block/nvme: support identify namespace descriptor list'
015/18:[0008] [FC] 'hw/block/nvme: reject invalid nsid values in active 
namespace id list'
016/18:[] [--] 'hw/block/nvme: enforce valid queue creation sequence'
017/18:[0006] [FC] 'hw/block/nvme: provide the mandatory subnqn field'
018/18:[] [--] 'hw/block/nvme: bump supported version to v1.3'


Klaus Jensen (18):
  hw/block/nvme: bump spec data structures to v1.3
  hw/block/nvme: fix missing endian conversion
  hw/block/nvme: additional tracing
  hw/block/nvme: add support for the abort command
  hw/block/nvme: add temperature threshold feature
  hw/block/nvme: mark fw slot 1 as read-only
  hw/block/nvme: add support for the get log page command
  hw/block/nvme: add support for the asynchronous event request command
  hw/block/nvme: move NvmeFeatureVal into hw/block/nvme.h
  hw/block/nvme: flush write cache when disabled
  hw/block/nvme: add remaining mandatory controller parameters
  hw/block/nvme: support the get/set features select and save fields
  hw/block/nvme: make sure ncqr and nsqr is valid
  hw/block/nvme: support identify namespace descriptor list
  hw/block/nvme: reject invalid nsid values in active namespace id list
  hw/block/nvme: enforce valid queue creation sequence
  hw/block/nvme: provide the mandatory subnqn field
  hw/block/nvme: bump supported version to v1.3

 block/nvme.c  |  18 +-
 hw/block/nvme.c   | 676 --
 hw/block/nvme.h   |  22 +-
 hw/block/trace-events |  27 +-
 include/block/nvme.h  | 225 +++---
 5 files changed, 892 insertions(+), 76 deletions(-)

-- 
2.27.0




[PATCH v3 07/18] hw/block/nvme: add support for the get log page command

2020-07-05 Thread Klaus Jensen
From: Klaus Jensen 

Add support for the Get Log Page command and basic implementations of
the mandatory Error Information, SMART / Health Information and Firmware
Slot Information log pages.

In violation of the specification, the SMART / Health Information log
page does not persist information over the lifetime of the controller
because the device has no place to store such persistent state.

Note that the LPA field in the Identify Controller data structure
intentionally has bit 0 cleared because there is no namespace specific
information in the SMART / Health information log page.

Required for compliance with NVMe revision 1.3d. See NVM Express 1.3d,
Section 5.14 ("Get Log Page command").

Signed-off-by: Klaus Jensen 
Signed-off-by: Klaus Jensen 
Acked-by: Keith Busch 
---
 hw/block/nvme.c   | 140 +-
 hw/block/nvme.h   |   2 +
 hw/block/trace-events |   2 +
 include/block/nvme.h  |   8 ++-
 4 files changed, 149 insertions(+), 3 deletions(-)

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index b6bc75eb61a2..7cb3787638f6 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -606,6 +606,140 @@ static uint16_t nvme_create_sq(NvmeCtrl *n, NvmeCmd *cmd)
 return NVME_SUCCESS;
 }
 
+static uint16_t nvme_smart_info(NvmeCtrl *n, NvmeCmd *cmd, uint32_t buf_len,
+uint64_t off, NvmeRequest *req)
+{
+uint64_t prp1 = le64_to_cpu(cmd->dptr.prp1);
+uint64_t prp2 = le64_to_cpu(cmd->dptr.prp2);
+uint32_t nsid = le32_to_cpu(cmd->nsid);
+
+uint32_t trans_len;
+time_t current_ms;
+uint64_t units_read = 0, units_written = 0;
+uint64_t read_commands = 0, write_commands = 0;
+NvmeSmartLog smart;
+BlockAcctStats *s;
+
+if (nsid && nsid != 0x) {
+return NVME_INVALID_FIELD | NVME_DNR;
+}
+
+s = blk_get_stats(n->conf.blk);
+
+units_read = s->nr_bytes[BLOCK_ACCT_READ] >> BDRV_SECTOR_BITS;
+units_written = s->nr_bytes[BLOCK_ACCT_WRITE] >> BDRV_SECTOR_BITS;
+read_commands = s->nr_ops[BLOCK_ACCT_READ];
+write_commands = s->nr_ops[BLOCK_ACCT_WRITE];
+
+if (off > sizeof(smart)) {
+return NVME_INVALID_FIELD | NVME_DNR;
+}
+
+trans_len = MIN(sizeof(smart) - off, buf_len);
+
+memset(&smart, 0x0, sizeof(smart));
+
+smart.data_units_read[0] = cpu_to_le64(units_read / 1000);
+smart.data_units_written[0] = cpu_to_le64(units_written / 1000);
+smart.host_read_commands[0] = cpu_to_le64(read_commands);
+smart.host_write_commands[0] = cpu_to_le64(write_commands);
+
+smart.temperature = cpu_to_le16(n->temperature);
+
+if ((n->temperature >= n->features.temp_thresh_hi) ||
+(n->temperature <= n->features.temp_thresh_low)) {
+smart.critical_warning |= NVME_SMART_TEMPERATURE;
+}
+
+current_ms = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
+smart.power_on_hours[0] =
+cpu_to_le64current_ms - n->starttime_ms) / 1000) / 60) / 60);
+
+return nvme_dma_read_prp(n, (uint8_t *) &smart + off, trans_len, prp1,
+ prp2);
+}
+
+static uint16_t nvme_fw_log_info(NvmeCtrl *n, NvmeCmd *cmd, uint32_t buf_len,
+ uint64_t off, NvmeRequest *req)
+{
+uint32_t trans_len;
+uint64_t prp1 = le64_to_cpu(cmd->dptr.prp1);
+uint64_t prp2 = le64_to_cpu(cmd->dptr.prp2);
+NvmeFwSlotInfoLog fw_log = {
+.afi = 0x1,
+};
+
+strpadcpy((char *)&fw_log.frs1, sizeof(fw_log.frs1), "1.0", ' ');
+
+if (off > sizeof(fw_log)) {
+return NVME_INVALID_FIELD | NVME_DNR;
+}
+
+trans_len = MIN(sizeof(fw_log) - off, buf_len);
+
+return nvme_dma_read_prp(n, (uint8_t *) &fw_log + off, trans_len, prp1,
+ prp2);
+}
+
+static uint16_t nvme_error_info(NvmeCtrl *n, NvmeCmd *cmd, uint32_t buf_len,
+uint64_t off, NvmeRequest *req)
+{
+uint32_t trans_len;
+uint64_t prp1 = le64_to_cpu(cmd->dptr.prp1);
+uint64_t prp2 = le64_to_cpu(cmd->dptr.prp2);
+NvmeErrorLog errlog;
+
+if (off > sizeof(errlog)) {
+return NVME_INVALID_FIELD | NVME_DNR;
+}
+
+memset(&errlog, 0x0, sizeof(errlog));
+
+trans_len = MIN(sizeof(errlog) - off, buf_len);
+
+return nvme_dma_read_prp(n, (uint8_t *)&errlog, trans_len, prp1, prp2);
+}
+
+static uint16_t nvme_get_log(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req)
+{
+uint32_t dw10 = le32_to_cpu(cmd->cdw10);
+uint32_t dw11 = le32_to_cpu(cmd->cdw11);
+uint32_t dw12 = le32_to_cpu(cmd->cdw12);
+uint32_t dw13 = le32_to_cpu(cmd->cdw13);
+uint8_t  lid = dw10 & 0xff;
+uint8_t  lsp = (dw10 >> 8) & 0xf;
+uint8_t  rae = (dw10 >> 15) & 0x1;
+uint32_t numdl, numdu;
+uint64_t off, lpol, lpou;
+size_t   len;
+
+numdl = (dw10 >> 16);
+numdu = (dw11 & 0x);
+lpol = dw12;
+lpou = dw13;
+
+len = (((numdu << 16) | numdl) + 1) << 2;
+off = (lpou << 32ULL) | lpol;
+
+if (off & 0x3) {
+   

[PATCH v3 03/18] hw/block/nvme: additional tracing

2020-07-05 Thread Klaus Jensen
From: Klaus Jensen 

Add various additional tracing and streamline nvme_identify_ns and
nvme_identify_nslist (they do not need to repeat the command, it is
already in the trace name).

Signed-off-by: Klaus Jensen 
---
 hw/block/nvme.c   | 33 +
 hw/block/trace-events | 13 +++--
 2 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/hw/block/nvme.c b/hw/block/nvme.c
index 766cd5b33bb1..09ef54d771c4 100644
--- a/hw/block/nvme.c
+++ b/hw/block/nvme.c
@@ -69,6 +69,20 @@
 
 static void nvme_process_sq(void *opaque);
 
+static uint16_t nvme_cid(NvmeRequest *req)
+{
+if (!req) {
+return 0x;
+}
+
+return le16_to_cpu(req->cqe.cid);
+}
+
+static uint16_t nvme_sqid(NvmeRequest *req)
+{
+return le16_to_cpu(req->sq->sqid);
+}
+
 static bool nvme_addr_is_cmb(NvmeCtrl *n, hwaddr addr)
 {
 hwaddr low = n->ctrl_mem.addr;
@@ -331,6 +345,8 @@ static void nvme_post_cqes(void *opaque)
 static void nvme_enqueue_req_completion(NvmeCQueue *cq, NvmeRequest *req)
 {
 assert(cq->cqid == req->sq->cqid);
+trace_pci_nvme_enqueue_req_completion(nvme_cid(req), cq->cqid,
+  req->status);
 QTAILQ_REMOVE(&req->sq->out_req_list, req, entry);
 QTAILQ_INSERT_TAIL(&cq->req_list, req, entry);
 timer_mod(cq->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 500);
@@ -343,6 +359,8 @@ static void nvme_rw_cb(void *opaque, int ret)
 NvmeCtrl *n = sq->ctrl;
 NvmeCQueue *cq = n->cq[sq->cqid];
 
+trace_pci_nvme_rw_cb(nvme_cid(req));
+
 if (!ret) {
 block_acct_done(blk_get_stats(n->conf.blk), &req->acct);
 req->status = NVME_SUCCESS;
@@ -378,6 +396,8 @@ static uint16_t nvme_write_zeros(NvmeCtrl *n, NvmeNamespace 
*ns, NvmeCmd *cmd,
 uint64_t offset = slba << data_shift;
 uint32_t count = nlb << data_shift;
 
+trace_pci_nvme_write_zeroes(nvme_cid(req), slba, nlb);
+
 if (unlikely(slba + nlb > ns->id_ns.nsze)) {
 trace_pci_nvme_err_invalid_lba_range(slba, nlb, ns->id_ns.nsze);
 return NVME_LBA_RANGE | NVME_DNR;
@@ -445,6 +465,8 @@ static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeCmd *cmd, 
NvmeRequest *req)
 NvmeNamespace *ns;
 uint32_t nsid = le32_to_cpu(cmd->nsid);
 
+trace_pci_nvme_io_cmd(nvme_cid(req), nsid, nvme_sqid(req), cmd->opcode);
+
 if (unlikely(nsid == 0 || nsid > n->num_namespaces)) {
 trace_pci_nvme_err_invalid_ns(nsid, n->num_namespaces);
 return NVME_INVALID_NSID | NVME_DNR;
@@ -876,6 +898,8 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeCmd *cmd, 
NvmeRequest *req)
 
 static uint16_t nvme_admin_cmd(NvmeCtrl *n, NvmeCmd *cmd, NvmeRequest *req)
 {
+trace_pci_nvme_admin_cmd(nvme_cid(req), nvme_sqid(req), cmd->opcode);
+
 switch (cmd->opcode) {
 case NVME_ADM_CMD_DELETE_SQ:
 return nvme_del_sq(n, cmd);
@@ -1204,6 +1228,8 @@ static uint64_t nvme_mmio_read(void *opaque, hwaddr addr, 
unsigned size)
 uint8_t *ptr = (uint8_t *)&n->bar;
 uint64_t val = 0;
 
+trace_pci_nvme_mmio_read(addr);
+
 if (unlikely(addr & (sizeof(uint32_t) - 1))) {
 NVME_GUEST_ERR(pci_nvme_ub_mmiord_misaligned32,
"MMIO read not 32-bit aligned,"
@@ -1273,6 +1299,8 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int 
val)
 return;
 }
 
+trace_pci_nvme_mmio_doorbell_cq(cq->cqid, new_head);
+
 start_sqs = nvme_cq_full(cq) ? 1 : 0;
 cq->head = new_head;
 if (start_sqs) {
@@ -1311,6 +1339,8 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int 
val)
 return;
 }
 
+trace_pci_nvme_mmio_doorbell_sq(sq->sqid, new_tail);
+
 sq->tail = new_tail;
 timer_mod(sq->timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 500);
 }
@@ -1320,6 +1350,9 @@ static void nvme_mmio_write(void *opaque, hwaddr addr, 
uint64_t data,
 unsigned size)
 {
 NvmeCtrl *n = (NvmeCtrl *)opaque;
+
+trace_pci_nvme_mmio_write(addr, data);
+
 if (addr < sizeof(n->bar)) {
 nvme_write_bar(n, addr, data, size);
 } else if (addr >= 0x1000) {
diff --git a/hw/block/trace-events b/hw/block/trace-events
index 958fcc5508d1..c40c0d2e4b28 100644
--- a/hw/block/trace-events
+++ b/hw/block/trace-events
@@ -33,19 +33,28 @@ pci_nvme_irq_msix(uint32_t vector) "raising MSI-X IRQ 
vector %u"
 pci_nvme_irq_pin(void) "pulsing IRQ pin"
 pci_nvme_irq_masked(void) "IRQ is masked"
 pci_nvme_dma_read(uint64_t prp1, uint64_t prp2) "DMA read, prp1=0x%"PRIx64" 
prp2=0x%"PRIx64""
+pci_nvme_io_cmd(uint16_t cid, uint32_t nsid, uint16_t sqid, uint8_t opcode) 
"cid %"PRIu16" nsid %"PRIu32" sqid %"PRIu16" opc 0x%"PRIx8""
+pci_nvme_admin_cmd(uint16_t cid, uint16_t sqid, uint8_t opcode) "cid %"PRIu16" 
sqid %"PRIu16" opc 0x%"PRIx8""
 pci_nvme_rw(const char *verb, uint32_t blk_count, uint64_t byte_count, 
uint64_t lba) "%s %"PRIu32" blocks (%"PRIu64" bytes) from LBA %"PRIu64""
+pci_nvme_rw_cb(uint16_t cid) "cid %"PRIu

Re: [PATCH 00/13] Reverse debugging

2020-07-05 Thread Pavel Dovgalyuk

Ping.


On 26.06.2020 13:19, Pavel Dovgalyuk wrote:

GDB remote protocol supports reverse debugging of the targets.
It includes 'reverse step' and 'reverse continue' operations.
The first one finds the previous step of the execution,
and the second one is intended to stop at the last breakpoint that
would happen when the program is executed normally.

Reverse debugging is possible in the replay mode, when at least
one snapshot was created at the record or replay phase.
QEMU can use these snapshots for travelling back in time with GDB.

Running the execution in replay mode allows using GDB reverse debugging
commands:
  - reverse-stepi (or rsi): Steps one instruction to the past.
QEMU loads on of the prior snapshots and proceeds to the desired
instruction forward. When that step is reaches, execution stops.
  - reverse-continue (or rc): Runs execution "backwards".
QEMU tries to find breakpoint or watchpoint by loaded prior snapshot
and replaying the execution. Then QEMU loads snapshots again and
replays to the latest breakpoint. When there are no breakpoints in
the examined section of the execution, QEMU finds one more snapshot
and tries again. After the first snapshot is processed, execution
stops at this snapshot.

The set of patches include the following modifications:
  - gdbstub update for reverse debugging support
  - functions that automatically perform reverse step and reverse
continue operations
  - hmp/qmp commands for manipulating the replay process
  - improvement of the snapshotting for saving the execution step
in the snapshot parameters
  - avocado-based acceptance tests for reverse debugging

Acceptance tests intended to use the version of avocado framework, that
will be released after 25.06.20, because it includes significant
fixes of the remote GDB protocol.

The patches are available in the repository:
https://github.com/ispras/qemu/tree/rr-200626

---

Pavel Dovgaluk (13):
   replay: provide an accessor for rr filename
   qcow2: introduce icount field for snapshots
   migration: introduce icount field for snapshots
   iotests: update snapshot test for new output format
   qapi: introduce replay.json for record/replay-related stuff
   replay: introduce info hmp/qmp command
   replay: introduce breakpoint at the specified step
   replay: implement replay-seek command
   replay: flush rr queue before loading the vmstate
   gdbstub: add reverse step support in replay mode
   gdbstub: add reverse continue support in replay mode
   replay: describe reverse debugging in docs/replay.txt
   tests/acceptance: add reverse debugging test


  0 files changed

--
Pavel Dovgalyuk






Re: [PATCH v11 1/8] error: auto propagated local_err

2020-07-05 Thread Markus Armbruster
Vladimir Sementsov-Ogievskiy  writes:

> Introduce a new ERRP_AUTO_PROPAGATE macro, to be used at start of
> functions with an errp OUT parameter.
>
> It has three goals:
>
> 1. Fix issue with error_fatal and error_prepend/error_append_hint: user
> can't see this additional information, because exit() happens in
> error_setg earlier than information is added. [Reported by Greg Kurz]
>
> 2. Fix issue with error_abort and error_propagate: when we wrap
> error_abort by local_err+error_propagate, the resulting coredump will
> refer to error_propagate and not to the place where error happened.
> (the macro itself doesn't fix the issue, but it allows us to [3.] drop
> the local_err+error_propagate pattern, which will definitely fix the
> issue) [Reported by Kevin Wolf]
>
> 3. Drop local_err+error_propagate pattern, which is used to workaround
> void functions with errp parameter, when caller wants to know resulting
> status. (Note: actually these functions could be merely updated to
> return int error code).
>
> To achieve these goals, later patches will add invocations
> of this macro at the start of functions with either use
> error_prepend/error_append_hint (solving 1) or which use
> local_err+error_propagate to check errors, switching those
> functions to use *errp instead (solving 2 and 3).
>
> Signed-off-by: Vladimir Sementsov-Ogievskiy 
> Reviewed-by: Paul Durrant 
> Reviewed-by: Greg Kurz 
> Reviewed-by: Eric Blake 
> ---
>
> Cc: Eric Blake 
> Cc: Kevin Wolf 
> Cc: Max Reitz 
> Cc: Greg Kurz 
> Cc: Christian Schoenebeck 
> Cc: Stefan Hajnoczi 
> Cc: Stefano Stabellini 
> Cc: Anthony Perard 
> Cc: Paul Durrant 
> Cc: "Philippe Mathieu-Daudé" 
> Cc: Laszlo Ersek 
> Cc: Gerd Hoffmann 
> Cc: Markus Armbruster 
> Cc: Michael Roth 
> Cc: qemu-devel@nongnu.org
> Cc: qemu-bl...@nongnu.org
> Cc: xen-de...@lists.xenproject.org
>
>  include/qapi/error.h | 205 ---
>  1 file changed, 172 insertions(+), 33 deletions(-)
>
> diff --git a/include/qapi/error.h b/include/qapi/error.h
> index 5ceb3ace06..b54aedbfd7 100644
> --- a/include/qapi/error.h
> +++ b/include/qapi/error.h
> @@ -39,7 +39,7 @@
>   *   • pointer-valued functions return non-null / null pointer, and
>   *   • integer-valued functions return non-negative / negative.
>   *
> - * How to:
> + * = Deal with Error object =
>   *
>   * Create an error:
>   * error_setg(errp, "situation normal, all fouled up");
> @@ -73,28 +73,91 @@
>   * reporting it (primarily useful in testsuites):
>   * error_free_or_abort(&err);
>   *
> - * Pass an existing error to the caller:
> - * error_propagate(errp, err);
> - * where Error **errp is a parameter, by convention the last one.
> + * = Deal with Error ** function parameter =
>   *
> - * Pass an existing error to the caller with the message modified:
> - * error_propagate_prepend(errp, err);
> + * A function may use the error system to return errors. In this case, the
> + * function defines an Error **errp parameter, by convention the last one 
> (with
> + * exceptions for functions using ... or va_list).
>   *
> - * Avoid
> - * error_propagate(errp, err);
> - * error_prepend(errp, "Could not frobnicate '%s': ", name);
> - * because this fails to prepend when @errp is &error_fatal.
> + * The caller may then pass in the following errp values:
> + *
> + * 1. &error_abort
> + *Any error will result in abort().
> + * 2. &error_fatal
> + *Any error will result in exit() with a non-zero status.
> + * 3. NULL
> + *No error reporting through errp parameter.
> + * 4. The address of a NULL-initialized Error *err
> + *Any error will populate errp with an error object.

The rebase onto my "error: Document Error API usage rules" rendered this
this partly redundant.  I'll try my hand at a proper merge, then ask you
to check it.

Should I fail to complete this in time for the soft freeze, we can merge
the thing as is.  Comment improvements are fair game until -rc1 or so.

>   *
> - * Create a new error and pass it to the caller:
> + * The following rules then implement the correct semantics desired by the
> + * caller.
> + *
> + * Create a new error to pass to the caller:
>   * error_setg(errp, "situation normal, all fouled up");
>   *
> - * Call a function and receive an error from it:
> + * Calling another errp-based function:
> + * f(..., errp);
> + *
> + * == Checking success of subcall ==
> + *
> + * If a function returns a value indicating an error in addition to setting
> + * errp (which is recommended), then you don't need any additional code, just
> + * do:
> + *
> + * int ret = f(..., errp);
> + * if (ret < 0) {
> + * ... handle error ...
> + * return ret;
> + * }
> + *
> + * If a function returns nothing (not recommended for new code), the only way

Also when a function returns something, but there is no distinct error
value.  Example: object_property_get_int().

I shouldn't criticize comments without suggesting im

Re: [PATCH v7 09/17] hw/sd/sdcard: Special case the -ENOMEDIUM error

2020-07-05 Thread Markus Armbruster
Peter Maydell  writes:

> On Tue, 30 Jun 2020 at 14:39, Philippe Mathieu-Daudé  wrote:
>>
>> As we have no interest in the underlying block geometry,
>> directly call blk_getlength(). We have to care about machines
>> creating SD card with not drive attached (probably incorrect
>> API use). Simply emit a warning when such Frankenstein cards
>> of zero size are reset.
>
> Which machines create SD cards without a backing block device?
>
> I have a feeling that also the monitor "change" and "eject"
> commands can remove the backing block device from the SD card
> object.

Correct:

static const BlockDevOps sd_block_ops = {
.change_media_cb = sd_cardchange,
};

This is TYPE_SD_CARD's ("sd-card").  What exactly does that device
model?

If it's the sd-card, then the modelling is odd.  A physical SD card gets
plugged and unplugged as a whole.  This model can't.  Instead, you
change "media".  Isn't the SD card the medium?

The other device models with removable media (IDE & SCSI CD drives,
floppy drives) model the receptacle for media.  On media change, the
drive stays put, and only the medium changes, both in the physical world
and in our virtual world.

Our "sd-card" seems to be an "SD card drive".  But then I wonder what
the thing at the other end of TYPE_SD_BUS ("sd-bus") actually models.
Any ideas?




[Bug 1885827] Re: building plugin failed on Windows with mingw

2020-07-05 Thread Xiaolei
Hi,
  I patched configure file and makefile. The output is listed below.
  The project is configured as :
  #../configure --target-list=dsp-softmmu --cross-prefix=x86_64-w64-mingw32- 
--enable-gtk --enable-sdl --enable-debug --enable-plugins 
--extra-cflags="-DBUILDING_DLL"
  
  But running make yeilds error:
  CC  dsp-softmmu/trace/generated-helpers.o
  CC  dsp-softmmu/trace/control-target.o
  LINKdsp-softmmu/qemu-system-dspw.exe
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/9.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
 cannot find -lfdt
collect2.exe: error: ld returned 1 exit status
make[1]: *** [Makefile:208: qemu-system-dspw.exe] Error 1
make: *** [Makefile:491: dsp-softmmu/all] Error 2
  
  We then reconfigured by disable the -fdt :
  ../configure --target-list=dsp-softmmu --cross-prefix=x86_64-w64-mingw32- 
--enable-gtk --enable-sdl --enable-debug --enable-plugins --disable-fdt 
--extra-cflags="-DBUILDING_DLL"
  Build finished and running  "make -C tests/plugin" gets similar linking 
errors:
  
  x86_64-w64-mingw32-gcc -shared -Wl,-soname,libbb.so -o libbb.so bb.o
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/9.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
 bb.o: in function `g_autoptr_cleanup_generic_gfree':
C:/msys64/mingw64/include/glib-2.0/glib/glib-autocleanups.h:28: undefined 
reference to `g_free'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/9.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
 bb.o: in function `plugin_exit':
C:/QRS_Project/simdsp/qemu-4.2.0/tests/plugin/bb.c:27: undefined reference to 
`g_strdup_printf'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/9.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
 C:/QRS_Project/simdsp/qemu-4.2.0/tests/plugin/bb.c:29: undefined reference to 
`qemu_plugin_outs'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/9.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
 C:/QRS_Project/simdsp/qemu-4.2.0/tests/plugin/bb.c:30: undefined reference to 
`__stack_chk_fail'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/9.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
 bb.o: in function `vcpu_tb_trans':
C:/QRS_Project/simdsp/qemu-4.2.0/tests/plugin/bb.c:42: undefined reference to 
`qemu_plugin_tb_n_insns'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/9.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
 C:/QRS_Project/simdsp/qemu-4.2.0/tests/plugin/bb.c:45: undefined reference to 
`qemu_plugin_register_vcpu_tb_exec_inline'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/9.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
 C:/QRS_Project/simdsp/qemu-4.2.0/tests/plugin/bb.c:47: undefined reference to 
`qemu_plugin_register_vcpu_tb_exec_inline'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/9.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
 C:/QRS_Project/simdsp/qemu-4.2.0/tests/plugin/bb.c:50: undefined reference to 
`qemu_plugin_register_vcpu_tb_exec_cb'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/9.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
 bb.o: in function `qemu_plugin_install':
C:/QRS_Project/simdsp/qemu-4.2.0/tests/plugin/bb.c:64: undefined reference to 
`qemu_plugin_register_vcpu_tb_trans_cb'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/9.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
 C:/QRS_Project/simdsp/qemu-4.2.0/tests/plugin/bb.c:65: undefined reference to 
`qemu_plugin_register_atexit_cb'
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/9.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
 bb.o:bb.c:(.rdata$.refptr.__stack_chk_guard[.refptr.__stack_chk_guard]+0x0): 
undefined reference to `__stack_chk_guard'
collect2.exe: error: ld returned 1 exit status

-makefile ---
BUILD_DIR := $(CURDIR)/../..

include $(BUILD_DIR)/config-host.mak
include $(SRC_PATH)/rules.mak

$(call set-vpath, $(SRC_PATH)/tests/plugin)
#out 
NAMES :=
NAMES += bb
NAMES += empty
NAMES += insn
NAMES += mem
NAMES += hotblocks
NAMES += howvec
NAMES += hotpages

SONAMES := $(addsuffix .so,$(addprefix lib,$(NAMES)))

QEMU_CFLAGS += -fPIC -DBUILDING_DLL
QEMU_CFLAGS += -I$(SRC_PATH)/include/qemu

all: $(SONAMES)

lib%.so: %.o
$(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LDLIBS)

clean:
rm -f *.o *.so *.d
rm -Rf .libs

.PHONY: all clean

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1885827

Title:
  building plugin failed on Windows with mingw

Status in QEMU:
  New

Bug description:
  I want to build QEMU 4.2.0's plugin module on Windows 7/10 with Mingw, but 
the building process faild.
   
  The step I follow is listed below:
  1. create "dsp_build" diretory under source file folder

  2.  change directory to dsp_build , and run ../configure 
--target-list=dsp-softmmu --cross-prefix=x86_64-w64-mingw32- --enable-gtk 
--enable-sdl --enable-debug --enable-plugins
  3. build qemu project
  4. switch dir to /dsp_build, make -C tests/plugin, yeilds error: 
 CC  bb.o
   D:/emu_devl/

Re: [PATCH 1/2] virtio-ccw: fix virtio_set_ind_atomic

2020-07-05 Thread Christian Borntraeger



On 04.07.20 20:34, Michael S. Tsirkin wrote:
> On Tue, Jun 16, 2020 at 06:50:34AM +0200, Halil Pasic wrote:
>> The atomic_cmpxchg() loop is broken because we occasionally end up with
>> old and _old having different values (a legit compiler can generate code
>> that accessed *ind_addr again to pick up a value for _old instead of
>> using the value of old that was already fetched according to the
>> rules of the abstract machine). This means the underlying CS instruction
>> may use a different old (_old) than the one we intended to use if
>> atomic_cmpxchg() performed the xchg part.
> 
> And was this ever observed in the field? Or is this a theoretical issue?
> commit log should probably say ...

It was observed in the field when the xml specified qemu instead of vhost.



Re: [PATCH v11 7/8] nbd: introduce ERRP_AUTO_PROPAGATE

2020-07-05 Thread Markus Armbruster
Vladimir Sementsov-Ogievskiy  writes:

> If we want to add some info to errp (by error_prepend() or
> error_append_hint()), we must use the ERRP_AUTO_PROPAGATE macro.
> Otherwise, this info will not be added when errp == &error_fatal
> (the program will exit prior to the error_append_hint() or
> error_prepend() call).  Fix such cases.
>
> If we want to check error after errp-function call, we need to
> introduce local_err and then propagate it to errp. Instead, use
> ERRP_AUTO_PROPAGATE macro, benefits are:
> 1. No need of explicit error_propagate call
> 2. No need of explicit local_err variable: use errp directly
> 3. ERRP_AUTO_PROPAGATE leaves errp as is if it's not NULL or
>&error_fatal, this means that we don't break error_abort
>(we'll abort on error_set, not on error_propagate)
>
> This commit is generated by command
>
> sed -n '/^Network Block Device (NBD)$/,/^$/{s/^F: //p}' \
> MAINTAINERS | \
> xargs git ls-files | grep '\.[hc]$' | \
> xargs spatch \
> --sp-file scripts/coccinelle/auto-propagated-errp.cocci \
> --macro-file scripts/cocci-macro-file.h \
> --in-place --no-show-diff --max-width 80
>
> Reported-by: Kevin Wolf 
> Reported-by: Greg Kurz 
> Signed-off-by: Vladimir Sementsov-Ogievskiy 

Reviewed-by: Markus Armbruster 




Re: [PATCH] load_elf: Remove unused address variables from callers

2020-07-05 Thread David Gibson
On Sun, Jul 05, 2020 at 07:22:11PM +0200, BALATON Zoltan wrote:
> Several callers of load_elf() pass pointers for lowaddr and highaddr
> parameters which are then not used for anything. This may stem from a
> misunderstanding that load_elf need a value here but in fact it can
> take NULL to ignore these values. Remove such unused variables and
> pass NULL instead from callers that don't need these.
> 
> Signed-off-by: BALATON Zoltan 

Reviewed-by: David Gibson 

ppc parts
Acked-by: David Gibson 

> ---
>  hw/alpha/dp264.c   |  8 
>  hw/arm/armv7m.c|  4 +---
>  hw/cris/boot.c |  4 ++--
>  hw/microblaze/boot.c   |  4 ++--
>  hw/mips/fuloong2e.c|  8 
>  hw/moxie/moxiesim.c|  4 ++--
>  hw/nios2/boot.c|  4 ++--
>  hw/ppc/mac_newworld.c  |  6 ++
>  hw/ppc/mac_oldworld.c  |  6 ++
>  hw/ppc/ppc440_bamboo.c |  9 +++--
>  hw/ppc/sam460ex.c  | 12 +---
>  hw/ppc/spapr.c | 11 ---
>  hw/ppc/virtex_ml507.c  |  4 ++--
>  hw/riscv/boot.c|  8 
>  hw/xtensa/sim.c|  3 +--
>  hw/xtensa/xtfpga.c |  3 +--
>  16 files changed, 41 insertions(+), 57 deletions(-)
> 
> diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c
> index f7751b18f6..4d24518d1d 100644
> --- a/hw/alpha/dp264.c
> +++ b/hw/alpha/dp264.c
> @@ -62,8 +62,8 @@ static void clipper_init(MachineState *machine)
>  qemu_irq rtc_irq;
>  long size, i;
>  char *palcode_filename;
> -uint64_t palcode_entry, palcode_low, palcode_high;
> -uint64_t kernel_entry, kernel_low, kernel_high;
> +uint64_t palcode_entry;
> +uint64_t kernel_entry, kernel_low;
>  unsigned int smp_cpus = machine->smp.cpus;
>  
>  /* Create up to 4 cpus.  */
> @@ -113,7 +113,7 @@ static void clipper_init(MachineState *machine)
>  exit(1);
>  }
>  size = load_elf(palcode_filename, NULL, cpu_alpha_superpage_to_phys,
> -NULL, &palcode_entry, &palcode_low, &palcode_high, NULL,
> +NULL, &palcode_entry, NULL, NULL, NULL,
>  0, EM_ALPHA, 0, 0);
>  if (size < 0) {
>  error_report("could not load palcode '%s'", palcode_filename);
> @@ -132,7 +132,7 @@ static void clipper_init(MachineState *machine)
>  uint64_t param_offset;
>  
>  size = load_elf(kernel_filename, NULL, cpu_alpha_superpage_to_phys,
> -NULL, &kernel_entry, &kernel_low, &kernel_high, NULL,
> +NULL, &kernel_entry, &kernel_low, NULL, NULL,
>  0, EM_ALPHA, 0, 0);
>  if (size < 0) {
>  error_report("could not load kernel '%s'", kernel_filename);
> diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
> index 3308211e9c..92f859d760 100644
> --- a/hw/arm/armv7m.c
> +++ b/hw/arm/armv7m.c
> @@ -309,7 +309,6 @@ void armv7m_load_kernel(ARMCPU *cpu, const char 
> *kernel_filename, int mem_size)
>  {
>  int image_size;
>  uint64_t entry;
> -uint64_t lowaddr;
>  int big_endian;
>  AddressSpace *as;
>  int asidx;
> @@ -330,12 +329,11 @@ void armv7m_load_kernel(ARMCPU *cpu, const char 
> *kernel_filename, int mem_size)
>  
>  if (kernel_filename) {
>  image_size = load_elf_as(kernel_filename, NULL, NULL, NULL,
> - &entry, &lowaddr, NULL,
> + &entry, NULL, NULL,
>   NULL, big_endian, EM_ARM, 1, 0, as);
>  if (image_size < 0) {
>  image_size = load_image_targphys_as(kernel_filename, 0,
>  mem_size, as);
> -lowaddr = 0;
>  }
>  if (image_size < 0) {
>  error_report("Could not load kernel '%s'", kernel_filename);
> diff --git a/hw/cris/boot.c b/hw/cris/boot.c
> index b8947bc660..aa8d2756d6 100644
> --- a/hw/cris/boot.c
> +++ b/hw/cris/boot.c
> @@ -67,7 +67,7 @@ static uint64_t translate_kernel_address(void *opaque, 
> uint64_t addr)
>  void cris_load_image(CRISCPU *cpu, struct cris_load_info *li)
>  {
>  CPUCRISState *env = &cpu->env;
> -uint64_t entry, high;
> +uint64_t entry;
>  int kcmdline_len;
>  int image_size;
>  
> @@ -76,7 +76,7 @@ void cris_load_image(CRISCPU *cpu, struct cris_load_info 
> *li)
> devboard SDK.  */
>  image_size = load_elf(li->image_filename, NULL,
>translate_kernel_address, NULL,
> -  &entry, NULL, &high, NULL, 0, EM_CRIS, 0, 0);
> +  &entry, NULL, NULL, NULL, 0, EM_CRIS, 0, 0);
>  li->entry = entry;
>  if (image_size < 0) {
>  /* Takes a kimage from the axis devboard SDK.  */
> diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c
> index 925e3f7c9d..8ad3c27f2c 100644
> --- a/hw/microblaze/boot.c
> +++ b/hw/microblaze/boot.c
> @@ -135,7 +135,7 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr 
> ddr_base,
>  
>  if (kernel_filename) {
>  

[Bug 1886362] [NEW] Heap use-after-free in lduw_he_p through e1000e_write_to_rx_buffers

2020-07-05 Thread Alexander Bulekov
Public bug reported:

Hello,
This reproducer causes a heap-use-after free. QEMU Built with 
--enable-sanitizers:
cat << EOF | ./i386-softmmu/qemu-system-i386 -M q35,accel=qtest \
-qtest stdio -nographic -monitor none -serial none
outl 0xcf8 0x80001010
outl 0xcfc 0xe102
outl 0xcf8 0x80001014
outl 0xcf8 0x80001004
outw 0xcfc 0x7
outl 0xcf8 0x800010a2
write 0xe102003b 0x1 0xff
write 0xe1020103 0x1e 
0xff055c5e5c30be4511d084ff
write 0xe1020420 0x4 0x
write 0xe1020424 0x4 0x
write 0xe102042b 0x1 0xff
write 0xe1020430 0x4 0x055c5e5c
write 0x5c041 0x1 0x04
write 0x5c042 0x1 0x02
write 0x5c043 0x1 0xe1
write 0x5c048 0x1 0x8a
write 0x5c04a 0x1 0x31
write 0x5c04b 0x1 0xff
write 0xe1020403 0x1 0xff
EOF

The Output:
==22689==ERROR: AddressSanitizer: heap-use-after-free on address 0x62500026800e 
at pc 0x55b93bb18bfa bp 0x7fffdbe844f0 sp 0x7fffdbe83cb8
READ of size 2 at 0x62500026800e thread T0
#0  in __asan_memcpy (/build/i386-softmmu/qemu-system-i386+)
#1  in lduw_he_p /include/qemu/bswap.h:332:5
#2  in ldn_he_p /include/qemu/bswap.h:550:1
#3  in flatview_write_continue /exec.c:3145:19
#4  in flatview_write /exec.c:3186:14
#5  in address_space_write /exec.c:3280:18
#6  in address_space_rw /exec.c:3290:16
#7  in dma_memory_rw_relaxed /include/sysemu/dma.h:87:18
#8  in dma_memory_rw /include/sysemu/dma.h:113:12
#9  in pci_dma_rw /include/hw/pci/pci.h:789:5
#10  in pci_dma_write /include/hw/pci/pci.h:802:12
#11  in e1000e_write_to_rx_buffers /hw/net/e1000e_core.c:1412:9
#12  in e1000e_write_packet_to_guest /hw/net/e1000e_core.c:1582:21
#13  in e1000e_receive_iov /hw/net/e1000e_core.c:1709:9
#14  in e1000e_nc_receive_iov /hw/net/e1000e.c:213:12
#15  in net_tx_pkt_sendv /hw/net/net_tx_pkt.c:544:9
#16  in net_tx_pkt_send /hw/net/net_tx_pkt.c:620:9
#17  in net_tx_pkt_send_loopback /hw/net/net_tx_pkt.c:633:11
#18  in e1000e_tx_pkt_send /hw/net/e1000e_core.c:664:16
#19  in e1000e_process_tx_desc /hw/net/e1000e_core.c:743:17
#20  in e1000e_start_xmit /hw/net/e1000e_core.c:934:9
#21  in e1000e_set_tctl /hw/net/e1000e_core.c:2431:9
#22  in e1000e_core_write /hw/net/e1000e_core.c:3265:9
#23  in e1000e_mmio_write /hw/net/e1000e.c:109:5
#24  in memory_region_write_accessor /memory.c:483:5
#25  in access_with_adjusted_size /memory.c:544:18
#26  in memory_region_dispatch_write /memory.c:1476:16
#27  in flatview_write_continue /exec.c:3146:23
#28  in flatview_write /exec.c:3186:14
#29  in address_space_write /exec.c:3280:18
#30  in qtest_process_command /qtest.c:567:9
#31  in qtest_process_inbuf /qtest.c:710:9
#32  in qtest_read /qtest.c:722:5
#33  in qemu_chr_be_write_impl /chardev/char.c:188:9
#34  in qemu_chr_be_write /chardev/char.c:200:9
#35  in fd_chr_read /chardev/char-fd.c:68:9
#36  in qio_channel_fd_source_dispatch /io/channel-watch.c:84:12
#37  in g_main_context_dispatch 
(/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0+)
#38  in glib_pollfds_poll /util/main-loop.c:219:9
#39  in os_host_main_loop_wait /util/main-loop.c:242:5
#40  in main_loop_wait /util/main-loop.c:518:11
#41  in qemu_main_loop /softmmu/vl.c:1664:9
#42  in main /softmmu/main.c:52:5
#43  in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+)
#44  in _start (/build/i386-softmmu/qemu-system-i386+)

0x62500026800e is located 14 bytes inside of 138-byte region 
[0x625000268000,0x62500026808a)
freed by thread T0 here:
#0  in free (/build/i386-softmmu/qemu-system-i386+)
#1  in qemu_vfree /util/oslib-posix.c:238:5
#2  in address_space_unmap /exec.c:3616:5
#3  in dma_memory_unmap /include/sysemu/dma.h:148:5
#4  in pci_dma_unmap /include/hw/pci/pci.h:839:5
#5  in net_tx_pkt_reset /hw/net/net_tx_pkt.c:453:9
#6  in e1000e_process_tx_desc /hw/net/e1000e_core.c:749:9
#7  in e1000e_start_xmit /hw/net/e1000e_core.c:934:9
#8  in e1000e_set_tctl /hw/net/e1000e_core.c:2431:9
#9  in e1000e_core_write /hw/net/e1000e_core.c:3265:9
#10  in e1000e_mmio_write /hw/net/e1000e.c:109:5
#11  in memory_region_write_accessor /memory.c:483:5
#12  in access_with_adjusted_size /memory.c:544:18
#13  in memory_region_dispatch_write /memory.c:1476:16
#14  in flatview_write_continue /exec.c:3146:23
#15  in flatview_write /exec.c:3186:14
#16  in address_space_write /exec.c:3280:18
#17  in address_space_rw /exec.c:3290:16
#18  in dma_memory_rw_relaxed /include/sysemu/dma.h:87:18
#19  in dma_memory_rw /include/sysemu/dma.h:113:12
#20  in pci_dma_rw /include/hw/pci/pci.h:789:5
#21  in pci_dma_write /include/hw/pci/pci.h:802:12
#22  in e1000e_write_to_rx_buffers /hw/net/e1000e_core.c:1412:9
#23  in e1000e_write_packet_to_guest /hw/net/e1000e_core.c:1582:21
#24  in e1000e_receive_iov /hw/net/e1000e_core.c:1709:9
#25  in e1000e_nc_receive_iov /hw/net/e1000e.c:213:12
#26

Re: [PATCH v2] ftgmac100: fix dblac write test

2020-07-05 Thread Andrew Jeffery



On Sun, 28 Jun 2020, at 23:56, erik-smit wrote:
> The test of the write of the dblac register was testing the old value
> instead of the new value. This would accept the write of an invalid value
> but subsequently refuse any following valid writes.
> 
> Signed-off-by: erik-smit 
> ---
> Changes since v1:
> 
> Changed %ld to HWADDR_PRIx to fix building on mingw

Bit of a nitpick, but the type of the value argument is uint64_t, so shouldn't 
the result of the expression captured by FTGMAC100_DBLAC_TXDES_SIZE() and 
FTGMAC100_DBLAC_RXDES_SIZE() be printed with a straight PRIx64 rather than 
HWADDR_PRIx?

Otherwise the change seems sensible, so:

Reviewed-by: Andrew Jeffery 



[PATCH] target/xtensa: implement NMI support

2020-07-05 Thread Max Filippov
When NMI is configured it is taken regardless of INTENABLE SR contents,
PS.INTLEVEL or PS.EXCM. It is cleared automatically once it's taken.

Add nmi_level to XtensaConfig, puth there NMI level from the overlay or
XCHAL_NUM_INTLEVELS + 1 when NMI is not configured. Add NMI mask to
INTENABLE SR and limit CINTLEVEL to nmi_level - 1 when determining
pending IRQ level in check_interrupt(). Always take and clear pending
interrupt at nmi_level in the handle_interrupt().

Signed-off-by: Max Filippov 
---
 hw/xtensa/pic_cpu.c  |  6 +-
 target/xtensa/cpu.h  |  1 +
 target/xtensa/exc_helper.c   | 23 +++
 target/xtensa/overlay_tool.h |  6 +-
 4 files changed, 26 insertions(+), 10 deletions(-)

diff --git a/hw/xtensa/pic_cpu.c b/hw/xtensa/pic_cpu.c
index edd53c9241c5..1d5982a9e424 100644
--- a/hw/xtensa/pic_cpu.c
+++ b/hw/xtensa/pic_cpu.c
@@ -35,9 +35,13 @@ void check_interrupts(CPUXtensaState *env)
 {
 CPUState *cs = env_cpu(env);
 int minlevel = xtensa_get_cintlevel(env);
-uint32_t int_set_enabled = env->sregs[INTSET] & env->sregs[INTENABLE];
+uint32_t int_set_enabled = env->sregs[INTSET] &
+(env->sregs[INTENABLE] | env->config->inttype_mask[INTTYPE_NMI]);
 int level;
 
+if (minlevel >= env->config->nmi_level) {
+minlevel = env->config->nmi_level - 1;
+}
 for (level = env->config->nlevel; level > minlevel; --level) {
 if (env->config->level_mask[level] & int_set_enabled) {
 env->pending_irq_level = level;
diff --git a/target/xtensa/cpu.h b/target/xtensa/cpu.h
index 65f00028501a..0c96181212a5 100644
--- a/target/xtensa/cpu.h
+++ b/target/xtensa/cpu.h
@@ -433,6 +433,7 @@ struct XtensaConfig {
 uint32_t exception_vector[EXC_MAX];
 unsigned ninterrupt;
 unsigned nlevel;
+unsigned nmi_level;
 uint32_t interrupt_vector[MAX_NLEVEL + MAX_NNMI + 1];
 uint32_t level_mask[MAX_NLEVEL + MAX_NNMI + 1];
 uint32_t inttype_mask[INTTYPE_MAX];
diff --git a/target/xtensa/exc_helper.c b/target/xtensa/exc_helper.c
index 601341d13aa0..58a64e6d620e 100644
--- a/target/xtensa/exc_helper.c
+++ b/target/xtensa/exc_helper.c
@@ -132,11 +132,15 @@ void HELPER(intset)(CPUXtensaState *env, uint32_t v)
   v & env->config->inttype_mask[INTTYPE_SOFTWARE]);
 }
 
+static void intclear(CPUXtensaState *env, uint32_t v)
+{
+atomic_and(&env->sregs[INTSET], ~v);
+}
+
 void HELPER(intclear)(CPUXtensaState *env, uint32_t v)
 {
-atomic_and(&env->sregs[INTSET],
-   ~(v & (env->config->inttype_mask[INTTYPE_SOFTWARE] |
-  env->config->inttype_mask[INTTYPE_EDGE])));
+intclear(env, v & (env->config->inttype_mask[INTTYPE_SOFTWARE] |
+   env->config->inttype_mask[INTTYPE_EDGE]));
 }
 
 static uint32_t relocated_vector(CPUXtensaState *env, uint32_t vector)
@@ -159,11 +163,11 @@ static void handle_interrupt(CPUXtensaState *env)
 {
 int level = env->pending_irq_level;
 
-if (level > xtensa_get_cintlevel(env) &&
-level <= env->config->nlevel &&
-(env->config->level_mask[level] &
- env->sregs[INTSET] &
- env->sregs[INTENABLE])) {
+if ((level > xtensa_get_cintlevel(env) &&
+ level <= env->config->nlevel &&
+ (env->config->level_mask[level] &
+  env->sregs[INTSET] & env->sregs[INTENABLE])) ||
+level == env->config->nmi_level) {
 CPUState *cs = env_cpu(env);
 
 if (level > 1) {
@@ -173,6 +177,9 @@ static void handle_interrupt(CPUXtensaState *env)
 (env->sregs[PS] & ~PS_INTLEVEL) | level | PS_EXCM;
 env->pc = relocated_vector(env,
env->config->interrupt_vector[level]);
+if (level == env->config->nmi_level) {
+intclear(env, env->config->inttype_mask[INTTYPE_NMI]);
+}
 } else {
 env->sregs[EXCCAUSE] = LEVEL1_INTERRUPT_CAUSE;
 
diff --git a/target/xtensa/overlay_tool.h b/target/xtensa/overlay_tool.h
index a994e69b6e96..eb9f08af0bf6 100644
--- a/target/xtensa/overlay_tool.h
+++ b/target/xtensa/overlay_tool.h
@@ -216,6 +216,9 @@
 #define XTHAL_INTTYPE_IDMA_ERR INTTYPE_IDMA_ERR
 #define XTHAL_INTTYPE_GS_ERR INTTYPE_GS_ERR
 
+#ifndef XCHAL_NMILEVEL
+#define XCHAL_NMILEVEL (XCHAL_NUM_INTLEVELS + 1)
+#endif
 
 #define INTERRUPT(i) { \
 .level = XCHAL_INT ## i ## _LEVEL, \
@@ -305,7 +308,8 @@
 
 #define INTERRUPTS_SECTION \
 .ninterrupt = XCHAL_NUM_INTERRUPTS, \
-.nlevel = XCHAL_NUM_INTLEVELS, \
+.nlevel = XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI, \
+.nmi_level = XCHAL_NMILEVEL, \
 .interrupt_vector = INTERRUPT_VECTORS, \
 .level_mask = LEVEL_MASKS, \
 .inttype_mask = INTTYPE_MASKS, \
-- 
2.20.1




Re: [PATCH v2 1/5] hw/i2c/aspeed_i2c: Simplify aspeed_i2c_get_bus()

2020-07-05 Thread Andrew Jeffery



On Mon, 6 Jul 2020, at 08:11, Philippe Mathieu-Daudé wrote:
> All the callers of aspeed_i2c_get_bus() have a AspeedI2CState and
> cast it to a DeviceState with DEVICE(), then aspeed_i2c_get_bus()
> cast the DeviceState to an AspeedI2CState with ASPEED_I2C()...
> 
> Simplify aspeed_i2c_get_bus() callers by using AspeedI2CState
> argument.
> 
> Reviewed-by: Markus Armbruster 
> Signed-off-by: Philippe Mathieu-Daudé 

Reviewed-by: Andrew Jeffery 



Re: [PATCH v2 1/1] disas: mips: Add Loongson 2F disassembler

2020-07-05 Thread Jiaxun Yang




在 2020/7/3 18:44, Stefan Brankovic 写道:

Add disassembler for Loongson 2F instruction set.

Testing is done by comparing qemu disassembly output, obtained by
using -d in_asm command line option, with appropriate objdump output.

This disassembler is written as a generic disassembler that can be
integrated into other projects. In this case, it is integrated into
QEMU. One of initial key requirements was that it uses C++ as its
language.

Signed-off-by: Stefan Brankovic 


Hi Stefan,

A biref review on the instruction format among some simple test show that
it's working as expected.

Good job!

But I'd agree with Aleksandar's idea, this patch still needs some polishing
on code-style.

Thanks.


---
  MAINTAINERS |1 +
  configure   |1 +
  disas/Makefile.objs |1 +
  disas/loongson2f.cpp| 8154 +++
  disas/loongson2f.h  | 2562 
  include/disas/dis-asm.h |1 +
  include/exec/poison.h   |1 +
  target/mips/cpu.c   |4 +
  8 files changed, 10725 insertions(+)
  create mode 100644 disas/loongson2f.cpp
  create mode 100644 disas/loongson2f.h





RE: [PATCH 3/3] target/nios2: Use gen_io_start around wrctl instruction

2020-07-05 Thread Wu, Wentong
Maybe below patch will reduce some overhead, because currently it will exit to 
main loop to handle interrupt but if with (env->regs[CR_STATUS] & 
CR_STATUS_PIE) = False, it does nothing except set env->irq_pending again.

diff --git a/hw/nios2/cpu_pic.c b/hw/nios2/cpu_pic.c
index 1c1989d5..5ea7e52a 100644
--- a/hw/nios2/cpu_pic.c
+++ b/hw/nios2/cpu_pic.c
@@ -54,7 +54,8 @@ static void nios2_pic_cpu_handler(void *opaque, int irq, int 
level)

 void nios2_check_interrupts(CPUNios2State *env)
 {
-if (env->irq_pending) {
+if (env->irq_pending &&
+(env->regs[CR_STATUS] & CR_STATUS_PIE)) {
 env->irq_pending = 0;
 cpu_interrupt(env_cpu(env), CPU_INTERRUPT_HARD);
 }

-Original Message-
From: Richard Henderson  
Sent: Friday, July 3, 2020 2:54 AM
To: Wu, Wentong ; qemu-devel@nongnu.org
Cc: qemu-triv...@nongnu.org; ma...@denx.de; crwu...@gmail.com; 
peter.mayd...@linaro.org
Subject: Re: [PATCH 3/3] target/nios2: Use gen_io_start around wrctl instruction

On 6/29/20 9:05 AM, Wentong Wu wrote:
> wrctl instruction on nios2 target will cause checking cpu interrupt 
> but tcg_handle_interrupt() will call cpu_abort() if the CPU gets an 
> interrupt while it's not in 'can do IO'
> state, so add gen_io_start around wrctl instruction. Also at the same 
> time, end the onging TB with DISAS_UPDATE.
> 
> Signed-off-by: Wentong Wu 
> ---
>  target/nios2/translate.c | 5 +
>  1 file changed, 5 insertions(+)
> 
> diff --git a/target/nios2/translate.c b/target/nios2/translate.c index 
> 83c10eb2..51347ada 100644
> --- a/target/nios2/translate.c
> +++ b/target/nios2/translate.c
> @@ -32,6 +32,7 @@
>  #include "exec/cpu_ldst.h"
>  #include "exec/translator.h"
>  #include "qemu/qemu-print.h"
> +#include "exec/gen-icount.h"
>  
>  /* is_jmp field values */
>  #define DISAS_JUMPDISAS_TARGET_0 /* only pc was modified dynamically */
> @@ -518,7 +519,11 @@ static void wrctl(DisasContext *dc, uint32_t code, 
> uint32_t flags)
>  /* If interrupts were enabled using WRCTL, trigger them. */  #if 
> !defined(CONFIG_USER_ONLY)
>  if ((instr.imm5 + CR_BASE) == CR_STATUS) {
> +if (tb_cflags(dc->tb) & CF_USE_ICOUNT) {
> +gen_io_start();
> +}
>  gen_helper_check_interrupts(dc->cpu_env);
> +dc->is_jmp = DISAS_UPDATE;
>  }
>  #endif

This isn't right.  Not so much the gen_io_start portion, but the entire 
existence of helper_check_interrupt.

The correct way to acknowledge interrupts after changing an interrupt mask bit 
is to exit the TB back to the cpu main loop.
Which you are doing here with DISAS_UPDATE, so that part is fine.  (Although 
you could merge that into the switch statement above.)

Looking at nios_pic_cpu_handler, there are two other bugs:

1) Get rid of env->irq_pending and use cpu_interrupt/cpu_reset_interrupt 
instead.

2) Do not check env->regs[CR_STATUS] & CR_STATUS_PIE.  That variable does not 
belong to the pic and should not be checked there.  The check belongs in 
nios2_cpu_exec_interrupt, and is in fact already there.


r~


RE: [PATCH 3/3] target/nios2: Use gen_io_start around wrctl instruction

2020-07-05 Thread Wu, Wentong
Thanks, I think we can get this series merged currently.

-Original Message-
From: Peter Maydell  
Sent: Monday, July 6, 2020 1:10 AM
To: Wu, Wentong 
Cc: QEMU Developers ; QEMU Trivial 
; Chris Wulff ; Marek Vasut 

Subject: Re: [PATCH 3/3] target/nios2: Use gen_io_start around wrctl instruction

On Mon, 29 Jun 2020 at 09:17, Wentong Wu  wrote:
>
> wrctl instruction on nios2 target will cause checking cpu interrupt 
> but tcg_handle_interrupt() will call cpu_abort() if the CPU gets an 
> interrupt while it's not in 'can do IO'
> state, so add gen_io_start around wrctl instruction. Also at the same 
> time, end the onging TB with DISAS_UPDATE.
>
> Signed-off-by: Wentong Wu 
> ---
>  target/nios2/translate.c | 5 +
>  1 file changed, 5 insertions(+)
>
> diff --git a/target/nios2/translate.c b/target/nios2/translate.c index 
> 83c10eb2..51347ada 100644
> --- a/target/nios2/translate.c
> +++ b/target/nios2/translate.c
> @@ -32,6 +32,7 @@
>  #include "exec/cpu_ldst.h"
>  #include "exec/translator.h"
>  #include "qemu/qemu-print.h"
> +#include "exec/gen-icount.h"
>
>  /* is_jmp field values */
>  #define DISAS_JUMPDISAS_TARGET_0 /* only pc was modified dynamically */
> @@ -518,7 +519,11 @@ static void wrctl(DisasContext *dc, uint32_t code, 
> uint32_t flags)
>  /* If interrupts were enabled using WRCTL, trigger them. */  #if 
> !defined(CONFIG_USER_ONLY)
>  if ((instr.imm5 + CR_BASE) == CR_STATUS) {
> +if (tb_cflags(dc->tb) & CF_USE_ICOUNT) {
> +gen_io_start();
> +}
>  gen_helper_check_interrupts(dc->cpu_env);
> +dc->is_jmp = DISAS_UPDATE;
>  }
>  #endif
>  }

Reviewed-by: Peter Maydell 

though as Richard notes ideally the interrupt handling code here should be 
rewritten because the check_interrupts helper is a very weird way to implement 
things.

thanks
-- PMM


[PATCH 2/2] target/i386: Enable TSX Suspend Load Address Tracking feature

2020-07-05 Thread Cathy Zhang
This instruction aims to give a way to choose which memory accesses
do not need to be tracked in the TSX read set, which is defined as
CPUID.(EAX=7,ECX=0):EDX[bit 16].

The release spec link is as follows:
https://software.intel.com/content/dam/develop/public/us/en/documents/\
architecture-instruction-set-extensions-programming-reference.pdf

The associated kvm patch link is as follows:
https://lore.kernel.org/patchwork/patch/1268026/

Signed-off-by: Cathy Zhang 
---
 target/i386/cpu.c | 2 +-
 target/i386/cpu.h | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 92716f4..256a9a1 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -987,7 +987,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
 NULL, NULL, NULL, NULL,
 "avx512-vp2intersect", NULL, "md-clear", NULL,
 NULL, NULL, "serialize", NULL,
-NULL, NULL, NULL /* pconfig */, NULL,
+"tsx-ldtrk", NULL, NULL /* pconfig */, NULL,
 NULL, NULL, NULL, NULL,
 NULL, NULL, "spec-ctrl", "stibp",
 NULL, "arch-capabilities", "core-capability", "ssbd",
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 3ef1123..155972b 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -779,6 +779,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];
 #define CPUID_7_0_EDX_AVX512_VP2INTERSECT (1U << 8)
 /* SERIALIZE instruction */
 #define CPUID_7_0_EDX_SERIALIZE (1U << 14)
+/* TSX Suspend Load Address Tracking instruction */
+#define CPUID_7_0_EDX_TSX_LDTRK (1U << 16)
 /* Speculation Control */
 #define CPUID_7_0_EDX_SPEC_CTRL (1U << 26)
 /* Single Thread Indirect Branch Predictors */
-- 
1.8.3.1




[PATCH 1/2] target/i386: Add SERIALIZE cpu feature

2020-07-05 Thread Cathy Zhang
The availability of the SERIALIZATION instruction is indicated
by the presence of the CPUID feature flag SERIALIZE, which is
defined as CPUID.(EAX=7,ECX=0):ECX[bit 14].

The release spec link is as follows:
https://software.intel.com/content/dam/develop/public/us/en/documents/\
architecture-instruction-set-extensions-programming-reference.pdf

The associated kvm patch link is as follows:
https://lore.kernel.org/patchwork/patch/1268025/

Signed-off-by: Cathy Zhang 
---
 target/i386/cpu.c | 2 +-
 target/i386/cpu.h | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 36cbd3d..92716f4 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -986,7 +986,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
 NULL, NULL, "avx512-4vnniw", "avx512-4fmaps",
 NULL, NULL, NULL, NULL,
 "avx512-vp2intersect", NULL, "md-clear", NULL,
-NULL, NULL, NULL, NULL,
+NULL, NULL, "serialize", NULL,
 NULL, NULL, NULL /* pconfig */, NULL,
 NULL, NULL, NULL, NULL,
 NULL, NULL, "spec-ctrl", "stibp",
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 7d77efd..3ef1123 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -777,6 +777,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS];
 #define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3)
 /* AVX512 Vector Pair Intersection to a Pair of Mask Registers */
 #define CPUID_7_0_EDX_AVX512_VP2INTERSECT (1U << 8)
+/* SERIALIZE instruction */
+#define CPUID_7_0_EDX_SERIALIZE (1U << 14)
 /* Speculation Control */
 #define CPUID_7_0_EDX_SPEC_CTRL (1U << 26)
 /* Single Thread Indirect Branch Predictors */
-- 
1.8.3.1




[PATCH 0/2] Add new features for intel processor

2020-07-05 Thread Cathy Zhang
This patchset is to add two new features for intel processors
which support them, like Sapphire Rapids. SERIALIZE is a faster
serializing instruction which does not modify registers,
arithmetic flags or memory, will not cause VM exit. TSX suspend
load tracking instruction aims to give a way to choose which
memory accesses do not need to be tracked in the TSX read set.

Cathy Zhang (2):
  target/i386: Add SERIALIZE cpu feature
  target/i386: Enable TSX Suspend Load Address Tracking feature

 target/i386/cpu.c | 4 ++--
 target/i386/cpu.h | 4 
 2 files changed, 6 insertions(+), 2 deletions(-)

--
1.8.3.1




[PATCH v2 4/5] hw/i2c: Rename i2c_create_slave() as i2c_slave_create_simple()

2020-07-05 Thread Philippe Mathieu-Daudé
We use "create_simple" names for functions that allocate, initialize,
configure and realize device objects: pci_create_simple(),
isa_create_simple(), usb_create_simple(). For consistency, rename
i2c_create_slave() as i2c_slave_create_simple(). Since we have
to update all the callers, also let it return a I2CSlave object.

Suggested-by: Markus Armbruster 
Reviewed-by: Corey Minyard 
Reviewed-by: Markus Armbruster 
Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/i2c/i2c.h |  2 +-
 hw/arm/aspeed.c  | 58 ++--
 hw/arm/musicpal.c|  4 +--
 hw/arm/nseries.c |  8 +++---
 hw/arm/pxa2xx.c  |  5 ++--
 hw/arm/realview.c|  2 +-
 hw/arm/spitz.c   |  4 +--
 hw/arm/stellaris.c   |  2 +-
 hw/arm/tosa.c|  2 +-
 hw/arm/versatilepb.c |  2 +-
 hw/arm/vexpress.c|  2 +-
 hw/arm/z2.c  |  4 +--
 hw/display/sii9022.c |  2 +-
 hw/i2c/core.c|  6 ++---
 hw/ppc/e500.c|  2 +-
 hw/ppc/sam460ex.c|  2 +-
 16 files changed, 54 insertions(+), 53 deletions(-)

diff --git a/include/hw/i2c/i2c.h b/include/hw/i2c/i2c.h
index cb7211f027..c533058998 100644
--- a/include/hw/i2c/i2c.h
+++ b/include/hw/i2c/i2c.h
@@ -80,7 +80,7 @@ int i2c_send(I2CBus *bus, uint8_t data);
 uint8_t i2c_recv(I2CBus *bus);
 
 I2CSlave *i2c_slave_new(const char *name, uint8_t addr);
-DeviceState *i2c_create_slave(I2CBus *bus, const char *name, uint8_t addr);
+I2CSlave *i2c_slave_create_simple(I2CBus *bus, const char *name, uint8_t addr);
 bool i2c_slave_realize_and_unref(I2CSlave *dev, I2CBus *bus, Error **errp);
 
 /* lm832x.c */
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index ed14e79f57..5fa95f0f02 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -385,14 +385,14 @@ static void palmetto_bmc_i2c_init(AspeedMachineState *bmc)
 
 /* The palmetto platform expects a ds3231 RTC but a ds1338 is
  * enough to provide basic RTC features. Alarms will be missing */
-i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 0), "ds1338", 0x68);
+i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 0), "ds1338", 0x68);
 
 smbus_eeprom_init_one(aspeed_i2c_get_bus(&soc->i2c, 0), 0x50,
   eeprom_buf);
 
 /* add a TMP423 temperature sensor */
-dev = i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 2),
-   "tmp423", 0x4c);
+dev = DEVICE(i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 2),
+ "tmp423", 0x4c));
 object_property_set_int(OBJECT(dev), 31000, "temperature0", &error_abort);
 object_property_set_int(OBJECT(dev), 28000, "temperature1", &error_abort);
 object_property_set_int(OBJECT(dev), 2, "temperature2", &error_abort);
@@ -408,12 +408,12 @@ static void ast2500_evb_i2c_init(AspeedMachineState *bmc)
   eeprom_buf);
 
 /* The AST2500 EVB expects a LM75 but a TMP105 is compatible */
-i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 7),
+i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 7),
  TYPE_TMP105, 0x4d);
 
 /* The AST2500 EVB does not have an RTC. Let's pretend that one is
  * plugged on the I2C bus header */
-i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 11), "ds1338", 0x32);
+i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), "ds1338", 0x32);
 }
 
 static void ast2600_evb_i2c_init(AspeedMachineState *bmc)
@@ -428,36 +428,36 @@ static void romulus_bmc_i2c_init(AspeedMachineState *bmc)
 
 /* The romulus board expects Epson RX8900 I2C RTC but a ds1338 is
  * good enough */
-i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 11), "ds1338", 0x32);
+i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 11), "ds1338", 0x32);
 }
 
 static void swift_bmc_i2c_init(AspeedMachineState *bmc)
 {
 AspeedSoCState *soc = &bmc->soc;
 
-i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 3), "pca9552", 0x60);
+i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 3), "pca9552", 0x60);
 
 /* The swift board expects a TMP275 but a TMP105 is compatible */
-i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 7), "tmp105", 0x48);
+i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 7), "tmp105", 0x48);
 /* The swift board expects a pca9551 but a pca9552 is compatible */
-i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 7), "pca9552", 0x60);
+i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 7), "pca9552", 0x60);
 
 /* The swift board expects an Epson RX8900 RTC but a ds1338 is compatible 
*/
-i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 8), "ds1338", 0x32);
-i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 8), "pca9552", 0x60);
+i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), "ds1338", 0x32);
+i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 8), "pca9552", 0x60);
 
-i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 9), "tmp423", 0x4c);
+i2c_slave_create_simple(aspeed_i2c_get_bus(&soc->i2c, 9),

[PATCH v2 5/5] hw/i2c: Document the I2C qdev helpers

2020-07-05 Thread Philippe Mathieu-Daudé
In commit d88c42ff2c we added new prototype but neglected to
add their documentation. Fix that.

Reported-by: Peter Maydell 
Reviewed-by: Corey Minyard 
Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/i2c/i2c.h | 48 
 1 file changed, 48 insertions(+)

diff --git a/include/hw/i2c/i2c.h b/include/hw/i2c/i2c.h
index c533058998..a9c030a512 100644
--- a/include/hw/i2c/i2c.h
+++ b/include/hw/i2c/i2c.h
@@ -79,8 +79,56 @@ int i2c_send_recv(I2CBus *bus, uint8_t *data, bool send);
 int i2c_send(I2CBus *bus, uint8_t data);
 uint8_t i2c_recv(I2CBus *bus);
 
+/**
+ * Create an I2C slave device on the heap.
+ * @name: a device type name
+ * @addr: I2C address of the slave when put on a bus
+ *
+ * This only initializes the device state structure and allows
+ * properties to be set. Type @name must exist. The device still
+ * needs to be realized. See qdev-core.h.
+ */
 I2CSlave *i2c_slave_new(const char *name, uint8_t addr);
+
+/**
+ * Create and realize an I2C slave device on the heap.
+ * @bus: I2C bus to put it on
+ * @name: I2C slave device type name
+ * @addr: I2C address of the slave when put on a bus
+ *
+ * Create the device state structure, initialize it, put it on the
+ * specified @bus, and drop the reference to it (the device is realized).
+ */
 I2CSlave *i2c_slave_create_simple(I2CBus *bus, const char *name, uint8_t addr);
+
+/**
+ * Realize and and drop a reference an I2C slave device
+ * @dev: I2C slave device to realize
+ * @bus: I2C bus to put it on
+ * @addr: I2C address of the slave on the bus
+ * @errp: pointer to NULL initialized error object
+ *
+ * Returns: %true on success, %false on failure.
+ *
+ * Call 'realize' on @dev, put it on the specified @bus, and drop the
+ * reference to it.
+ *
+ * This function is useful if you have created @dev via qdev_new(),
+ * i2c_slave_new() or i2c_slave_try_new() (which take a reference to
+ * the device it returns to you), so that you can set properties on it
+ * before realizing it. If you don't need to set properties then
+ * i2c_slave_create_simple() is probably better (as it does the create,
+ * init and realize in one step).
+ *
+ * If you are embedding the I2C slave into another QOM device and
+ * initialized it via some variant on object_initialize_child() then
+ * do not use this function, because that family of functions arrange
+ * for the only reference to the child device to be held by the parent
+ * via the child<> property, and so the reference-count-drop done here
+ * would be incorrect.  (Instead you would want i2c_slave_realize(),
+ * which doesn't currently exist but would be trivial to create if we
+ * had any code that wanted it.)
+ */
 bool i2c_slave_realize_and_unref(I2CSlave *dev, I2CBus *bus, Error **errp);
 
 /* lm832x.c */
-- 
2.21.3




[PATCH v2 2/5] hw/i2c: Rename i2c_try_create_slave() as i2c_slave_new()

2020-07-05 Thread Philippe Mathieu-Daudé
We use "new" names for functions that allocate and initialize
device objects: pci_new(), isa_new(), usb_new().
Let's call this one i2c_slave_new(). Since we have to update
all the callers, also let it return a I2CSlave object.

Suggested-by: Markus Armbruster 
Reviewed-by: Markus Armbruster 
Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/i2c/i2c.h |  2 +-
 hw/arm/aspeed.c  |  4 ++--
 hw/i2c/core.c| 11 +--
 3 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/include/hw/i2c/i2c.h b/include/hw/i2c/i2c.h
index d6e3d85faf..18efc668f1 100644
--- a/include/hw/i2c/i2c.h
+++ b/include/hw/i2c/i2c.h
@@ -79,8 +79,8 @@ int i2c_send_recv(I2CBus *bus, uint8_t *data, bool send);
 int i2c_send(I2CBus *bus, uint8_t data);
 uint8_t i2c_recv(I2CBus *bus);
 
+I2CSlave *i2c_slave_new(const char *name, uint8_t addr);
 DeviceState *i2c_create_slave(I2CBus *bus, const char *name, uint8_t addr);
-DeviceState *i2c_try_create_slave(const char *name, uint8_t addr);
 bool i2c_realize_and_unref(DeviceState *dev, I2CBus *bus, Error **errp);
 
 /* lm832x.c */
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 1285bf82c0..54ca36e0b6 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -513,7 +513,7 @@ static void witherspoon_bmc_i2c_init(AspeedMachineState 
*bmc)
 /* Bus 3: TODO bmp280@77 */
 /* Bus 3: TODO max31785@52 */
 /* Bus 3: TODO dps310@76 */
-dev = i2c_try_create_slave(TYPE_PCA9552, 0x60);
+dev = DEVICE(i2c_slave_new(TYPE_PCA9552, 0x60));
 qdev_prop_set_string(dev, "description", "pca1");
 i2c_realize_and_unref(dev, aspeed_i2c_get_bus(&soc->i2c, 3),
   &error_fatal);
@@ -531,7 +531,7 @@ static void witherspoon_bmc_i2c_init(AspeedMachineState 
*bmc)
 
 smbus_eeprom_init_one(aspeed_i2c_get_bus(&soc->i2c, 11), 0x51,
   eeprom_buf);
-dev = i2c_try_create_slave(TYPE_PCA9552, 0x60);
+dev = DEVICE(i2c_slave_new(TYPE_PCA9552, 0x60));
 qdev_prop_set_string(dev, "description", "pca0");
 i2c_realize_and_unref(dev, aspeed_i2c_get_bus(&soc->i2c, 11),
   &error_fatal);
diff --git a/hw/i2c/core.c b/hw/i2c/core.c
index acf34a12d6..144786f17a 100644
--- a/hw/i2c/core.c
+++ b/hw/i2c/core.c
@@ -267,13 +267,13 @@ const VMStateDescription vmstate_i2c_slave = {
 }
 };
 
-DeviceState *i2c_try_create_slave(const char *name, uint8_t addr)
+I2CSlave *i2c_slave_new(const char *name, uint8_t addr)
 {
 DeviceState *dev;
 
 dev = qdev_new(name);
 qdev_prop_set_uint8(dev, "address", addr);
-return dev;
+return I2C_SLAVE(dev);
 }
 
 bool i2c_realize_and_unref(DeviceState *dev, I2CBus *bus, Error **errp)
@@ -283,12 +283,11 @@ bool i2c_realize_and_unref(DeviceState *dev, I2CBus *bus, 
Error **errp)
 
 DeviceState *i2c_create_slave(I2CBus *bus, const char *name, uint8_t addr)
 {
-DeviceState *dev;
+I2CSlave *dev = i2c_slave_new(name, addr);
 
-dev = i2c_try_create_slave(name, addr);
-i2c_realize_and_unref(dev, bus, &error_fatal);
+i2c_realize_and_unref(DEVICE(dev), bus, &error_fatal);
 
-return dev;
+return DEVICE(dev);
 }
 
 static void i2c_slave_class_init(ObjectClass *klass, void *data)
-- 
2.21.3




[PATCH v2 1/5] hw/i2c/aspeed_i2c: Simplify aspeed_i2c_get_bus()

2020-07-05 Thread Philippe Mathieu-Daudé
All the callers of aspeed_i2c_get_bus() have a AspeedI2CState and
cast it to a DeviceState with DEVICE(), then aspeed_i2c_get_bus()
cast the DeviceState to an AspeedI2CState with ASPEED_I2C()...

Simplify aspeed_i2c_get_bus() callers by using AspeedI2CState
argument.

Reviewed-by: Markus Armbruster 
Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/i2c/aspeed_i2c.h |  2 +-
 hw/arm/aspeed.c | 70 ++---
 hw/i2c/aspeed_i2c.c |  3 +-
 3 files changed, 37 insertions(+), 38 deletions(-)

diff --git a/include/hw/i2c/aspeed_i2c.h b/include/hw/i2c/aspeed_i2c.h
index f1b9e5bf91..243789ae5d 100644
--- a/include/hw/i2c/aspeed_i2c.h
+++ b/include/hw/i2c/aspeed_i2c.h
@@ -93,6 +93,6 @@ typedef struct AspeedI2CClass {
 
 } AspeedI2CClass;
 
-I2CBus *aspeed_i2c_get_bus(DeviceState *dev, int busnr);
+I2CBus *aspeed_i2c_get_bus(AspeedI2CState *s, int busnr);
 
 #endif /* ASPEED_I2C_H */
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 379f9672a5..1285bf82c0 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -385,13 +385,13 @@ static void palmetto_bmc_i2c_init(AspeedMachineState *bmc)
 
 /* The palmetto platform expects a ds3231 RTC but a ds1338 is
  * enough to provide basic RTC features. Alarms will be missing */
-i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 0), "ds1338", 0x68);
+i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 0), "ds1338", 0x68);
 
-smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 0), 0x50,
+smbus_eeprom_init_one(aspeed_i2c_get_bus(&soc->i2c, 0), 0x50,
   eeprom_buf);
 
 /* add a TMP423 temperature sensor */
-dev = i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 2),
+dev = i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 2),
"tmp423", 0x4c);
 object_property_set_int(OBJECT(dev), 31000, "temperature0", &error_abort);
 object_property_set_int(OBJECT(dev), 28000, "temperature1", &error_abort);
@@ -404,16 +404,16 @@ static void ast2500_evb_i2c_init(AspeedMachineState *bmc)
 AspeedSoCState *soc = &bmc->soc;
 uint8_t *eeprom_buf = g_malloc0(8 * 1024);
 
-smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 3), 0x50,
+smbus_eeprom_init_one(aspeed_i2c_get_bus(&soc->i2c, 3), 0x50,
   eeprom_buf);
 
 /* The AST2500 EVB expects a LM75 but a TMP105 is compatible */
-i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 7),
+i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 7),
  TYPE_TMP105, 0x4d);
 
 /* The AST2500 EVB does not have an RTC. Let's pretend that one is
  * plugged on the I2C bus header */
-i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), "ds1338", 
0x32);
+i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 11), "ds1338", 0x32);
 }
 
 static void ast2600_evb_i2c_init(AspeedMachineState *bmc)
@@ -428,36 +428,36 @@ static void romulus_bmc_i2c_init(AspeedMachineState *bmc)
 
 /* The romulus board expects Epson RX8900 I2C RTC but a ds1338 is
  * good enough */
-i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), "ds1338", 
0x32);
+i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 11), "ds1338", 0x32);
 }
 
 static void swift_bmc_i2c_init(AspeedMachineState *bmc)
 {
 AspeedSoCState *soc = &bmc->soc;
 
-i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 3), "pca9552", 
0x60);
+i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 3), "pca9552", 0x60);
 
 /* The swift board expects a TMP275 but a TMP105 is compatible */
-i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 7), "tmp105", 0x48);
+i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 7), "tmp105", 0x48);
 /* The swift board expects a pca9551 but a pca9552 is compatible */
-i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 7), "pca9552", 
0x60);
+i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 7), "pca9552", 0x60);
 
 /* The swift board expects an Epson RX8900 RTC but a ds1338 is compatible 
*/
-i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 8), "ds1338", 0x32);
-i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 8), "pca9552", 
0x60);
+i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 8), "ds1338", 0x32);
+i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 8), "pca9552", 0x60);
 
-i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 9), "tmp423", 0x4c);
+i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 9), "tmp423", 0x4c);
 /* The swift board expects a pca9539 but a pca9552 is compatible */
-i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 9), "pca9552", 
0x74);
+i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 9), "pca9552", 0x74);
 
-i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 10), "tmp423", 
0x4c);
+i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 10), "tmp423", 0x4c);
 /* The swift board expects a pca9539 but a pca9552 is compatible */
-i2c

[PATCH v2 3/5] hw/i2c: Rename i2c_realize_and_unref() as i2c_slave_realize_and_unref()

2020-07-05 Thread Philippe Mathieu-Daudé
The other i2c functions are called i2c_slave_FOO(). Rename as
i2c_slave_realize_and_unref() to be consistent.

Suggested-by: Markus Armbruster 
Reviewed-by: Corey Minyard 
Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/i2c/i2c.h |  2 +-
 hw/arm/aspeed.c  | 10 ++
 hw/i2c/core.c|  6 +++---
 3 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/include/hw/i2c/i2c.h b/include/hw/i2c/i2c.h
index 18efc668f1..cb7211f027 100644
--- a/include/hw/i2c/i2c.h
+++ b/include/hw/i2c/i2c.h
@@ -81,7 +81,7 @@ uint8_t i2c_recv(I2CBus *bus);
 
 I2CSlave *i2c_slave_new(const char *name, uint8_t addr);
 DeviceState *i2c_create_slave(I2CBus *bus, const char *name, uint8_t addr);
-bool i2c_realize_and_unref(DeviceState *dev, I2CBus *bus, Error **errp);
+bool i2c_slave_realize_and_unref(I2CSlave *dev, I2CBus *bus, Error **errp);
 
 /* lm832x.c */
 void lm832x_key_event(DeviceState *dev, int key, int state);
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 54ca36e0b6..ed14e79f57 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -515,8 +515,9 @@ static void witherspoon_bmc_i2c_init(AspeedMachineState 
*bmc)
 /* Bus 3: TODO dps310@76 */
 dev = DEVICE(i2c_slave_new(TYPE_PCA9552, 0x60));
 qdev_prop_set_string(dev, "description", "pca1");
-i2c_realize_and_unref(dev, aspeed_i2c_get_bus(&soc->i2c, 3),
-  &error_fatal);
+i2c_slave_realize_and_unref(I2C_SLAVE(dev),
+aspeed_i2c_get_bus(&soc->i2c, 3),
+&error_fatal);
 
 i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 4), "tmp423", 0x4c);
 i2c_create_slave(aspeed_i2c_get_bus(&soc->i2c, 5), "tmp423", 0x4c);
@@ -533,8 +534,9 @@ static void witherspoon_bmc_i2c_init(AspeedMachineState 
*bmc)
   eeprom_buf);
 dev = DEVICE(i2c_slave_new(TYPE_PCA9552, 0x60));
 qdev_prop_set_string(dev, "description", "pca0");
-i2c_realize_and_unref(dev, aspeed_i2c_get_bus(&soc->i2c, 11),
-  &error_fatal);
+i2c_slave_realize_and_unref(I2C_SLAVE(dev),
+aspeed_i2c_get_bus(&soc->i2c, 11),
+&error_fatal);
 /* Bus 11: TODO ucd90160@64 */
 }
 
diff --git a/hw/i2c/core.c b/hw/i2c/core.c
index 144786f17a..f81601a5b9 100644
--- a/hw/i2c/core.c
+++ b/hw/i2c/core.c
@@ -276,16 +276,16 @@ I2CSlave *i2c_slave_new(const char *name, uint8_t addr)
 return I2C_SLAVE(dev);
 }
 
-bool i2c_realize_and_unref(DeviceState *dev, I2CBus *bus, Error **errp)
+bool i2c_slave_realize_and_unref(I2CSlave *dev, I2CBus *bus, Error **errp)
 {
-return qdev_realize_and_unref(dev, &bus->qbus, errp);
+return qdev_realize_and_unref(&dev->qdev, &bus->qbus, errp);
 }
 
 DeviceState *i2c_create_slave(I2CBus *bus, const char *name, uint8_t addr)
 {
 I2CSlave *dev = i2c_slave_new(name, addr);
 
-i2c_realize_and_unref(DEVICE(dev), bus, &error_fatal);
+i2c_slave_realize_and_unref(dev, bus, &error_fatal);
 
 return DEVICE(dev);
 }
-- 
2.21.3




[PATCH v2 0/5] hw/i2c: Rename method names for consistency and add documentation

2020-07-05 Thread Philippe Mathieu-Daudé
In commit d88c42ff2c we added 2 methods: i2c_try_create_slave()
and i2c_realize_and_unref().
Markus noted their name could be improved for consistency [1],
and Peter reported the lack of documentation [2]. Fix that now.

Since v1:
- Addressed Markus review comments
- Added Markus/Corey R-b tags

[1] https://lists.gnu.org/archive/html/qemu-devel/2020-06/msg07060.html
[2] https://lists.gnu.org/archive/html/qemu-devel/2020-06/msg08997.html

$ git backport-diff -u -v1
Key:
[] : patches are identical
[] : number of functional differences between upstream/downstream patch
[down] : patch is downstream-only
The flags [FC] indicate (F)unctional and (C)ontextual differences, respectively

001/5:[] [--] 'hw/i2c/aspeed_i2c: Simplify aspeed_i2c_get_bus()'
002/5:[0006] [FC] 'hw/i2c: Rename i2c_try_create_slave() as i2c_slave_new()'
003/5:[0004] [FC] 'hw/i2c: Rename i2c_realize_and_unref() as 
i2c_slave_realize_and_unref()'
004/5:[0006] [FC] 'hw/i2c: Rename i2c_create_slave() as 
i2c_slave_create_simple()'
005/5:[0012] [FC] 'hw/i2c: Document the I2C qdev helpers'

Philippe Mathieu-Daudé (5):
  hw/i2c/aspeed_i2c: Simplify aspeed_i2c_get_bus()
  hw/i2c: Rename i2c_try_create_slave() as i2c_slave_new()
  hw/i2c: Rename i2c_realize_and_unref() as
i2c_slave_realize_and_unref()
  hw/i2c: Rename i2c_create_slave() as i2c_slave_create_simple()
  hw/i2c: Document the I2C qdev helpers

 include/hw/i2c/aspeed_i2c.h |  2 +-
 include/hw/i2c/i2c.h| 54 ++--
 hw/arm/aspeed.c | 82 +++--
 hw/arm/musicpal.c   |  4 +-
 hw/arm/nseries.c|  8 ++--
 hw/arm/pxa2xx.c |  5 ++-
 hw/arm/realview.c   |  2 +-
 hw/arm/spitz.c  |  4 +-
 hw/arm/stellaris.c  |  2 +-
 hw/arm/tosa.c   |  2 +-
 hw/arm/versatilepb.c|  2 +-
 hw/arm/vexpress.c   |  2 +-
 hw/arm/z2.c |  4 +-
 hw/display/sii9022.c|  2 +-
 hw/i2c/aspeed_i2c.c |  3 +-
 hw/i2c/core.c   | 15 ---
 hw/ppc/e500.c   |  2 +-
 hw/ppc/sam460ex.c   |  2 +-
 18 files changed, 123 insertions(+), 74 deletions(-)

-- 
2.21.3




[PATCH v2] hw/core/qdev: Increase qdev_realize() kindness

2020-07-05 Thread Philippe Mathieu-Daudé
Since commit 510ef98dca5, qdev_realize() aborts if bus-less
device is realized on a bus. Be kind with the developer by
displaying a hint about what is wrong.

Signed-off-by: Philippe Mathieu-Daudé 
---
v2: Use errp (bonzini suggestion)

Paolo, I was tempted to check errp is really &error_abort else
it is an error! :P

} else if (DEVICE_GET_CLASS(dev)->bus_type) {
error_setg(errp, "%s: Unexpected bus '%s' for bus-less device '%s'",
   __func__, DEVICE_GET_CLASS(dev)->bus_type,
   object_get_typename(OBJECT(dev)));
assert(errp == &error_abort); // <--
return false;
}
---
 hw/core/qdev.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 2131c7f951..9d1530c39d 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -392,8 +392,11 @@ bool qdev_realize(DeviceState *dev, BusState *bus, Error 
**errp)
 
 if (bus) {
 qdev_set_parent_bus(dev, bus);
-} else {
-assert(!DEVICE_GET_CLASS(dev)->bus_type);
+} else if (DEVICE_GET_CLASS(dev)->bus_type) {
+error_setg(errp, "%s: Unexpected bus '%s' for bus-less device '%s'",
+   __func__, DEVICE_GET_CLASS(dev)->bus_type,
+   object_get_typename(OBJECT(dev)));
+return false;
 }
 
 object_property_set_bool(OBJECT(dev), true, "realized", &err);
-- 
2.21.3




[RFC PATCH 2/2] hw/sd/sdcard: Deprecate the SPI mode

2020-07-05 Thread Philippe Mathieu-Daudé
SD cards be used with SPI, SD or MMC protocol.

Unfortunately, maintaining the SPI protocol make improving the
MMC mode very difficult. As of 2020 users are more interested
in using cards with the MMC protocol.

Signed-off-by: Philippe Mathieu-Daudé 
---
 docs/system/deprecated.rst | 5 +
 1 file changed, 5 insertions(+)

diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
index 5e67d7f3e0..01dca3d038 100644
--- a/docs/system/deprecated.rst
+++ b/docs/system/deprecated.rst
@@ -384,6 +384,11 @@ full SCSI support.  Use virtio-scsi instead when SCSI 
passthrough is required.
 Note this also applies to ``-device virtio-blk-pci,scsi=on|off``, which is an
 alias.
 
+``-device sd-card,spi=on`` (since 5.1)
+^^
+
+The SPI mode of the 'sd-card' device is deprecated.
+
 Block device options
 
 
-- 
2.21.3




[RFC PATCH 1/2] hw/sd/ssi-sd: Deprecate the SPI to SD card 'adapter'

2020-07-05 Thread Philippe Mathieu-Daudé
This device duplicate the SPI mode of the sd-card device. The
SPI protocol is better handler in the sd-card, however as the
TYPE_SSI_SLAVE is not an interface, the sd-card can not implement
it easily to be pluggable on a SPI bus. Meanwhile the ssi-sd
device acts as a bridge, but is bitroting. Deprecate it.

Signed-off-by: Philippe Mathieu-Daudé 
---
 docs/system/deprecated.rst | 5 +
 1 file changed, 5 insertions(+)

diff --git a/docs/system/deprecated.rst b/docs/system/deprecated.rst
index 47f84be8e0..5e67d7f3e0 100644
--- a/docs/system/deprecated.rst
+++ b/docs/system/deprecated.rst
@@ -343,6 +343,11 @@ The 'ide-drive' device is deprecated. Users should use 
'ide-hd' or
 The 'scsi-disk' device is deprecated. Users should use 'scsi-hd' or
 'scsi-cd' as appropriate to get a SCSI hard disk or CD-ROM as needed.
 
+``ssi-sd`` (since 5.1)
+'
+
+The 'ssi-sd' (SSI to SD card adapter) device is deprecated.
+
 System emulator machines
 
 
-- 
2.21.3




[RFC PATCH 0/2] hw/sd: Deprecate the SPI mode and the SPI to SD adapter

2020-07-05 Thread Philippe Mathieu-Daudé
I tried to maintain the SPI mode because it is useful in
tiny embedded devices, and thought it would be helpful for
the AVR MCUs.
As AVR was blocked, I thought it was wise to deprecate the
SPI mode as users are interested in the faster MMC mode.
Today Thomas surprised me by posting an update of it!
https://www.mail-archive.com/qemu-devel@nongnu.org/msg720089.html

I'm still posting this as RFC to discuss, but I'm reconsiderating
keeping this mode a bit more.

Philippe Mathieu-Daudé (2):
  hw/sd/ssi-sd: Deprecate the SPI to SD card 'adapter'
  hw/sd/sdcard: Deprecate the SPI mode

 docs/system/deprecated.rst | 10 ++
 1 file changed, 10 insertions(+)

-- 
2.21.3




[PATCH 2/2] hw/sd/pxa2xx_mmci: Trivial simplification

2020-07-05 Thread Philippe Mathieu-Daudé
Avoid declaring PXA2xxMMCIState local variable, return it directly.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/pxa2xx_mmci.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c
index 9482b9212d..2996a2ef17 100644
--- a/hw/sd/pxa2xx_mmci.c
+++ b/hw/sd/pxa2xx_mmci.c
@@ -480,10 +480,8 @@ PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem,
 {
 DeviceState *dev;
 SysBusDevice *sbd;
-PXA2xxMMCIState *s;
 
 dev = qdev_new(TYPE_PXA2XX_MMCI);
-s = PXA2XX_MMCI(dev);
 sbd = SYS_BUS_DEVICE(dev);
 sysbus_mmio_map(sbd, 0, base);
 sysbus_connect_irq(sbd, 0, irq);
@@ -491,7 +489,7 @@ PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem,
 qdev_connect_gpio_out_named(dev, "tx-dma", 0, tx_dma);
 sysbus_realize_and_unref(sbd, &error_fatal);
 
-return s;
+return PXA2XX_MMCI(dev);
 }
 
 static void pxa2xx_mmci_set_inserted(DeviceState *dev, bool inserted)
-- 
2.21.3




[PATCH 1/2] hw/sd/pxa2xx_mmci: Do not create SD card within the SDHCI controller

2020-07-05 Thread Philippe Mathieu-Daudé
SDHCI controllers provide a SD Bus to plug SD cards, but don't
come with SD card plugged in :) Let the machine/board object
create and plug the SD cards when required.

Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/arm/pxa.h |  3 +--
 hw/arm/pxa2xx.c  | 39 +--
 hw/sd/pxa2xx_mmci.c  | 11 ++-
 3 files changed, 32 insertions(+), 21 deletions(-)

diff --git a/include/hw/arm/pxa.h b/include/hw/arm/pxa.h
index 8843e5f910..d99b6192da 100644
--- a/include/hw/arm/pxa.h
+++ b/include/hw/arm/pxa.h
@@ -89,8 +89,7 @@ void pxa2xx_lcd_vsync_notifier(PXA2xxLCDState *s, qemu_irq 
handler);
 typedef struct PXA2xxMMCIState PXA2xxMMCIState;
 PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem,
 hwaddr base,
-BlockBackend *blk, qemu_irq irq,
-qemu_irq rx_dma, qemu_irq tx_dma);
+qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma);
 void pxa2xx_mmci_handlers(PXA2xxMMCIState *s, qemu_irq readonly,
 qemu_irq coverswitch);
 
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index f104a33463..78f6e69f63 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -22,6 +22,7 @@
 #include "hw/irq.h"
 #include "hw/qdev-properties.h"
 #include "hw/ssi/ssi.h"
+#include "hw/sd/sd.h"
 #include "chardev/char-fe.h"
 #include "sysemu/blockdev.h"
 #include "sysemu/qtest.h"
@@ -2135,15 +2136,24 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
 
 s->gpio = pxa2xx_gpio_init(0x40e0, s->cpu, s->pic, 121);
 
-dinfo = drive_get(IF_SD, 0, 0);
-if (!dinfo && !qtest_enabled()) {
-warn_report("missing SecureDigital device");
-}
 s->mmc = pxa2xx_mmci_init(address_space, 0x4110,
-dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
 qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC),
 qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI),
 qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI));
+dinfo = drive_get(IF_SD, 0, 0);
+if (dinfo) {
+DeviceState *carddev;
+
+/* Create and plug in the sd card */
+carddev = qdev_new(TYPE_SD_CARD);
+qdev_prop_set_drive_err(carddev, "drive",
+blk_by_legacy_dinfo(dinfo), &error_fatal);
+qdev_realize_and_unref(carddev, qdev_get_child_bus(DEVICE(s->mmc),
+   "sd-bus"),
+   &error_fatal);
+} else if (!qtest_enabled()) {
+warn_report("missing SecureDigital device");
+}
 
 for (i = 0; pxa270_serial[i].io_base; i++) {
 if (serial_hd(i)) {
@@ -2259,15 +2269,24 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, 
unsigned int sdram_size)
 
 s->gpio = pxa2xx_gpio_init(0x40e0, s->cpu, s->pic, 85);
 
-dinfo = drive_get(IF_SD, 0, 0);
-if (!dinfo && !qtest_enabled()) {
-warn_report("missing SecureDigital device");
-}
 s->mmc = pxa2xx_mmci_init(address_space, 0x4110,
-dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
 qdev_get_gpio_in(s->pic, PXA2XX_PIC_MMC),
 qdev_get_gpio_in(s->dma, PXA2XX_RX_RQ_MMCI),
 qdev_get_gpio_in(s->dma, PXA2XX_TX_RQ_MMCI));
+dinfo = drive_get(IF_SD, 0, 0);
+if (dinfo) {
+DeviceState *carddev;
+
+/* Create and plug in the sd card */
+carddev = qdev_new(TYPE_SD_CARD);
+qdev_prop_set_drive_err(carddev, "drive",
+blk_by_legacy_dinfo(dinfo), &error_fatal);
+qdev_realize_and_unref(carddev, qdev_get_child_bus(DEVICE(s->mmc),
+   "sd-bus"),
+   &error_fatal);
+} else if (!qtest_enabled()) {
+warn_report("missing SecureDigital device");
+}
 
 for (i = 0; pxa255_serial[i].io_base; i++) {
 if (serial_hd(i)) {
diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c
index 68bed24480..9482b9212d 100644
--- a/hw/sd/pxa2xx_mmci.c
+++ b/hw/sd/pxa2xx_mmci.c
@@ -476,10 +476,9 @@ static const MemoryRegionOps pxa2xx_mmci_ops = {
 
 PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem,
 hwaddr base,
-BlockBackend *blk, qemu_irq irq,
-qemu_irq rx_dma, qemu_irq tx_dma)
+qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma)
 {
-DeviceState *dev, *carddev;
+DeviceState *dev;
 SysBusDevice *sbd;
 PXA2xxMMCIState *s;
 
@@ -492,12 +491,6 @@ PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem,
 qdev_connect_gpio_out_named(dev, "tx-dma", 0, tx_dma);
 sysbus_realize_and_unref(sbd, &error_fatal);
 
-/* Create and plug in the sd card */
-carddev = qdev_new(TYPE_SD_CARD);
-qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
-qdev_realize_and_unref(carddev, qdev_get_child_bus(dev, "sd-bus"),
-   &error_fatal);
-
 

[PATCH 0/2] hw/sd/pxa2xx_mmci: Do not create SD card within the SDHCI controller

2020-07-05 Thread Philippe Mathieu-Daudé
SDHCI controllers provide a SD Bus to plug SD cards, but don't
come with SD card plugged in

This series move the SD card creation to the machine/board code.

Regards,

Phil.

Philippe Mathieu-Daudé (2):
  hw/sd/pxa2xx_mmci: Do not create SD card within the SDHCI controller
  hw/sd/pxa2xx_mmci: Trivial simplification

 include/hw/arm/pxa.h |  3 +--
 hw/arm/pxa2xx.c  | 39 +--
 hw/sd/pxa2xx_mmci.c  | 15 +++
 3 files changed, 33 insertions(+), 24 deletions(-)

-- 
2.21.3




Re: [PATCH rc6 26/30] target/avr: Update build system

2020-07-05 Thread Philippe Mathieu-Daudé
On 7/5/20 4:03 PM, Thomas Huth wrote:
> From: Michael Rolnik 
> 
> Make AVR support buildable.
> 
> [AM: Remove word 'Atmel' from filenames and all elements of code]
> Suggested-by: Aleksandar Markovic 
> Signed-off-by: Michael Rolnik 
> Signed-off-by: Richard Henderson 
> Signed-off-by: Aleksandar Markovic 
> Tested-by: Philippe Mathieu-Daudé 
> Reviewed-by: Aleksandar Markovic 
> Signed-off-by: Thomas Huth 
> ---
>  MAINTAINERS |  1 +
>  configure   |  7 +++
>  default-configs/avr-softmmu.mak |  5 +
>  target/avr/Makefile.objs| 34 +
>  4 files changed, 47 insertions(+)
>  create mode 100644 default-configs/avr-softmmu.mak
>  create mode 100644 target/avr/Makefile.objs

IMO this belongs to patch #22 "target/avr: Register AVR support with the
rest of QEMU". Trivial conflict in MAINTAINERS while squashing.

> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 0ab0a0e40b..79e7470f5c 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -982,6 +982,7 @@ AVR MCUs
>  M: Michael Rolnik 
>  R: Sarah Harris 
>  S: Maintained
> +F: default-configs/avr-softmmu.mak
>  F: hw/avr/
>  F: include/hw/char/avr_usart.h
>  F: hw/char/avr_usart.c
> diff --git a/configure b/configure
> index 8a65240d4a..e84b532bf5 100755
> --- a/configure
> +++ b/configure
> @@ -8105,6 +8105,10 @@ case "$target_name" in
>  mttcg="yes"
>  gdb_xml_files="aarch64-core.xml aarch64-fpu.xml arm-core.xml arm-vfp.xml 
> arm-vfp3.xml arm-neon.xml arm-m-profile.xml"
>;;
> +  avr)
> +gdb_xml_files="avr-cpu.xml"
> +target_compiler=$cross_cc_avr
> +  ;;
>cris)
>;;
>hppa)
> @@ -8349,6 +8353,9 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
>disas_config "ARM_A64"
>  fi
>;;
> +  avr)
> +disas_config "AVR"
> +  ;;
>cris)
>  disas_config "CRIS"
>;;
> diff --git a/default-configs/avr-softmmu.mak b/default-configs/avr-softmmu.mak
> new file mode 100644
> index 00..80218add98
> --- /dev/null
> +++ b/default-configs/avr-softmmu.mak
> @@ -0,0 +1,5 @@
> +# Default configuration for avr-softmmu
> +
> +# Boards:
> +#
> +CONFIG_ARDUINO=y
> diff --git a/target/avr/Makefile.objs b/target/avr/Makefile.objs
> new file mode 100644
> index 00..7523e0c6e2
> --- /dev/null
> +++ b/target/avr/Makefile.objs
> @@ -0,0 +1,34 @@
> +#
> +#  QEMU AVR CPU
> +#
> +#  Copyright (c) 2019 Michael Rolnik
> +#
> +#  This library is free software; you can redistribute it and/or
> +#  modify it under the terms of the GNU Lesser General Public
> +#  License as published by the Free Software Foundation; either
> +#  version 2.1 of the License, or (at your option) any later version.
> +#
> +#  This library is distributed in the hope that it will be useful,
> +#  but WITHOUT ANY WARRANTY; without even the implied warranty of
> +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +#  Lesser General Public License for more details.
> +#
> +#  You should have received a copy of the GNU Lesser General Public
> +#  License along with this library; if not, see
> +#  
> +#
> +
> +DECODETREE = $(SRC_PATH)/scripts/decodetree.py
> +decode-y = $(SRC_PATH)/target/avr/insn.decode
> +
> +target/avr/decode_insn.inc.c: $(decode-y) $(DECODETREE)
> + $(call quiet-command, \
> +   $(PYTHON) $(DECODETREE) -o $@ --decode decode_insn --insnwidth 16 $<, 
> \
> +   "GEN", $(TARGET_DIR)$@)
> +
> +target/avr/translate.o: target/avr/decode_insn.inc.c
> +
> +obj-y += translate.o cpu.o helper.o
> +obj-y += gdbstub.o
> +obj-y += disas.o
> +obj-$(CONFIG_SOFTMMU) += machine.o
> 



[PATCH 1/4] hw/lm32/milkymist: Un-inline milkymist_memcard_create()

2020-07-05 Thread Philippe Mathieu-Daudé
As we will modify milkymist_memcard_create(), move it first
to the source file where it is used.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/lm32/milkymist-hw.h | 11 ---
 hw/lm32/milkymist.c| 11 +++
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/hw/lm32/milkymist-hw.h b/hw/lm32/milkymist-hw.h
index 05e2c2a5a7..5dca5d52f5 100644
--- a/hw/lm32/milkymist-hw.h
+++ b/hw/lm32/milkymist-hw.h
@@ -31,17 +31,6 @@ static inline DeviceState *milkymist_hpdmc_create(hwaddr 
base)
 return dev;
 }
 
-static inline DeviceState *milkymist_memcard_create(hwaddr base)
-{
-DeviceState *dev;
-
-dev = qdev_new("milkymist-memcard");
-sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
-sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
-
-return dev;
-}
-
 static inline DeviceState *milkymist_vgafb_create(hwaddr base,
 uint32_t fb_offset, uint32_t fb_mask)
 {
diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c
index 85913bb68b..469e3c4322 100644
--- a/hw/lm32/milkymist.c
+++ b/hw/lm32/milkymist.c
@@ -80,6 +80,17 @@ static void main_cpu_reset(void *opaque)
 env->deba = reset_info->flash_base;
 }
 
+static DeviceState *milkymist_memcard_create(hwaddr base)
+{
+DeviceState *dev;
+
+dev = qdev_new("milkymist-memcard");
+sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
+sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+
+return dev;
+}
+
 static void
 milkymist_init(MachineState *machine)
 {
-- 
2.21.3




[PATCH 3/4] hw/sd/milkymist: Create the SDBus at init()

2020-07-05 Thread Philippe Mathieu-Daudé
We don't need to wait until realize() to create the SDBus,
create it in init() directly.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/milkymist-memcard.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c
index afdb8aa0c0..fb02309f07 100644
--- a/hw/sd/milkymist-memcard.c
+++ b/hw/sd/milkymist-memcard.c
@@ -261,6 +261,9 @@ static void milkymist_memcard_init(Object *obj)
 memory_region_init_io(&s->regs_region, OBJECT(s), &memcard_mmio_ops, s,
 "milkymist-memcard", R_MAX * 4);
 sysbus_init_mmio(dev, &s->regs_region);
+
+qbus_create_inplace(&s->sdbus, sizeof(s->sdbus), TYPE_SD_BUS,
+DEVICE(obj), "sd-bus");
 }
 
 static void milkymist_memcard_realize(DeviceState *dev, Error **errp)
@@ -271,9 +274,6 @@ static void milkymist_memcard_realize(DeviceState *dev, 
Error **errp)
 DriveInfo *dinfo;
 Error *err = NULL;
 
-qbus_create_inplace(&s->sdbus, sizeof(s->sdbus), TYPE_SD_BUS,
-dev, "sd-bus");
-
 /* Create and plug in the sd card */
 /* FIXME use a qdev drive property instead of drive_get_next() */
 dinfo = drive_get_next(IF_SD);
-- 
2.21.3




[PATCH 0/4] hw/sd/milkymist: Do not create SD card within the SDHCI controller

2020-07-05 Thread Philippe Mathieu-Daudé
SDHCI controllers provide a SD Bus to plug SD cards, but don't
come with SD card plugged in :)

This series move the SD card creation to the machine/board code.

Regards,

Phil.

Philippe Mathieu-Daudé (4):
  hw/lm32/milkymist: Un-inline milkymist_memcard_create()
  hw/lm32/milkymist: Comment to remember some IRQs lines are left
unwired
  hw/sd/milkymist: Create the SDBus at init()
  hw/sd/milkymist: Do not create SD card within the SDHCI controller

 hw/lm32/milkymist-hw.h| 11 
 hw/lm32/milkymist.c   | 25 +
 hw/sd/milkymist-memcard.c | 57 ++-
 3 files changed, 58 insertions(+), 35 deletions(-)

-- 
2.21.3




[PATCH 2/4] hw/lm32/milkymist: Comment to remember some IRQs lines are left unwired

2020-07-05 Thread Philippe Mathieu-Daudé
The 'card is readonly' and 'card inserted' IRQs are not wired.
Add a comment in case someone know where to wire them.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/lm32/milkymist.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c
index 469e3c4322..117973c967 100644
--- a/hw/lm32/milkymist.c
+++ b/hw/lm32/milkymist.c
@@ -87,6 +87,7 @@ static DeviceState *milkymist_memcard_create(hwaddr base)
 dev = qdev_new("milkymist-memcard");
 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
+/* FIXME wire 'card is readonly' and 'card inserted' IRQs? */
 
 return dev;
 }
-- 
2.21.3




[PATCH 4/4] hw/sd/milkymist: Do not create SD card within the SDHCI controller

2020-07-05 Thread Philippe Mathieu-Daudé
SDHCI controllers provide a SD Bus to plug SD cards, but don't
come with SD card plugged in :) Let the machine/board object
create and plug the SD cards when required.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/lm32/milkymist.c   | 13 +
 hw/sd/milkymist-memcard.c | 55 +++
 2 files changed, 45 insertions(+), 23 deletions(-)

diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c
index 117973c967..8e2c68da5a 100644
--- a/hw/lm32/milkymist.c
+++ b/hw/lm32/milkymist.c
@@ -34,6 +34,7 @@
 #include "elf.h"
 #include "milkymist-hw.h"
 #include "hw/display/milkymist_tmu2.h"
+#include "hw/sd/sd.h"
 #include "lm32.h"
 #include "exec/address-spaces.h"
 #include "qemu/cutils.h"
@@ -83,12 +84,24 @@ static void main_cpu_reset(void *opaque)
 static DeviceState *milkymist_memcard_create(hwaddr base)
 {
 DeviceState *dev;
+DriveInfo *dinfo;
 
 dev = qdev_new("milkymist-memcard");
 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
 sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
 /* FIXME wire 'card is readonly' and 'card inserted' IRQs? */
 
+dinfo = drive_get_next(IF_SD);
+if (dinfo) {
+DeviceState *card;
+
+card = qdev_new(TYPE_SD_CARD);
+qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo),
+&error_fatal);
+qdev_realize_and_unref(card, qdev_get_child_bus(dev, "sd-bus"),
+   &error_fatal);
+}
+
 return dev;
 }
 
diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c
index fb02309f07..e9f5db5e22 100644
--- a/hw/sd/milkymist-memcard.c
+++ b/hw/sd/milkymist-memcard.c
@@ -66,6 +66,8 @@ enum {
 #define MILKYMIST_MEMCARD(obj) \
 OBJECT_CHECK(MilkymistMemcardState, (obj), TYPE_MILKYMIST_MEMCARD)
 
+#define TYPE_MILKYMIST_SDBUS "milkymist-sdbus"
+
 struct MilkymistMemcardState {
 SysBusDevice parent_obj;
 
@@ -253,6 +255,19 @@ static void milkymist_memcard_reset(DeviceState *d)
 }
 }
 
+static void milkymist_memcard_set_readonly(DeviceState *dev, bool level)
+{
+qemu_log_mask(LOG_UNIMP,
+  "milkymist_memcard: read-only mode not supported\n");
+}
+
+static void milkymist_memcard_set_inserted(DeviceState *dev, bool level)
+{
+MilkymistMemcardState *s = MILKYMIST_MEMCARD(dev);
+
+s->enabled = !!level;
+}
+
 static void milkymist_memcard_init(Object *obj)
 {
 MilkymistMemcardState *s = MILKYMIST_MEMCARD(obj);
@@ -266,27 +281,6 @@ static void milkymist_memcard_init(Object *obj)
 DEVICE(obj), "sd-bus");
 }
 
-static void milkymist_memcard_realize(DeviceState *dev, Error **errp)
-{
-MilkymistMemcardState *s = MILKYMIST_MEMCARD(dev);
-DeviceState *carddev;
-BlockBackend *blk;
-DriveInfo *dinfo;
-Error *err = NULL;
-
-/* Create and plug in the sd card */
-/* FIXME use a qdev drive property instead of drive_get_next() */
-dinfo = drive_get_next(IF_SD);
-blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
-carddev = qdev_new(TYPE_SD_CARD);
-qdev_prop_set_drive(carddev, "drive", blk);
-if (!qdev_realize_and_unref(carddev, BUS(&s->sdbus), &err)) {
-error_propagate_prepend(errp, err, "failed to init SD card: %s");
-return;
-}
-s->enabled = blk && blk_is_inserted(blk);
-}
-
 static const VMStateDescription vmstate_milkymist_memcard = {
 .name = "milkymist-memcard",
 .version_id = 1,
@@ -308,10 +302,9 @@ static void milkymist_memcard_class_init(ObjectClass 
*klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 
-dc->realize = milkymist_memcard_realize;
 dc->reset = milkymist_memcard_reset;
 dc->vmsd = &vmstate_milkymist_memcard;
-/* Reason: init() method uses drive_get_next() */
+/* Reason: output IRQs should be wired up */
 dc->user_creatable = false;
 }
 
@@ -323,9 +316,25 @@ static const TypeInfo milkymist_memcard_info = {
 .class_init= milkymist_memcard_class_init,
 };
 
+static void milkymist_sdbus_class_init(ObjectClass *klass, void *data)
+{
+SDBusClass *sbc = SD_BUS_CLASS(klass);
+
+sbc->set_inserted = milkymist_memcard_set_inserted;
+sbc->set_readonly = milkymist_memcard_set_readonly;
+}
+
+static const TypeInfo milkymist_sdbus_info = {
+.name = TYPE_MILKYMIST_SDBUS,
+.parent = TYPE_SD_BUS,
+.instance_size = sizeof(SDBus),
+.class_init = milkymist_sdbus_class_init,
+};
+
 static void milkymist_memcard_register_types(void)
 {
 type_register_static(&milkymist_memcard_info);
+type_register_static(&milkymist_sdbus_info);
 }
 
 type_init(milkymist_memcard_register_types)
-- 
2.21.3




Re: [PATCH 3/3] target/nios2: Use gen_io_start around wrctl instruction

2020-07-05 Thread Max Filippov
On Sun, Jul 5, 2020 at 11:16 AM Max Filippov  wrote:
> On Sun, Jul 5, 2020 at 10:09 AM Peter Maydell  
> wrote:
> > On Thu, 2 Jul 2020 at 19:53, Richard Henderson
> >  wrote:
> > > This isn't right.  Not so much the gen_io_start portion, but the entire
> > > existence of helper_check_interrupt.
> > I agree that it looks bogus (xtensa has a similar helper as well, 
> > incidentally),
> I think there was a reason for it.

...and the reason is that this helper calls cpu_[re]set_interrupt
to update CPU_INTERRUPT_HARD, which makes exit to the
main CPU loop do something to handle IRQ.
Maybe 'check_interrupt' is not a good name for that, but the
action taken there seems right to me.

-- 
Thanks.
-- Max



[PATCH v4 09/10] hw/sd/sdcard: make sd_data_ready() static

2020-07-05 Thread Philippe Mathieu-Daudé
sd_data_ready() belongs to the legacy API. As its last user has
been converted to the SDBus API, make it static.

Reviewed-by: Alistair Francis 
Message-Id: <20180216022933.10945-7-f4...@amsat.org>
Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/sd/sd.h | 1 -
 hw/sd/sd.c | 2 +-
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
index a84b8e274a..ace350e0e8 100644
--- a/include/hw/sd/sd.h
+++ b/include/hw/sd/sd.h
@@ -143,7 +143,6 @@ int sd_do_command(SDState *sd, SDRequest *req,
 void sd_write_data(SDState *sd, uint8_t value);
 uint8_t sd_read_data(SDState *sd);
 void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert);
-bool sd_data_ready(SDState *sd);
 /* sd_enable should not be used -- it is only used on the nseries boards,
  * where it is part of a broken implementation of the MMC card slot switch
  * (there should be two card slots which are multiplexed to a single MMC
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 97a9d32964..54b1414131 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -2059,7 +2059,7 @@ uint8_t sd_read_data(SDState *sd)
 return ret;
 }
 
-bool sd_data_ready(SDState *sd)
+static bool sd_data_ready(SDState *sd)
 {
 return sd->state == sd_sendingdata_state;
 }
-- 
2.21.3




[PATCH v4 10/10] hw/sd: move sdcard legacy API to 'hw/sd/sdcard_legacy.h'

2020-07-05 Thread Philippe Mathieu-Daudé
omap_mmc.c is the last device left using the legacy sdcard API.
Move the prototype declarations into a separate header, to
make it clear this is a legacy API.

Reviewed-by: Alistair Francis 
Message-Id: <20180216022933.10945-8-f4...@amsat.org>
Signed-off-by: Philippe Mathieu-Daudé 
---
 include/hw/sd/sd.h| 16 ---
 include/hw/sd/sdcard_legacy.h | 50 +++
 hw/sd/omap_mmc.c  |  2 +-
 hw/sd/sd.c|  1 +
 4 files changed, 52 insertions(+), 17 deletions(-)
 create mode 100644 include/hw/sd/sdcard_legacy.h

diff --git a/include/hw/sd/sd.h b/include/hw/sd/sd.h
index ace350e0e8..8767ab817c 100644
--- a/include/hw/sd/sd.h
+++ b/include/hw/sd/sd.h
@@ -136,22 +136,6 @@ typedef struct {
 void (*set_readonly)(DeviceState *dev, bool readonly);
 } SDBusClass;
 
-/* Legacy functions to be used only by non-qdevified callers */
-SDState *sd_init(BlockBackend *bs, bool is_spi);
-int sd_do_command(SDState *sd, SDRequest *req,
-  uint8_t *response);
-void sd_write_data(SDState *sd, uint8_t value);
-uint8_t sd_read_data(SDState *sd);
-void sd_set_cb(SDState *sd, qemu_irq readonly, qemu_irq insert);
-/* sd_enable should not be used -- it is only used on the nseries boards,
- * where it is part of a broken implementation of the MMC card slot switch
- * (there should be two card slots which are multiplexed to a single MMC
- * controller, but instead we model it with one card and controller and
- * disable the card when the second slot is selected, so it looks like the
- * second slot is always empty).
- */
-void sd_enable(SDState *sd, bool enable);
-
 /* Functions to be used by qdevified callers (working via
  * an SDBus rather than directly with SDState)
  */
diff --git a/include/hw/sd/sdcard_legacy.h b/include/hw/sd/sdcard_legacy.h
new file mode 100644
index 00..8681f8089b
--- /dev/null
+++ b/include/hw/sd/sdcard_legacy.h
@@ -0,0 +1,50 @@
+/*
+ * SD Memory Card emulation (deprecated legacy API)
+ *
+ * Copyright (c) 2006 Andrzej Zaborowski  
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *notice, this list of conditions and the following disclaimer in
+ *the documentation and/or other materials provided with the
+ *distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef HW_SDCARD_LEGACY_H
+#define HW_SDCARD_LEGACY_H
+
+#include "hw/sd/sd.h"
+
+/* Legacy functions to be used only by non-qdevified callers */
+SDState *sd_init(BlockBackend *blk, bool is_spi);
+int sd_do_command(SDState *card, SDRequest *request, uint8_t *response);
+void sd_write_data(SDState *card, uint8_t value);
+uint8_t sd_read_data(SDState *card);
+void sd_set_cb(SDState *card, qemu_irq readonly, qemu_irq insert);
+
+/* sd_enable should not be used -- it is only used on the nseries boards,
+ * where it is part of a broken implementation of the MMC card slot switch
+ * (there should be two card slots which are multiplexed to a single MMC
+ * controller, but instead we model it with one card and controller and
+ * disable the card when the second slot is selected, so it looks like the
+ * second slot is always empty).
+ */
+void sd_enable(SDState *card, bool enable);
+
+#endif /* HW_SDCARD_LEGACY_H */
diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c
index 4088a8a80b..7d33c59226 100644
--- a/hw/sd/omap_mmc.c
+++ b/hw/sd/omap_mmc.c
@@ -23,7 +23,7 @@
 #include "qemu/log.h"
 #include "hw/irq.h"
 #include "hw/arm/omap.h"
-#include "hw/sd/sd.h"
+#include "hw/sd/sdcard_legacy.h"
 
 struct omap_mmc_s {
 qemu_irq irq;
diff --git a/hw/sd/sd.c b/hw/sd/sd.c
index 54b1414131..6bd7ed59e7 100644
--- a/hw/sd/sd.c
+++ b/hw/sd/sd.c
@@ -36,6 +36,7 @@
 #include "hw/registerfields.h"
 #include "sysemu/block-backend.h"
 #include "hw/sd/sd.h"
+#include "hw/sd/sdcard_legacy.h"
 #include "migration/vmstate.h"
 #include "qapi/error.h"
 #include "qemu/bitmap.h"
-- 
2.21.3




[PATCH v4 07/10] hw/sd/pl181: Do not create SD card within the SDHCI controller

2020-07-05 Thread Philippe Mathieu-Daudé
SDHCI controllers provide a SD Bus to plug SD cards, but don't
come with SD card plugged in :) Let the machine/board object
create and plug the SD cards when required.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/arm/integratorcp.c | 13 +
 hw/arm/realview.c | 12 
 hw/arm/versatilepb.c  | 26 --
 hw/arm/vexpress.c | 11 +++
 hw/sd/pl181.c | 19 +--
 5 files changed, 61 insertions(+), 20 deletions(-)

diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
index 2595e4d052..9bf25945d2 100644
--- a/hw/arm/integratorcp.c
+++ b/hw/arm/integratorcp.c
@@ -25,6 +25,7 @@
 #include "hw/char/pl011.h"
 #include "hw/hw.h"
 #include "hw/irq.h"
+#include "hw/sd/sd.h"
 
 #define TYPE_INTEGRATOR_CM "integrator_core"
 #define INTEGRATOR_CM(obj) \
@@ -595,6 +596,7 @@ static void integratorcp_init(MachineState *machine)
 MemoryRegion *ram_alias = g_new(MemoryRegion, 1);
 qemu_irq pic[32];
 DeviceState *dev, *sic, *icp;
+DriveInfo *dinfo;
 int i;
 
 cpuobj = object_new(machine->cpu_type);
@@ -649,6 +651,17 @@ static void integratorcp_init(MachineState *machine)
   qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_WPROT, 0));
 qdev_connect_gpio_out_named(dev, "card-inserted", 0,
   qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_CARDIN, 0));
+dinfo = drive_get_next(IF_SD);
+if (dinfo) {
+DeviceState *card;
+
+card = qdev_new(TYPE_SD_CARD);
+qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo),
+&error_fatal);
+qdev_realize_and_unref(card, qdev_get_child_bus(dev, "sd-bus"),
+   &error_fatal);
+}
+
 sysbus_create_varargs("pl041", 0x1d00, pic[25], NULL);
 
 if (nd_table[0].used)
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
index 8dc5f77139..4df8ea4fce 100644
--- a/hw/arm/realview.c
+++ b/hw/arm/realview.c
@@ -27,6 +27,7 @@
 #include "hw/intc/realview_gic.h"
 #include "hw/irq.h"
 #include "hw/i2c/arm_sbcon_i2c.h"
+#include "hw/sd/sd.h"
 
 #define SMP_BOOT_ADDR 0xe000
 #define SMP_BOOTREG_ADDR 0x1030
@@ -69,6 +70,7 @@ static void realview_init(MachineState *machine,
 qemu_irq mmc_irq[2];
 PCIBus *pci_bus = NULL;
 NICInfo *nd;
+DriveInfo *dinfo;
 I2CBus *i2c;
 int n;
 unsigned int smp_cpus = machine->smp.cpus;
@@ -236,6 +238,16 @@ static void realview_init(MachineState *machine,
 qemu_irq_invert(qdev_get_gpio_in(gpio2, 0)));
 qdev_connect_gpio_out_named(dev, "card-read-only", 0, mmc_irq[0]);
 qdev_connect_gpio_out_named(dev, "card-inserted", 0, mmc_irq[1]);
+dinfo = drive_get_next(IF_SD);
+if (dinfo) {
+DeviceState *card;
+
+card = qdev_new(TYPE_SD_CARD);
+qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo),
+&error_fatal);
+qdev_realize_and_unref(card, qdev_get_child_bus(dev, "sd-bus"),
+   &error_fatal);
+}
 
 sysbus_create_simple("pl031", 0x10017000, pic[10]);
 
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
index 45a13ae2b9..7fb9da5a47 100644
--- a/hw/arm/versatilepb.c
+++ b/hw/arm/versatilepb.c
@@ -25,6 +25,7 @@
 #include "hw/block/flash.h"
 #include "qemu/error-report.h"
 #include "hw/char/pl011.h"
+#include "hw/sd/sd.h"
 
 #define VERSATILE_FLASH_ADDR 0x3400
 #define VERSATILE_FLASH_SIZE (64 * 1024 * 1024)
@@ -309,10 +310,31 @@ static void versatile_init(MachineState *machine, int 
board_id)
 /* Wire up the mux control signals from the SYS_CLCD register */
 qdev_connect_gpio_out(sysctl, 0, qdev_get_gpio_in(dev, 0));
 
-sysbus_create_varargs("pl181", 0x10005000, sic[22], sic[1], NULL);
+dev = sysbus_create_varargs("pl181", 0x10005000, sic[22], sic[1], NULL);
 /* FIXME wire 'card is readonly' and 'card inserted' IRQs? */
-sysbus_create_varargs("pl181", 0x1000b000, sic[23], sic[2], NULL);
+dinfo = drive_get_next(IF_SD);
+if (dinfo) {
+DeviceState *card;
+
+card = qdev_new(TYPE_SD_CARD);
+qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo),
+&error_fatal);
+qdev_realize_and_unref(card, qdev_get_child_bus(dev, "sd-bus"),
+   &error_fatal);
+}
+
+dev = sysbus_create_varargs("pl181", 0x1000b000, sic[23], sic[2], NULL);
 /* FIXME wire 'card is readonly' and 'card inserted' IRQs? */
+dinfo = drive_get_next(IF_SD);
+if (dinfo) {
+DeviceState *card;
+
+card = qdev_new(TYPE_SD_CARD);
+qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo),
+&error_fatal);
+qdev_realize_and_unref(card, qdev_get_child_bus(dev, "sd-bus"),
+   &error_fatal);
+}
 
 /* Add PL031 Real Time Clock. */
 sysbus_create_simple("pl031",

[PATCH v4 08/10] hw/sd/pl181: Replace disabled fprintf()s by trace events

2020-07-05 Thread Philippe Mathieu-Daudé
Convert disabled DPRINTF() to trace events and remove ifdef'ry.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/pl181.c  | 26 +-
 hw/sd/trace-events | 10 ++
 2 files changed, 19 insertions(+), 17 deletions(-)

diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
index f69488ebac..574500ce60 100644
--- a/hw/sd/pl181.c
+++ b/hw/sd/pl181.c
@@ -17,15 +17,7 @@
 #include "qemu/module.h"
 #include "qemu/error-report.h"
 #include "qapi/error.h"
-
-//#define DEBUG_PL181 1
-
-#ifdef DEBUG_PL181
-#define DPRINTF(fmt, ...) \
-do { printf("pl181: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while(0)
-#endif
+#include "trace.h"
 
 #define PL181_FIFO_LEN 16
 
@@ -158,7 +150,7 @@ static void pl181_fifo_push(PL181State *s, uint32_t value)
 n = (s->fifo_pos + s->fifo_len) & (PL181_FIFO_LEN - 1);
 s->fifo_len++;
 s->fifo[n] = value;
-DPRINTF("FIFO push %08x\n", (int)value);
+trace_pl181_fifo_push(value);
 }
 
 static uint32_t pl181_fifo_pop(PL181State *s)
@@ -172,7 +164,7 @@ static uint32_t pl181_fifo_pop(PL181State *s)
 value = s->fifo[s->fifo_pos];
 s->fifo_len--;
 s->fifo_pos = (s->fifo_pos + 1) & (PL181_FIFO_LEN - 1);
-DPRINTF("FIFO pop %08x\n", (int)value);
+trace_pl181_fifo_pop(value);
 return value;
 }
 
@@ -184,7 +176,7 @@ static void pl181_do_command(PL181State *s)
 
 request.cmd = s->cmd & PL181_CMD_INDEX;
 request.arg = s->cmdarg;
-DPRINTF("Command %d %08x\n", request.cmd, request.arg);
+trace_pl181_command_send(request.cmd, request.arg);
 rlen = sdbus_do_command(&s->sdbus, &request, response);
 if (rlen < 0)
 goto error;
@@ -201,16 +193,16 @@ static void pl181_do_command(PL181State *s)
 s->response[2] = ldl_be_p(&response[8]);
 s->response[3] = ldl_be_p(&response[12]) & ~1;
 }
-DPRINTF("Response received\n");
+trace_pl181_command_response_pending();
 s->status |= PL181_STATUS_CMDRESPEND;
 } else {
-DPRINTF("Command sent\n");
+trace_pl181_command_sent();
 s->status |= PL181_STATUS_CMDSENT;
 }
 return;
 
 error:
-DPRINTF("Timeout\n");
+trace_pl181_command_timeout();
 s->status |= PL181_STATUS_CMDTIMEOUT;
 }
 
@@ -262,11 +254,11 @@ static void pl181_fifo_run(PL181State *s)
 s->status |= PL181_STATUS_DATAEND;
 /* HACK: */
 s->status |= PL181_STATUS_DATABLOCKEND;
-DPRINTF("Transfer Complete\n");
+trace_pl181_fifo_transfer_complete();
 }
 if (s->datacnt == 0 && s->fifo_len == 0) {
 s->datactrl &= ~PL181_DATA_ENABLE;
-DPRINTF("Data engine idle\n");
+trace_pl181_data_engine_idle();
 } else {
 /* Update FIFO bits.  */
 bits = PL181_STATUS_TXACTIVE | PL181_STATUS_RXACTIVE;
diff --git a/hw/sd/trace-events b/hw/sd/trace-events
index 5f09d32eb2..a87d7355fb 100644
--- a/hw/sd/trace-events
+++ b/hw/sd/trace-events
@@ -62,3 +62,13 @@ milkymist_memcard_memory_write(uint32_t addr, uint32_t 
value) "addr 0x%08x value
 # pxa2xx_mmci.c
 pxa2xx_mmci_read(uint8_t size, uint32_t addr, uint32_t value) "size %d addr 
0x%02x value 0x%08x"
 pxa2xx_mmci_write(uint8_t size, uint32_t addr, uint32_t value) "size %d addr 
0x%02x value 0x%08x"
+
+# pl181.c
+pl181_command_send(uint8_t cmd, uint32_t arg) "sending CMD%02d arg 0x%08" 
PRIx32
+pl181_command_sent(void) "command sent"
+pl181_command_response_pending(void) "response received"
+pl181_command_timeout(void) "command timeouted"
+pl181_fifo_push(uint32_t data) "FIFO push 0x%08" PRIx32
+pl181_fifo_pop(uint32_t data) "FIFO pop 0x%08" PRIx32
+pl181_fifo_transfer_complete(void) "FIFO transfer complete"
+pl181_data_engine_idle(void) "data engine idle"
-- 
2.21.3




[PATCH v4 05/10] hw/sd/pl181: Use named GPIOs

2020-07-05 Thread Philippe Mathieu-Daudé
To make the code easier to manage/review/use, rename the
cardstatus[0] variable as 'card_readonly' and name the GPIO
"card-read-only".
Similarly with cardstatus[1], renamed as 'card_inserted' and
name its GPIO "card-inserted".

Adapt the users accordingly by using the qdev_init_gpio_out_named()
function.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/arm/integratorcp.c | 4 ++--
 hw/arm/realview.c | 4 ++--
 hw/arm/vexpress.c | 4 ++--
 hw/sd/pl181.c | 8 +---
 4 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
index b11a846355..2595e4d052 100644
--- a/hw/arm/integratorcp.c
+++ b/hw/arm/integratorcp.c
@@ -645,9 +645,9 @@ static void integratorcp_init(MachineState *machine)
 sysbus_create_simple(TYPE_INTEGRATOR_DEBUG, 0x1a00, 0);
 
 dev = sysbus_create_varargs("pl181", 0x1c00, pic[23], pic[24], NULL);
-qdev_connect_gpio_out(dev, 0,
+qdev_connect_gpio_out_named(dev, "card-read-only", 0,
   qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_WPROT, 0));
-qdev_connect_gpio_out(dev, 1,
+qdev_connect_gpio_out_named(dev, "card-inserted", 0,
   qdev_get_gpio_in_named(icp, ICP_GPIO_MMC_CARDIN, 0));
 sysbus_create_varargs("pl041", 0x1d00, pic[25], NULL);
 
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
index b6c0a1adb9..8dc5f77139 100644
--- a/hw/arm/realview.c
+++ b/hw/arm/realview.c
@@ -234,8 +234,8 @@ static void realview_init(MachineState *machine,
 mmc_irq[1] = qemu_irq_split(
 qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN),
 qemu_irq_invert(qdev_get_gpio_in(gpio2, 0)));
-qdev_connect_gpio_out(dev, 0, mmc_irq[0]);
-qdev_connect_gpio_out(dev, 1, mmc_irq[1]);
+qdev_connect_gpio_out_named(dev, "card-read-only", 0, mmc_irq[0]);
+qdev_connect_gpio_out_named(dev, "card-inserted", 0, mmc_irq[1]);
 
 sysbus_create_simple("pl031", 0x10017000, pic[10]);
 
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index 5bf9cff8a8..16629d6599 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -624,9 +624,9 @@ static void vexpress_common_init(MachineState *machine)
 
 dev = sysbus_create_varargs("pl181", map[VE_MMCI], pic[9], pic[10], NULL);
 /* Wire up MMC card detect and read-only signals */
-qdev_connect_gpio_out(dev, 0,
+qdev_connect_gpio_out_named(dev, "card-read-only", 0,
   qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT));
-qdev_connect_gpio_out(dev, 1,
+qdev_connect_gpio_out_named(dev, "card-inserted", 0,
   qdev_get_gpio_in(sysctl, 
ARM_SYSCTL_GPIO_MMC_CARDIN));
 
 sysbus_create_simple("pl050_keyboard", map[VE_KMI0], pic[12]);
diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
index 86219c851d..ab4cd733a4 100644
--- a/hw/sd/pl181.c
+++ b/hw/sd/pl181.c
@@ -60,7 +60,8 @@ typedef struct PL181State {
 uint32_t fifo[PL181_FIFO_LEN]; /* TODO use Fifo32 */
 qemu_irq irq[2];
 /* GPIO outputs for 'card is readonly' and 'card inserted' */
-qemu_irq cardstatus[2];
+qemu_irq card_readonly;
+qemu_irq card_inserted;
 } PL181State;
 
 static const VMStateDescription vmstate_pl181 = {
@@ -479,7 +480,7 @@ static void pl181_reset(DeviceState *d)
 s->mask[1] = 0;
 
 /* We can assume our GPIO outputs have been wired up now */
-sd_set_cb(s->card, s->cardstatus[0], s->cardstatus[1]);
+sd_set_cb(s->card, s->card_readonly, s->card_inserted);
 /* Since we're still using the legacy SD API the card is not plugged
  * into any bus, and we must reset it manually.
  */
@@ -496,7 +497,8 @@ static void pl181_init(Object *obj)
 sysbus_init_mmio(sbd, &s->iomem);
 sysbus_init_irq(sbd, &s->irq[0]);
 sysbus_init_irq(sbd, &s->irq[1]);
-qdev_init_gpio_out(dev, s->cardstatus, 2);
+qdev_init_gpio_out_named(dev, &s->card_readonly, "card-read-only", 1);
+qdev_init_gpio_out_named(dev, &s->card_inserted, "card-inserted", 1);
 }
 
 static void pl181_realize(DeviceState *dev, Error **errp)
-- 
2.21.3




[PATCH v4 04/10] hw/arm/versatilepb: Comment to remember some IRQs lines are left unwired

2020-07-05 Thread Philippe Mathieu-Daudé
The 'card is readonly' and 'card inserted' IRQs are not wired.
Add a comment in case someone know where to wire them.

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/arm/versatilepb.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
index e596b8170f..45a13ae2b9 100644
--- a/hw/arm/versatilepb.c
+++ b/hw/arm/versatilepb.c
@@ -310,7 +310,9 @@ static void versatile_init(MachineState *machine, int 
board_id)
 qdev_connect_gpio_out(sysctl, 0, qdev_get_gpio_in(dev, 0));
 
 sysbus_create_varargs("pl181", 0x10005000, sic[22], sic[1], NULL);
+/* FIXME wire 'card is readonly' and 'card inserted' IRQs? */
 sysbus_create_varargs("pl181", 0x1000b000, sic[23], sic[2], NULL);
+/* FIXME wire 'card is readonly' and 'card inserted' IRQs? */
 
 /* Add PL031 Real Time Clock. */
 sysbus_create_simple("pl031", 0x101e8000, pic[10]);
-- 
2.21.3




[PATCH v4 01/10] hw/sd/pl181: Replace fprintf(stderr, "*\n") with error_report()

2020-07-05 Thread Philippe Mathieu-Daudé
From: Alistair Francis 

Replace a large number of the fprintf(stderr, "*\n" calls with
error_report(). The functions were renamed with these commands and then
compiler issues where manually fixed.

find ./* -type f -exec sed -i \
'N;N;N;N;N;N;N;N;N;N;N;N; {s|fprintf(stderr, 
"\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N;N;N;N;N;N;N;N; {s|fprintf(stderr, 
"\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N;N;N;N;N;N; {s|fprintf(stderr, 
"\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N;N;N;N;N; {s|fprintf(stderr, 
"\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N;N;N;N; {s|fprintf(stderr, 
"\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N;N;N; {s|fprintf(stderr, 
"\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N;N; {s|fprintf(stderr, 
"\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' 
\
{} +
find ./* -type f -exec sed -i \
'N;N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N;N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +
find ./* -type f -exec sed -i \
'N; {s|fprintf(stderr, "\(.*\)\\n"\(.*\));|error_report("\1"\2);|Ig}' \
{} +

Some lines where then manually tweaked to pass checkpatch.

Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Alistair Francis 
Message-Id: 
<488ba8d4c562ea44119de8ea0f385a898bd8fa1e.1513790495.git.alistair.fran...@xilinx.com>
Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/pl181.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
index 2b3776a6a0..649386ec3d 100644
--- a/hw/sd/pl181.c
+++ b/hw/sd/pl181.c
@@ -15,6 +15,7 @@
 #include "hw/sd/sd.h"
 #include "qemu/log.h"
 #include "qemu/module.h"
+#include "qemu/error-report.h"
 #include "qapi/error.h"
 
 //#define DEBUG_PL181 1
@@ -148,7 +149,7 @@ static void pl181_fifo_push(PL181State *s, uint32_t value)
 int n;
 
 if (s->fifo_len == PL181_FIFO_LEN) {
-fprintf(stderr, "pl181: FIFO overflow\n");
+error_report("%s: FIFO overflow", __func__);
 return;
 }
 n = (s->fifo_pos + s->fifo_len) & (PL181_FIFO_LEN - 1);
@@ -162,7 +163,7 @@ static uint32_t pl181_fifo_pop(PL181State *s)
 uint32_t value;
 
 if (s->fifo_len == 0) {
-fprintf(stderr, "pl181: FIFO underflow\n");
+error_report("%s: FIFO underflow", __func__);
 return 0;
 }
 value = s->fifo[s->fifo_pos];
-- 
2.21.3




[PATCH v4 03/10] hw/sd/pl181: Add TODO to use Fifo32 API

2020-07-05 Thread Philippe Mathieu-Daudé
Add TODO to use Fifo32 API from "qemu/fifo32.h".

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/pl181.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
index 3fc2cdd71a..86219c851d 100644
--- a/hw/sd/pl181.c
+++ b/hw/sd/pl181.c
@@ -57,7 +57,7 @@ typedef struct PL181State {
http://www.arm.linux.org.uk/developer/patches/viewpatch.php?id=4446/1
  */
 int32_t linux_hack;
-uint32_t fifo[PL181_FIFO_LEN];
+uint32_t fifo[PL181_FIFO_LEN]; /* TODO use Fifo32 */
 qemu_irq irq[2];
 /* GPIO outputs for 'card is readonly' and 'card inserted' */
 qemu_irq cardstatus[2];
-- 
2.21.3




[PATCH v4 00/10] hw/sd: convert legacy SDHCI devices to the SDBus API

2020-07-05 Thread Philippe Mathieu-Daudé
Hi,

Since v3:
- rebased (was from Feb 2018)
- use named GPIOs
- addressed Peter review comment (adding TYPE_PL181_BUS object)
- convert DPRINF to trace events

Since v2:
- pl181: remove legacy sd_set_cb() (Peter)

Since v1:
- rebased on /master (Peter sdcard reset() patches)
- fix milkymist-mmc from previous seris using instance_init (Michael Walle)

This series convert 3 devices using the legacy SDCard API to the SDBus API:
- milkymist-mmc
- pl181
- ssi-sd

Then move the legacy API to a separate header "sdcard_legacy.h".

Now the OMAP MMC is the last device using the legacy API, but need to get
QOM'ified first.

Regards,

Phil.

v3: https://www.mail-archive.com/qemu-devel@nongnu.org/msg514645.html

Alistair Francis (1):
  hw/sd/pl181: Replace fprintf(stderr, "*\n") with error_report()

Philippe Mathieu-Daudé (9):
  hw/sd/pl181: Rename pl181_send_command() as pl181_do_command()
  hw/sd/pl181: Add TODO to use Fifo32 API
  hw/arm/versatilepb: Comment to remember some IRQs lines are left
unwired
  hw/sd/pl181: Use named GPIOs
  hw/sd/pl181: Expose a SDBus and connect the SDCard to it
  hw/sd/pl181: Do not create SD card within the SDHCI controller
  hw/sd/pl181: Replace disabled fprintf()s by trace events
  hw/sd/sdcard: make sd_data_ready() static
  hw/sd: move sdcard legacy API to 'hw/sd/sdcard_legacy.h'

 include/hw/sd/sd.h|  17 --
 include/hw/sd/sdcard_legacy.h |  50 +++
 hw/arm/integratorcp.c |  17 +-
 hw/arm/realview.c |  16 -
 hw/arm/versatilepb.c  |  28 -
 hw/arm/vexpress.c |  15 -
 hw/sd/omap_mmc.c  |   2 +-
 hw/sd/pl181.c | 111 +++---
 hw/sd/sd.c|   3 +-
 hw/sd/trace-events|  10 +++
 10 files changed, 193 insertions(+), 76 deletions(-)
 create mode 100644 include/hw/sd/sdcard_legacy.h

-- 
2.21.3




[PATCH v4 06/10] hw/sd/pl181: Expose a SDBus and connect the SDCard to it

2020-07-05 Thread Philippe Mathieu-Daudé
Convert the controller to the SDBus API:
- add the a TYPE_PL181_BUS object of type TYPE_SD_BUS,
- adapt the SDBusClass set_inserted/set_readonly handlers
- create the bus in the PL181 controller
- switch legacy sd_*() API to the sdbus_*() API.

Signed-off-by: Philippe Mathieu-Daudé 
---
Since v3:
Addressed Peter comment, adding TYPE_PL181_BUS:
https://www.mail-archive.com/qemu-devel@nongnu.org/msg515866.html
---
 hw/sd/pl181.c | 67 +++
 1 file changed, 51 insertions(+), 16 deletions(-)

diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
index ab4cd733a4..f6de06ece8 100644
--- a/hw/sd/pl181.c
+++ b/hw/sd/pl181.c
@@ -17,6 +17,7 @@
 #include "qemu/module.h"
 #include "qemu/error-report.h"
 #include "qapi/error.h"
+#include "hw/qdev-properties.h"
 
 //#define DEBUG_PL181 1
 
@@ -32,11 +33,13 @@ do { printf("pl181: " fmt , ## __VA_ARGS__); } while (0)
 #define TYPE_PL181 "pl181"
 #define PL181(obj) OBJECT_CHECK(PL181State, (obj), TYPE_PL181)
 
+#define TYPE_PL181_BUS "pl181-bus"
+
 typedef struct PL181State {
 SysBusDevice parent_obj;
 
 MemoryRegion iomem;
-SDState *card;
+SDBus sdbus;
 uint32_t clock;
 uint32_t power;
 uint32_t cmdarg;
@@ -183,7 +186,7 @@ static void pl181_do_command(PL181State *s)
 request.cmd = s->cmd & PL181_CMD_INDEX;
 request.arg = s->cmdarg;
 DPRINTF("Command %d %08x\n", request.cmd, request.arg);
-rlen = sd_do_command(s->card, &request, response);
+rlen = sdbus_do_command(&s->sdbus, &request, response);
 if (rlen < 0)
 goto error;
 if (s->cmd & PL181_CMD_RESPONSE) {
@@ -224,12 +227,12 @@ static void pl181_fifo_run(PL181State *s)
 int is_read;
 
 is_read = (s->datactrl & PL181_DATA_DIRECTION) != 0;
-if (s->datacnt != 0 && (!is_read || sd_data_ready(s->card))
+if (s->datacnt != 0 && (!is_read || sdbus_data_ready(&s->sdbus))
 && !s->linux_hack) {
 if (is_read) {
 n = 0;
 while (s->datacnt && s->fifo_len < PL181_FIFO_LEN) {
-value |= (uint32_t)sd_read_data(s->card) << (n * 8);
+value |= (uint32_t)sdbus_read_data(&s->sdbus) << (n * 8);
 s->datacnt--;
 n++;
 if (n == 4) {
@@ -250,7 +253,7 @@ static void pl181_fifo_run(PL181State *s)
 }
 n--;
 s->datacnt--;
-sd_write_data(s->card, value & 0xff);
+sdbus_write_data(&s->sdbus, value & 0xff);
 value >>= 8;
 }
 }
@@ -456,6 +459,20 @@ static const MemoryRegionOps pl181_ops = {
 .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
+static void pl181_set_readonly(DeviceState *dev, bool level)
+{
+PL181State *s = (PL181State *)dev;
+
+qemu_set_irq(s->card_readonly, level);
+}
+
+static void pl181_set_inserted(DeviceState *dev, bool level)
+{
+PL181State *s = (PL181State *)dev;
+
+qemu_set_irq(s->card_inserted, level);
+}
+
 static void pl181_reset(DeviceState *d)
 {
 PL181State *s = PL181(d);
@@ -479,12 +496,9 @@ static void pl181_reset(DeviceState *d)
 s->mask[0] = 0;
 s->mask[1] = 0;
 
-/* We can assume our GPIO outputs have been wired up now */
-sd_set_cb(s->card, s->card_readonly, s->card_inserted);
-/* Since we're still using the legacy SD API the card is not plugged
- * into any bus, and we must reset it manually.
- */
-device_legacy_reset(DEVICE(s->card));
+/* Reset other state based on current card insertion/readonly status */
+pl181_set_inserted(DEVICE(s), sdbus_get_inserted(&s->sdbus));
+pl181_set_readonly(DEVICE(s), sdbus_get_readonly(&s->sdbus));
 }
 
 static void pl181_init(Object *obj)
@@ -499,19 +513,24 @@ static void pl181_init(Object *obj)
 sysbus_init_irq(sbd, &s->irq[1]);
 qdev_init_gpio_out_named(dev, &s->card_readonly, "card-read-only", 1);
 qdev_init_gpio_out_named(dev, &s->card_inserted, "card-inserted", 1);
+
+qbus_create_inplace(&s->sdbus, sizeof(s->sdbus),
+TYPE_PL181_BUS, dev, "sd-bus");
 }
 
 static void pl181_realize(DeviceState *dev, Error **errp)
 {
-PL181State *s = PL181(dev);
+DeviceState *card;
 DriveInfo *dinfo;
 
 /* FIXME use a qdev drive property instead of drive_get_next() */
+card = qdev_new(TYPE_SD_CARD);
 dinfo = drive_get_next(IF_SD);
-s->card = sd_init(dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, false);
-if (s->card == NULL) {
-error_setg(errp, "sd_init failed");
-}
+qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo),
+&error_fatal);
+qdev_realize_and_unref(card,
+   qdev_get_child_bus(dev, "sd-bus"),
+   &error_fatal);
 }
 
 static void pl181_class_init(ObjectClass *klass, void *data)
@@ -533,9 +552,25 @@ static const TypeInfo pl181_info = {
 .class_init= pl181_class_init,
 };
 
+static void pl181_bus_class_init

[PATCH v4 02/10] hw/sd/pl181: Rename pl181_send_command() as pl181_do_command()

2020-07-05 Thread Philippe Mathieu-Daudé
pl181_send_command() do a bus transaction (send or receive),
rename it as pl181_do_command().

Signed-off-by: Philippe Mathieu-Daudé 
---
 hw/sd/pl181.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c
index 649386ec3d..3fc2cdd71a 100644
--- a/hw/sd/pl181.c
+++ b/hw/sd/pl181.c
@@ -173,7 +173,7 @@ static uint32_t pl181_fifo_pop(PL181State *s)
 return value;
 }
 
-static void pl181_send_command(PL181State *s)
+static void pl181_do_command(PL181State *s)
 {
 SDRequest request;
 uint8_t response[16];
@@ -402,7 +402,7 @@ static void pl181_write(void *opaque, hwaddr offset,
 qemu_log_mask(LOG_UNIMP,
   "pl181: Pending commands not implemented\n");
 } else {
-pl181_send_command(s);
+pl181_do_command(s);
 pl181_fifo_run(s);
 }
 /* The command has completed one way or the other.  */
-- 
2.21.3




Re: [PATCH 22/26] hw/usb/usb-hcd: Use OHCI type definitions

2020-07-05 Thread Niek Linnenbank
On Sat, Jul 4, 2020, 16:50 Philippe Mathieu-Daudé  wrote:

> Various machine/board/soc models create OHCI device instances
> with the generic QDEV API, and don't need to access USB internals.
>
> Simplify header inclusions by moving the QOM type names into a
> simple header, with no need to include other "hw/usb" headers.
>
> Suggested-by: BALATON Zoltan 
> Signed-off-by: Philippe Mathieu-Daudé 
>
Reviewed-by: Niek Linnenbank 

---
>  hw/usb/hcd-ohci.h|  2 +-
>  include/hw/usb/usb-hcd.h | 16 
>  hw/arm/allwinner-a10.c   |  2 +-
>  hw/arm/allwinner-h3.c|  9 +
>  hw/arm/pxa2xx.c  |  3 ++-
>  hw/arm/realview.c|  3 ++-
>  hw/arm/versatilepb.c |  3 ++-
>  hw/display/sm501.c   |  3 ++-
>  hw/ppc/mac_newworld.c|  3 ++-
>  hw/ppc/mac_oldworld.c|  3 ++-
>  hw/ppc/sam460ex.c|  3 ++-
>  hw/ppc/spapr.c   |  3 ++-
>  hw/usb/hcd-ohci-pci.c|  2 +-
>  13 files changed, 40 insertions(+), 15 deletions(-)
>  create mode 100644 include/hw/usb/usb-hcd.h
>
> diff --git a/hw/usb/hcd-ohci.h b/hw/usb/hcd-ohci.h
> index 771927ea17..6949cf0dab 100644
> --- a/hw/usb/hcd-ohci.h
> +++ b/hw/usb/hcd-ohci.h
> @@ -21,6 +21,7 @@
>  #ifndef HCD_OHCI_H
>  #define HCD_OHCI_H
>
> +#include "hw/usb/usb-hcd.h"
>  #include "sysemu/dma.h"
>  #include "usb-internal.h"
>
> @@ -91,7 +92,6 @@ typedef struct OHCIState {
>  void (*ohci_die)(struct OHCIState *ohci);
>  } OHCIState;
>
> -#define TYPE_SYSBUS_OHCI "sysbus-ohci"
>  #define SYSBUS_OHCI(obj) OBJECT_CHECK(OHCISysBusState, (obj),
> TYPE_SYSBUS_OHCI)
>
>  typedef struct {
> diff --git a/include/hw/usb/usb-hcd.h b/include/hw/usb/usb-hcd.h
> new file mode 100644
> index 00..21fdfaf22d
> --- /dev/null
> +++ b/include/hw/usb/usb-hcd.h
> @@ -0,0 +1,16 @@
> +/*
> + * QEMU USB HCD types
> + *
> + * Copyright (c) 2020  Philippe Mathieu-Daudé 
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#ifndef HW_USB_HCD_TYPES_H
> +#define HW_USB_HCD_TYPES_H
> +
> +/* OHCI */
> +#define TYPE_SYSBUS_OHCI"sysbus-ohci"
> +#define TYPE_PCI_OHCI   "pci-ohci"
> +
> +#endif
> diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
> index 52e0d83760..53c24ff602 100644
> --- a/hw/arm/allwinner-a10.c
> +++ b/hw/arm/allwinner-a10.c
> @@ -25,7 +25,7 @@
>  #include "hw/misc/unimp.h"
>  #include "sysemu/sysemu.h"
>  #include "hw/boards.h"
> -#include "hw/usb/hcd-ohci.h"
> +#include "hw/usb/usb-hcd.h"
>
>  #define AW_A10_MMC0_BASE0x01c0f000
>  #define AW_A10_PIC_REG_BASE 0x01c20400
> diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
> index 8e09468e86..d1d90ffa79 100644
> --- a/hw/arm/allwinner-h3.c
> +++ b/hw/arm/allwinner-h3.c
> @@ -28,6 +28,7 @@
>  #include "hw/sysbus.h"
>  #include "hw/char/serial.h"
>  #include "hw/misc/unimp.h"
> +#include "hw/usb/usb-hcd.h"
>  #include "hw/usb/hcd-ehci.h"
>  #include "hw/loader.h"
>  #include "sysemu/sysemu.h"
> @@ -381,16 +382,16 @@ static void allwinner_h3_realize(DeviceState *dev,
> Error **errp)
>   qdev_get_gpio_in(DEVICE(&s->gic),
>AW_H3_GIC_SPI_EHCI3));
>
> -sysbus_create_simple("sysbus-ohci", s->memmap[AW_H3_OHCI0],
> +sysbus_create_simple(TYPE_SYSBUS_OHCI, s->memmap[AW_H3_OHCI0],
>   qdev_get_gpio_in(DEVICE(&s->gic),
>AW_H3_GIC_SPI_OHCI0));
> -sysbus_create_simple("sysbus-ohci", s->memmap[AW_H3_OHCI1],
> +sysbus_create_simple(TYPE_SYSBUS_OHCI, s->memmap[AW_H3_OHCI1],
>   qdev_get_gpio_in(DEVICE(&s->gic),
>AW_H3_GIC_SPI_OHCI1));
> -sysbus_create_simple("sysbus-ohci", s->memmap[AW_H3_OHCI2],
> +sysbus_create_simple(TYPE_SYSBUS_OHCI, s->memmap[AW_H3_OHCI2],
>   qdev_get_gpio_in(DEVICE(&s->gic),
>AW_H3_GIC_SPI_OHCI2));
> -sysbus_create_simple("sysbus-ohci", s->memmap[AW_H3_OHCI3],
> +sysbus_create_simple(TYPE_SYSBUS_OHCI, s->memmap[AW_H3_OHCI3],
>   qdev_get_gpio_in(DEVICE(&s->gic),
>AW_H3_GIC_SPI_OHCI3));
>
> diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
> index f104a33463..27196170f5 100644
> --- a/hw/arm/pxa2xx.c
> +++ b/hw/arm/pxa2xx.c
> @@ -18,6 +18,7 @@
>  #include "hw/arm/pxa.h"
>  #include "sysemu/sysemu.h"
>  #include "hw/char/serial.h"
> +#include "hw/usb/usb-hcd.h"
>  #include "hw/i2c/i2c.h"
>  #include "hw/irq.h"
>  #include "hw/qdev-properties.h"
> @@ -2196,7 +2197,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
>  s->ssp[i] = (SSIBus *)qdev_get_child_bus(dev, "ssi");
>  }
>
> -sysbus_create_simple("sysbus-ohci", 0x4c00,
> +sysbus_create_simple(TYPE_SYSBUS_OHCI, 0x4c00,
>   qdev_get_gpio_in(s->pic, PXA2XX_PIC_USBH1));
>
>  s->pcmcia[0] = pxa2xx_pcmcia_init(address_space, 0x20

[Bug 1886343] [NEW] configure has non-posix bash syntax

2020-07-05 Thread Wilson-q
Public bug reported:

which gives an error when run on a system that uses dash for /bin/sh.

The problem is at line 6464 which has
if test "$have_keyring" == "yes"
the double equal sign is non-posix bash syntax that isn't accepted by posix 
shells like dash.  This was added 2020-05-25 according to git blame so looks 
like a recent problem.

On an Ubuntu 20.04 system with top of tree sources I get
gondor:2027$ ../qemu/configure --prefix=/home/wilson/FOSS/qemu/install-qemu-tmp 
--target-list=riscv64-linux-user,riscv64-softmmu,riscv32-linux-user,riscv32-softmmu
../qemu/configure: 6464: test: yes: unexpected operator
...

configure completes OK, so this is a minor problem.  It is just one
configure test that is failing to work properly.

** Affects: qemu
 Importance: Undecided
 Status: New

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1886343

Title:
  configure has non-posix bash syntax

Status in QEMU:
  New

Bug description:
  which gives an error when run on a system that uses dash for /bin/sh.

  The problem is at line 6464 which has
  if test "$have_keyring" == "yes"
  the double equal sign is non-posix bash syntax that isn't accepted by posix 
shells like dash.  This was added 2020-05-25 according to git blame so looks 
like a recent problem.

  On an Ubuntu 20.04 system with top of tree sources I get
  gondor:2027$ ../qemu/configure 
--prefix=/home/wilson/FOSS/qemu/install-qemu-tmp 
--target-list=riscv64-linux-user,riscv64-softmmu,riscv32-linux-user,riscv32-softmmu
  ../qemu/configure: 6464: test: yes: unexpected operator
  ...

  configure completes OK, so this is a minor problem.  It is just one
  configure test that is failing to work properly.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1886343/+subscriptions



Re: [PATCH rc6 00/30] target/avr merger

2020-07-05 Thread Peter Maydell
On Sun, 5 Jul 2020 at 19:31, Thomas Huth  wrote:
>
> Am Sun, 5 Jul 2020 07:29:06 -0700 (PDT)
> schrieb no-re...@patchew.org:
>
> > Patchew URL:
> > https://patchew.org/QEMU/20200705140315.260514-1-h...@tuxfamily.org/
> [...]
> > === OUTPUT BEGIN ===
> > 1/30 Checking commit b5e3116a3591 (target/avr: Add basic parameters
> > of the new platform) WARNING: added, moved or deleted file(s), does
> > MAINTAINERS need updating? #42:
> > new file mode 100644
>
> These warnings are really annoying. The target/avr folder is added to
> MAINTAINERS in the first patch, so they should not occur...?

checkpatch's logic for this is extremely simplistic: it will
warn if:
 * the patch adds, moves or deletes a file
 * the patch does not itself modify MAINTAINERS

This naturally leads to a ton of false-positives.

thanks
-- PMM



Re: [PATCH rc6 00/30] target/avr merger

2020-07-05 Thread Thomas Huth
Am Sun, 5 Jul 2020 07:29:06 -0700 (PDT)
schrieb no-re...@patchew.org:

> Patchew URL:
> https://patchew.org/QEMU/20200705140315.260514-1-h...@tuxfamily.org/
[...]
> === OUTPUT BEGIN ===
> 1/30 Checking commit b5e3116a3591 (target/avr: Add basic parameters
> of the new platform) WARNING: added, moved or deleted file(s), does
> MAINTAINERS need updating? #42: 
> new file mode 100644

These warnings are really annoying. The target/avr folder is added to
MAINTAINERS in the first patch, so they should not occur...?

[...]
> ERROR: trailing whitespace
> #39: FILE: docs/system/target-avr.rst:20:
> + - Continuous non interrupted execution: $

Ok, that's a real one. I just already fixed it in my local branch.

 Thomas



Re: [PULL 05/34] virtio-iommu: Implement RESV_MEM probe request

2020-07-05 Thread Peter Maydell
On Fri, 3 Jul 2020 at 17:54, Peter Maydell  wrote:
>
> From: Eric Auger 
>
> This patch implements the PROBE request. At the moment,
> only THE RESV_MEM property is handled. The first goal is
> to report iommu wide reserved regions such as the MSI regions
> set by the machine code. On x86 this will be the IOAPIC MSI
> region, [0xFEE0 - 0xFEEF], on ARM this may be the ITS
> doorbell.

> @@ -452,6 +524,17 @@ static void virtio_iommu_handle_command(VirtIODevice 
> *vdev, VirtQueue *vq)
>  case VIRTIO_IOMMU_T_UNMAP:
>  tail.status = virtio_iommu_handle_unmap(s, iov, iov_cnt);
>  break;
> +case VIRTIO_IOMMU_T_PROBE:
> +{
> +struct virtio_iommu_req_tail *ptail;
> +
> +output_size = s->config.probe_size + sizeof(tail);
> +buf = g_malloc0(output_size);
> +
> +ptail = (struct virtio_iommu_req_tail *)
> +(buf + s->config.probe_size);
> +ptail->status = virtio_iommu_handle_probe(s, iov, iov_cnt, buf);
> +}
>  default:
>  tail.status = VIRTIO_IOMMU_S_UNSUPP;
>  }

Hi Eric -- Coverity points out (CID 1430180) that this new case
has neither a 'break' nor a /* fallthrough */ comment. Which is correct?

thanks
-- PMM



Re: [PULL v2 12/64] target/riscv: add vector amo operations

2020-07-05 Thread Peter Maydell
On Thu, 2 Jul 2020 at 17:33, Alistair Francis  wrote:
>
> From: LIU Zhiwei 
>
> Vector AMOs operate as if aq and rl bits were zero on each element
> with regard to ordering relative to other instructions in the same hart.
> Vector AMOs provide no ordering guarantee between element operations
> in the same vector AMO instruction

Hi; Coverity thinks (probably wrongly) that there might be an array
overflow here:

> +static bool amo_op(DisasContext *s, arg_rwdvm *a, uint8_t seq)
> +{
> +uint32_t data = 0;
> +gen_helper_amo *fn;
> +static gen_helper_amo *const fnsw[9] = {

This is a 9-element array...

> +/* no atomic operation */
> +gen_helper_vamoswapw_v_w,
> +gen_helper_vamoaddw_v_w,
> +gen_helper_vamoxorw_v_w,
> +gen_helper_vamoandw_v_w,
> +gen_helper_vamoorw_v_w,
> +gen_helper_vamominw_v_w,
> +gen_helper_vamomaxw_v_w,
> +gen_helper_vamominuw_v_w,
> +gen_helper_vamomaxuw_v_w
> +};

> +if (tb_cflags(s->base.tb) & CF_PARALLEL) {
> +gen_helper_exit_atomic(cpu_env);
> +s->base.is_jmp = DISAS_NORETURN;
> +return true;
> +} else {
> +if (s->sew == 3) {
> +#ifdef TARGET_RISCV64
> +fn = fnsd[seq];
> +#else
> +/* Check done in amo_check(). */
> +g_assert_not_reached();
> +#endif
> +} else {
> +fn = fnsw[seq];

...which we here index via 'seq'...


> +#ifdef TARGET_RISCV64
> +GEN_VEXT_TRANS(vamoswapd_v, 9, rwdvm, amo_op, amo_check)
> +GEN_VEXT_TRANS(vamoaddd_v, 10, rwdvm, amo_op, amo_check)
> +GEN_VEXT_TRANS(vamoxord_v, 11, rwdvm, amo_op, amo_check)
> +GEN_VEXT_TRANS(vamoandd_v, 12, rwdvm, amo_op, amo_check)
> +GEN_VEXT_TRANS(vamoord_v, 13, rwdvm, amo_op, amo_check)
> +GEN_VEXT_TRANS(vamomind_v, 14, rwdvm, amo_op, amo_check)
> +GEN_VEXT_TRANS(vamomaxd_v, 15, rwdvm, amo_op, amo_check)
> +GEN_VEXT_TRANS(vamominud_v, 16, rwdvm, amo_op, amo_check)
> +GEN_VEXT_TRANS(vamomaxud_v, 17, rwdvm, amo_op, amo_check)
> +#endif

...which in the calls that these macros expand out to can
be 9 or greater.

If it's in fact impossible to get into that code path
with a value of seq that's larger than the array, it
would help Coverity if we asserted so, maybe
   assert(seq < ARRAY_SIZE(fnsw));

This is CID 1430177, 1430178, 1430179, 1430180, 1430181,
1430182, 1430183, 1430184, 1430185, 14305186.

thanks
-- PMM



Re: [PATCH 3/3] target/nios2: Use gen_io_start around wrctl instruction

2020-07-05 Thread Max Filippov
On Sun, Jul 5, 2020 at 10:09 AM Peter Maydell  wrote:
> On Thu, 2 Jul 2020 at 19:53, Richard Henderson
>  wrote:
> > This isn't right.  Not so much the gen_io_start portion, but the entire
> > existence of helper_check_interrupt.
>
> I agree that it looks bogus (xtensa has a similar helper as well, 
> incidentally),

I think there was a reason for it. According to Richard

> The correct way to acknowledge interrupts after changing an interrupt mask bit
> is to exit the TB back to the cpu main loop.

But if I do this change for Xtensa I get a bunch of test_interrupt failures
that indicate that the interrupt that should have been taken wasn't taken.
FTR here's the change that I tested, did I miss something?

diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
index fdf47642e6f1..85e8d65f169d 100644
--- a/target/xtensa/translate.c
+++ b/target/xtensa/translate.c
@@ -631,18 +631,10 @@ static int gen_postprocess(DisasContext *dc, int slot)
 {
 uint32_t op_flags = dc->op_flags;

-#ifndef CONFIG_USER_ONLY
-if (op_flags & XTENSA_OP_CHECK_INTERRUPTS) {
-if (tb_cflags(dc->base.tb) & CF_USE_ICOUNT) {
-gen_io_start();
-}
-gen_helper_check_interrupts(cpu_env);
-}
-#endif
 if (op_flags & XTENSA_OP_SYNC_REGISTER_WINDOW) {
 gen_helper_sync_windowbase(cpu_env);
 }
-if (op_flags & XTENSA_OP_EXIT_TB_M1) {
+if (op_flags & (XTENSA_OP_EXIT_TB_M1 | XTENSA_OP_CHECK_INTERRUPTS)) {
 slot = -1;
 }
 return slot;
@@ -1175,7 +1167,7 @@ static void disas_xtensa_insn(CPUXtensaState
*env, DisasContext *dc)
 if (dc->base.is_jmp == DISAS_NEXT) {
 gen_postprocess(dc, 0);
 dc->op_flags = 0;
-if (op_flags & XTENSA_OP_EXIT_TB_M1) {
+if (op_flags & (XTENSA_OP_EXIT_TB_M1 | XTENSA_OP_CHECK_INTERRUPTS)) {
 /* Change in mmu index, memory mapping or tb->flags; exit tb */
 gen_jumpi_check_loop_end(dc, -1);
 } else if (op_flags & XTENSA_OP_EXIT_TB_0) {


-- 
Thanks.
-- Max



Re: [PATCH v2] apic: Report current_count via 'info lapic'

2020-07-05 Thread Jan Kiszka

On 07.02.20 07:43, Jan Kiszka wrote:

From: Jan Kiszka 

This is helpful when debugging stuck guest timers.

As we need apic_get_current_count for that, and it is really not
emulation specific, move it to apic_common.c and export it. Fix its
style at this chance as well.

Signed-off-by: Jan Kiszka 
Reviewed-by: Philippe Mathieu-Daudé 
---

Changes in v2:
  - fix style of apic_get_current_count

  hw/intc/apic.c  | 18 --
  hw/intc/apic_common.c   | 19 +++
  include/hw/i386/apic_internal.h |  1 +
  target/i386/helper.c|  5 +++--
  4 files changed, 23 insertions(+), 20 deletions(-)

diff --git a/hw/intc/apic.c b/hw/intc/apic.c
index bd40467965..f2207d0ace 100644
--- a/hw/intc/apic.c
+++ b/hw/intc/apic.c
@@ -615,24 +615,6 @@ int apic_accept_pic_intr(DeviceState *dev)
  return 0;
  }

-static uint32_t apic_get_current_count(APICCommonState *s)
-{
-int64_t d;
-uint32_t val;
-d = (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->initial_count_load_time) >>
-s->count_shift;
-if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
-/* periodic */
-val = s->initial_count - (d % ((uint64_t)s->initial_count + 1));
-} else {
-if (d >= s->initial_count)
-val = 0;
-else
-val = s->initial_count - d;
-}
-return val;
-}
-
  static void apic_timer_update(APICCommonState *s, int64_t current_time)
  {
  if (apic_next_timer(s, current_time)) {
diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c
index 9ec0f2deb2..fb432e83f2 100644
--- a/hw/intc/apic_common.c
+++ b/hw/intc/apic_common.c
@@ -189,6 +189,25 @@ bool apic_next_timer(APICCommonState *s, int64_t 
current_time)
  return true;
  }

+uint32_t apic_get_current_count(APICCommonState *s)
+{
+int64_t d;
+uint32_t val;
+d = (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->initial_count_load_time) >>
+s->count_shift;
+if (s->lvt[APIC_LVT_TIMER] & APIC_LVT_TIMER_PERIODIC) {
+/* periodic */
+val = s->initial_count - (d % ((uint64_t)s->initial_count + 1));
+} else {
+if (d >= s->initial_count) {
+val = 0;
+} else {
+val = s->initial_count - d;
+}
+}
+return val;
+}
+
  void apic_init_reset(DeviceState *dev)
  {
  APICCommonState *s;
diff --git a/include/hw/i386/apic_internal.h b/include/hw/i386/apic_internal.h
index b04bdd947f..2597000e03 100644
--- a/include/hw/i386/apic_internal.h
+++ b/include/hw/i386/apic_internal.h
@@ -211,6 +211,7 @@ void vapic_report_tpr_access(DeviceState *dev, CPUState 
*cpu, target_ulong ip,
   TPRAccess access);

  int apic_get_ppr(APICCommonState *s);
+uint32_t apic_get_current_count(APICCommonState *s);

  static inline void apic_set_bit(uint32_t *tab, int index)
  {
diff --git a/target/i386/helper.c b/target/i386/helper.c
index c3a6e4fabe..e3c3726c29 100644
--- a/target/i386/helper.c
+++ b/target/i386/helper.c
@@ -370,10 +370,11 @@ void x86_cpu_dump_local_apic_state(CPUState *cs, int 
flags)
  dump_apic_lvt("LVTTHMR", lvt[APIC_LVT_THERMAL], false);
  dump_apic_lvt("LVTT", lvt[APIC_LVT_TIMER], true);

-qemu_printf("Timer\t DCR=0x%x (divide by %u) initial_count = %u\n",
+qemu_printf("Timer\t DCR=0x%x (divide by %u) initial_count = %u"
+" current_count = %u\n",
  s->divide_conf & APIC_DCR_MASK,
  divider_conf(s->divide_conf),
-s->initial_count);
+s->initial_count, apic_get_current_count(s));

  qemu_printf("SPIV\t 0x%08x APIC %s, focus=%s, spurious vec %u\n",
  s->spurious_vec,



Ping.

Jan



Re: [PATCH v7 1/8] mac_oldworld: Allow loading binary ROM image

2020-07-05 Thread BALATON Zoltan

On Sun, 5 Jul 2020, David Gibson wrote:

On Tue, Jun 30, 2020 at 11:45:42PM +0200, BALATON Zoltan wrote:

On Tue, 30 Jun 2020, Mark Cave-Ayland wrote:

On 29/06/2020 19:55, BALATON Zoltan wrote:

The beige G3 Power Macintosh has a 4MB firmware ROM. Fix the size of
the rom region and fall back to loading a binary image with -bios if
loading ELF image failed. This allows testing emulation with a ROM
image from real hardware as well as using an ELF OpenBIOS image.

Signed-off-by: BALATON Zoltan 
---
v4: use load address from ELF to check if ROM is too big

 hw/ppc/mac_oldworld.c | 29 -
 1 file changed, 20 insertions(+), 9 deletions(-)

diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index f8c204ead7..baf3da6f90 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -59,6 +59,8 @@
 #define NDRV_VGA_FILENAME "qemu_vga.ndrv"

 #define GRACKLE_BASE 0xfec0
+#define PROM_BASE 0xffc0
+#define PROM_SIZE (4 * MiB)

 static void fw_cfg_boot_set(void *opaque, const char *boot_device,
 Error **errp)
@@ -99,6 +101,7 @@ static void ppc_heathrow_init(MachineState *machine)
 SysBusDevice *s;
 DeviceState *dev, *pic_dev;
 BusState *adb_bus;
+uint64_t bios_addr;
 int bios_size;
 unsigned int smp_cpus = machine->smp.cpus;
 uint16_t ppc_boot_device;
@@ -127,24 +130,32 @@ static void ppc_heathrow_init(MachineState *machine)

 memory_region_add_subregion(sysmem, 0, machine->ram);

-/* allocate and load BIOS */
-memory_region_init_rom(bios, NULL, "ppc_heathrow.bios", BIOS_SIZE,
+/* allocate and load firmware ROM */
+memory_region_init_rom(bios, NULL, "ppc_heathrow.bios", PROM_SIZE,
&error_fatal);
+memory_region_add_subregion(sysmem, PROM_BASE, bios);

-if (bios_name == NULL)
+if (!bios_name) {
 bios_name = PROM_FILENAME;
+}
 filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
-memory_region_add_subregion(sysmem, PROM_ADDR, bios);
-
-/* Load OpenBIOS (ELF) */
 if (filename) {
-bios_size = load_elf(filename, NULL, 0, NULL, NULL, NULL, NULL, NULL,
- 1, PPC_ELF_MACHINE, 0, 0);
+/* Load OpenBIOS (ELF) */
+bios_size = load_elf(filename, NULL, NULL, NULL, NULL, &bios_addr,
+ NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0);
+if (bios_size <= 0) {
+/* or load binary ROM image */
+bios_size = load_image_targphys(filename, PROM_BASE, PROM_SIZE);
+bios_addr = PROM_BASE;
+} else {
+/* load_elf sets high 32 bits for some reason, strip those */
+bios_addr &= 0xULL;


Repeating my earlier comment from v5: something is wrong here if you need to 
manually
strip the high bits. If you compare with SPARC32 which uses the same approach, 
there
is no such strip required - have a look there to try and figure out what's 
going on here.


OK, the problem here is this:

$ gdb qemu-system-ppc
(gdb) b mac_oldworld.c:146
Breakpoint 1 at 0x416770: file hw/ppc/mac_oldworld.c, line 146.
(gdb) r
Thread 1 "qemu-system-ppc" hit Breakpoint 1, ppc_heathrow_init 
(machine=0x56863800) at hw/ppc/mac_oldworld.c:146
146 filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
(gdb) n
147 if (filename) {
149 bios_size = load_elf(filename, NULL, NULL, NULL, NULL, 
&bios_addr,
151 if (bios_size <= 0) {
(gdb) p bios_size
$1 = 755500
(gdb) p/x bios_addr
$2 = 0xfff0

this happens within load_elf that I don't feel like wanting to debug but
causes problem when we use it to calculate bios size later here:


I think the problem is here, in include/hw/elf_ops.h:

   if (lowaddr)
   *lowaddr = (uint64_t)(elf_sword)low;

"low" is a u64, but for a 32-bit ELF file, which is what I'm guessing
you're dealing with here, elf_sword is an int32_t.  So the first cast
truncates the high bits, but makes it a signed value, so the second
cast sign extends, resulting in those high bits.


Thanks for finding this, this looks like a likely reason.


Sign extending rather than zero-extending seems a dubious choice here,
so I wonder if that should be (elf_word) instead of (elf_sword).  But
maybe there's some weird other case where we do want the sign
extension here.


Looks like most callers which get this value don't even use it, I've 
submitted a patch to clean that up. Of the remaining callers at least 
hppa does similar truncating but uses a cast instead of explicit masking. 
I'll update my mac patches to do the same.


Regards,
BALATON Zoltan


-if (bios_size < 0 || bios_size > BIOS_SIZE) {
+if (bios_size < 0 || bios_addr - PROM_BASE + bios_size > PROM_SIZE) {

unless we strip it down to expected 32 bits. This could be some unwanted
size extension or whatnot but I don't have time to dig deeper.

Now lets see what sun4m does:

$ gdb qemu-system-sparc
(gdb) b sun4m.c:721
Brea

[PATCH] load_elf: Remove unused address variables from callers

2020-07-05 Thread BALATON Zoltan
Several callers of load_elf() pass pointers for lowaddr and highaddr
parameters which are then not used for anything. This may stem from a
misunderstanding that load_elf need a value here but in fact it can
take NULL to ignore these values. Remove such unused variables and
pass NULL instead from callers that don't need these.

Signed-off-by: BALATON Zoltan 
---
 hw/alpha/dp264.c   |  8 
 hw/arm/armv7m.c|  4 +---
 hw/cris/boot.c |  4 ++--
 hw/microblaze/boot.c   |  4 ++--
 hw/mips/fuloong2e.c|  8 
 hw/moxie/moxiesim.c|  4 ++--
 hw/nios2/boot.c|  4 ++--
 hw/ppc/mac_newworld.c  |  6 ++
 hw/ppc/mac_oldworld.c  |  6 ++
 hw/ppc/ppc440_bamboo.c |  9 +++--
 hw/ppc/sam460ex.c  | 12 +---
 hw/ppc/spapr.c | 11 ---
 hw/ppc/virtex_ml507.c  |  4 ++--
 hw/riscv/boot.c|  8 
 hw/xtensa/sim.c|  3 +--
 hw/xtensa/xtfpga.c |  3 +--
 16 files changed, 41 insertions(+), 57 deletions(-)

diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c
index f7751b18f6..4d24518d1d 100644
--- a/hw/alpha/dp264.c
+++ b/hw/alpha/dp264.c
@@ -62,8 +62,8 @@ static void clipper_init(MachineState *machine)
 qemu_irq rtc_irq;
 long size, i;
 char *palcode_filename;
-uint64_t palcode_entry, palcode_low, palcode_high;
-uint64_t kernel_entry, kernel_low, kernel_high;
+uint64_t palcode_entry;
+uint64_t kernel_entry, kernel_low;
 unsigned int smp_cpus = machine->smp.cpus;
 
 /* Create up to 4 cpus.  */
@@ -113,7 +113,7 @@ static void clipper_init(MachineState *machine)
 exit(1);
 }
 size = load_elf(palcode_filename, NULL, cpu_alpha_superpage_to_phys,
-NULL, &palcode_entry, &palcode_low, &palcode_high, NULL,
+NULL, &palcode_entry, NULL, NULL, NULL,
 0, EM_ALPHA, 0, 0);
 if (size < 0) {
 error_report("could not load palcode '%s'", palcode_filename);
@@ -132,7 +132,7 @@ static void clipper_init(MachineState *machine)
 uint64_t param_offset;
 
 size = load_elf(kernel_filename, NULL, cpu_alpha_superpage_to_phys,
-NULL, &kernel_entry, &kernel_low, &kernel_high, NULL,
+NULL, &kernel_entry, &kernel_low, NULL, NULL,
 0, EM_ALPHA, 0, 0);
 if (size < 0) {
 error_report("could not load kernel '%s'", kernel_filename);
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index 3308211e9c..92f859d760 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -309,7 +309,6 @@ void armv7m_load_kernel(ARMCPU *cpu, const char 
*kernel_filename, int mem_size)
 {
 int image_size;
 uint64_t entry;
-uint64_t lowaddr;
 int big_endian;
 AddressSpace *as;
 int asidx;
@@ -330,12 +329,11 @@ void armv7m_load_kernel(ARMCPU *cpu, const char 
*kernel_filename, int mem_size)
 
 if (kernel_filename) {
 image_size = load_elf_as(kernel_filename, NULL, NULL, NULL,
- &entry, &lowaddr, NULL,
+ &entry, NULL, NULL,
  NULL, big_endian, EM_ARM, 1, 0, as);
 if (image_size < 0) {
 image_size = load_image_targphys_as(kernel_filename, 0,
 mem_size, as);
-lowaddr = 0;
 }
 if (image_size < 0) {
 error_report("Could not load kernel '%s'", kernel_filename);
diff --git a/hw/cris/boot.c b/hw/cris/boot.c
index b8947bc660..aa8d2756d6 100644
--- a/hw/cris/boot.c
+++ b/hw/cris/boot.c
@@ -67,7 +67,7 @@ static uint64_t translate_kernel_address(void *opaque, 
uint64_t addr)
 void cris_load_image(CRISCPU *cpu, struct cris_load_info *li)
 {
 CPUCRISState *env = &cpu->env;
-uint64_t entry, high;
+uint64_t entry;
 int kcmdline_len;
 int image_size;
 
@@ -76,7 +76,7 @@ void cris_load_image(CRISCPU *cpu, struct cris_load_info *li)
devboard SDK.  */
 image_size = load_elf(li->image_filename, NULL,
   translate_kernel_address, NULL,
-  &entry, NULL, &high, NULL, 0, EM_CRIS, 0, 0);
+  &entry, NULL, NULL, NULL, 0, EM_CRIS, 0, 0);
 li->entry = entry;
 if (image_size < 0) {
 /* Takes a kimage from the axis devboard SDK.  */
diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c
index 925e3f7c9d..8ad3c27f2c 100644
--- a/hw/microblaze/boot.c
+++ b/hw/microblaze/boot.c
@@ -135,7 +135,7 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr 
ddr_base,
 
 if (kernel_filename) {
 int kernel_size;
-uint64_t entry, low, high;
+uint64_t entry, high;
 uint32_t base32;
 int big_endian = 0;
 
@@ -145,7 +145,7 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr 
ddr_base,
 
 /* Boots a kernel elf binary.  */
 kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
- 

[PATCH] hw/arm/aspeed: Do not create and attach empty SD cards by default

2020-07-05 Thread Philippe Mathieu-Daudé
Since added in commit 2bea128c3d, each SDHCI is wired with a SD
card, using empty card when no block drive provided. This is not
the desired behavior. The SDHCI exposes a SD bus to plug cards
on, if no card available, it is fine to have an unplugged bus.

Avoid creating unnecessary SD card device when no block drive
provided.

Fixes: 2bea128c3d ("hw/sd/aspeed_sdhci: New device")
Signed-off-by: Philippe Mathieu-Daudé 
---
Cc: Eddie James 
Cc: Cédric Le Goater 
Cc: Joel Stanley 
Cc: Andrew Jeffery 
---
 hw/arm/aspeed.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 379f9672a5..11521c4be1 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -246,11 +246,12 @@ static void sdhci_attach_drive(SDHCIState *sdhci, 
DriveInfo *dinfo)
 {
 DeviceState *card;
 
-card = qdev_new(TYPE_SD_CARD);
-if (dinfo) {
-qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo),
-&error_fatal);
+if (!dinfo) {
+return;
 }
+card = qdev_new(TYPE_SD_CARD);
+qdev_prop_set_drive_err(card, "drive", blk_by_legacy_dinfo(dinfo),
+&error_fatal);
 qdev_realize_and_unref(card,
qdev_get_child_bus(DEVICE(sdhci), "sd-bus"),
&error_fatal);
-- 
2.21.3




Re: [PATCH v7 09/17] hw/sd/sdcard: Special case the -ENOMEDIUM error

2020-07-05 Thread Philippe Mathieu-Daudé
On 7/5/20 12:26 AM, Philippe Mathieu-Daudé wrote:
> On 7/5/20 12:18 AM, Philippe Mathieu-Daudé wrote:
>> On 7/5/20 12:10 AM, Philippe Mathieu-Daudé wrote:
>>> On 7/4/20 1:42 AM, Philippe Mathieu-Daudé wrote:
 On 7/3/20 5:16 PM, Philippe Mathieu-Daudé wrote:
> On 7/3/20 3:23 PM, Peter Maydell wrote:
>> On Tue, 30 Jun 2020 at 14:39, Philippe Mathieu-Daudé  
>> wrote:
>>>
>>> As we have no interest in the underlying block geometry,
>>> directly call blk_getlength(). We have to care about machines
>>> creating SD card with not drive attached (probably incorrect
>>> API use). Simply emit a warning when such Frankenstein cards
>>> of zero size are reset.
>>
>> Which machines create SD cards without a backing block device?
>
> The Aspeed machines:
> https://www.mail-archive.com/qemu-devel@nongnu.org/msg718116.html
>>>
>>> Also all boards using:
>>>
>>> hw/sd/milkymist-memcard.c:278:/* FIXME use a qdev drive property
>>> instead of drive_get_next() */
>>> hw/sd/pl181.c:506:/* FIXME use a qdev drive property instead of
>>> drive_get_next() */
>>> hw/sd/ssi-sd.c:253:/* FIXME use a qdev drive property instead of
>>> drive_get_next() */
>>>
>>> I.e.:
>>>
>>> static void pl181_realize(DeviceState *dev, Error **errp)
>>> {
>>> PL181State *s = PL181(dev);
>>> DriveInfo *dinfo;
>>>
>>> /* FIXME use a qdev drive property instead of drive_get_next() */
>>> dinfo = drive_get_next(IF_SD);
>>> s->card = sd_init(dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, false);
>>> if (s->card == NULL) {
>>> error_setg(errp, "sd_init failed");
>>> }
>>> }
>>
>> Doh I was pretty sure this series was merged:
>> https://www.mail-archive.com/qemu-devel@nongnu.org/msg514645.html
>>
>> Time to respin I guess, addressing your comment...
>> https://www.mail-archive.com/qemu-devel@nongnu.org/msg515866.html
> 
> Not straight forward at first glance, so probably too late for soft
> freeze.

I looked in backups of my previous computer and found the branch with
your comment addressed... Not sure why I never send the series, but
this explains why I was sure it was already fixed.

> 
> Meanwhile patches 1-8 are reviewed and sufficient to fix
> CVE-2020-13253. The problematic patch is #9, your "Check address is
> in range" suggestion. Patches 11-14 are also reviewed and can go in.
> 
> Peter, can you consider taking them via your ARM queue? If you prefer
> I can prepare a pull request.
> 
> I'll keep working on this during the next dev window.
> 
> Thanks,
> 
> Phil.
> 
>>
>>>
>
>> I have a feeling that also the monitor "change" and "eject"
>> commands can remove the backing block device from the SD card
>> object.
>
> This is what I wanted to talk about on IRC. This seems wrong to me,
> we should eject the card and destroy it, and recreate a new card
> when plugging in another backing block device.
>
> Keep the reparenting on the bus layer, not on the card.

 I was wrong, the current code is correct:

 void sdbus_reparent_card(SDBus *from, SDBus *to)
 {
 SDState *card = get_card(from);
 SDCardClass *sc;
 bool readonly;

 /* We directly reparent the card object rather than implementing this
  * as a hotpluggable connection because we don't want to expose SD 
 cards
  * to users as being hotpluggable, and we can get away with it in this
  * limited use case. This could perhaps be implemented more cleanly in
  * future by adding support to the hotplug infrastructure for "device
  * can be hotplugged only via code, not by user".
  */

 if (!card) {
 return;
 }

 sc = SD_CARD_GET_CLASS(card);
 readonly = sc->get_readonly(card);

 sdbus_set_inserted(from, false);
 qdev_set_parent_bus(DEVICE(card), &to->qbus);
 sdbus_set_inserted(to, true);
 sdbus_set_readonly(to, readonly);
 }

 What I don't understand is why create a sdcard with no block backend.

 Maybe this is old code before the null-co block backend existed? I
 haven't checked the git history yet.

 I'll try to restrict sdcard with only block backend and see if
 something break (I doubt) at least it simplifies the code.
 But I need to update the Aspeed machines first.

 The problem when not using block backend, is the size is 0,
 so the next patch abort in sd_reset() due to:

   static uint64_t sd_addr_to_wpnum(SDState *sd, uint64_t addr)
   {
   assert(addr < sd->size);

>>>
>>>
>>
> 



Re: [PATCH 3/3] target/nios2: Use gen_io_start around wrctl instruction

2020-07-05 Thread Peter Maydell
On Mon, 29 Jun 2020 at 09:17, Wentong Wu  wrote:
>
> wrctl instruction on nios2 target will cause checking cpu
> interrupt but tcg_handle_interrupt() will call cpu_abort()
> if the CPU gets an interrupt while it's not in 'can do IO'
> state, so add gen_io_start around wrctl instruction. Also
> at the same time, end the onging TB with DISAS_UPDATE.
>
> Signed-off-by: Wentong Wu 
> ---
>  target/nios2/translate.c | 5 +
>  1 file changed, 5 insertions(+)
>
> diff --git a/target/nios2/translate.c b/target/nios2/translate.c
> index 83c10eb2..51347ada 100644
> --- a/target/nios2/translate.c
> +++ b/target/nios2/translate.c
> @@ -32,6 +32,7 @@
>  #include "exec/cpu_ldst.h"
>  #include "exec/translator.h"
>  #include "qemu/qemu-print.h"
> +#include "exec/gen-icount.h"
>
>  /* is_jmp field values */
>  #define DISAS_JUMPDISAS_TARGET_0 /* only pc was modified dynamically */
> @@ -518,7 +519,11 @@ static void wrctl(DisasContext *dc, uint32_t code, 
> uint32_t flags)
>  /* If interrupts were enabled using WRCTL, trigger them. */
>  #if !defined(CONFIG_USER_ONLY)
>  if ((instr.imm5 + CR_BASE) == CR_STATUS) {
> +if (tb_cflags(dc->tb) & CF_USE_ICOUNT) {
> +gen_io_start();
> +}
>  gen_helper_check_interrupts(dc->cpu_env);
> +dc->is_jmp = DISAS_UPDATE;
>  }
>  #endif
>  }

Reviewed-by: Peter Maydell 

though as Richard notes ideally the interrupt handling code here should
be rewritten because the check_interrupts helper is a very weird way
to implement things.

thanks
-- PMM



Re: [PATCH 3/3] target/nios2: Use gen_io_start around wrctl instruction

2020-07-05 Thread Peter Maydell
On Thu, 2 Jul 2020 at 19:53, Richard Henderson
 wrote:
> This isn't right.  Not so much the gen_io_start portion, but the entire
> existence of helper_check_interrupt.

I agree that it looks bogus (xtensa has a similar helper as well, incidentally),
but fixing all that stuff up is more effort than the relatively small job
of getting the icount handling right for the code we have today, which
is why I suggested to Wentong that we could just do this bit for now.

thanks
-- PMM



Re: [PATCH v2 1/1] disas: mips: Add Loongson 2F disassembler

2020-07-05 Thread Aleksandar Markovic
On Sunday, July 5, 2020, Aleksandar Markovic <
aleksandar.qemu.de...@gmail.com> wrote:

>
>
> On Saturday, July 4, 2020, Aleksandar Markovic <
> aleksandar.qemu.de...@gmail.com> wrote:
>
>>
>>
>> On Friday, July 3, 2020, Stefan Brankovic 
>> wrote:
>>
>>> Add disassembler for Loongson 2F instruction set.
>>>
>>> Testing is done by comparing qemu disassembly output, obtained by
>>> using -d in_asm command line option, with appropriate objdump output.
>>>
>>> This disassembler is written as a generic disassembler that can be
>>> integrated into other projects. In this case, it is integrated into
>>> QEMU. One of initial key requirements was that it uses C++ as its
>>> language.
>>>
>>> Signed-off-by: Stefan Brankovic 
>>> ---
>>
>>
>>
> I did some basic tests, and the output matches objdump's.
>
> Apart from the mentioned cosmetic changes with ALIAS_MAX_LEN, there is one
> function invocation that should be under "ifdef", similar to the nanomips
> counterpart case.
>
> Otherwise:
>
> Reviewed-by: Aleksandar Markovic 
>
>
I plan to select this patch for the next MIPS + TCG Continuous Benchmarking
pull request.


>
>
>> Thank you, Stefan!
>>
>> I am going to dor some independant testing in next few days, including
>> building on systems without g++ (build should be successful, and the
>> disassembler should fallback on the current one).
>>
>> I noticed some cosmetic improvements may still be done, like, for
>> example, using [ALIAS_MAX_LEN] instead of [5] in numerous places. But,
>> there is no need to respin (send a new version) just for this. Overall, the
>> code looks well-organized and clean.
>>
>> An interesting topic for future work would be the automation of QEMU
>> disassembler testing. Not only for this dissasembler, but for any supported
>> disassembler in QEMU. I don't say you should do it, this is just a
>> brainstorming idea, somebody may hopefully pick it up.
>>
>> Congratulations on this interesting work!
>>
>> Aleksandar
>>
>>
>>
>>
>>>  MAINTAINERS |1 +
>>>  configure   |1 +
>>>  disas/Makefile.objs |1 +
>>>  disas/loongson2f.cpp| 8154 +++
>>>  disas/loongson2f.h  | 2562 
>>>  include/disas/dis-asm.h |1 +
>>>  include/exec/poison.h   |1 +
>>>  target/mips/cpu.c   |4 +
>>>  8 files changed, 10725 insertions(+)
>>>  create mode 100644 disas/loongson2f.cpp
>>>  create mode 100644 disas/loongson2f.h
>>>
>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>> index 3abe3faa4e..913ed2a6d3 100644
>>> --- a/MAINTAINERS
>>> +++ b/MAINTAINERS
>>> @@ -219,6 +219,7 @@ S: Maintained
>>>  F: target/mips/
>>>  F: default-configs/*mips*
>>>  F: disas/*mips*
>>> +F: disas/loongson*
>>>  F: docs/system/cpu-models-mips.rst.inc
>>>  F: hw/intc/mips_gic.c
>>>  F: hw/mips/
>>> diff --git a/configure b/configure
>>> index 597e909b53..e163dac53e 100755
>>> --- a/configure
>>> +++ b/configure
>>> @@ -8102,6 +8102,7 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
>>>  disas_config "MIPS"
>>>  if test -n "${cxx}"; then
>>>disas_config "NANOMIPS"
>>> +  disas_config "LOONGSON2F"
>>>  fi
>>>;;
>>>moxie*)
>>> diff --git a/disas/Makefile.objs b/disas/Makefile.objs
>>> index 3c1cdce026..0d5ee1e038 100644
>>> --- a/disas/Makefile.objs
>>> +++ b/disas/Makefile.objs
>>> @@ -14,6 +14,7 @@ common-obj-$(CONFIG_I386_DIS) += i386.o
>>>  common-obj-$(CONFIG_M68K_DIS) += m68k.o
>>>  common-obj-$(CONFIG_MICROBLAZE_DIS) += microblaze.o
>>>  common-obj-$(CONFIG_MIPS_DIS) += mips.o
>>> +common-obj-$(CONFIG_LOONGSON2F_DIS) += loongson2f.o
>>>  common-obj-$(CONFIG_NANOMIPS_DIS) += nanomips.o
>>>  common-obj-$(CONFIG_NIOS2_DIS) += nios2.o
>>>  common-obj-$(CONFIG_MOXIE_DIS) += moxie.o
>>> diff --git a/disas/loongson2f.cpp b/disas/loongson2f.cpp
>>> new file mode 100644
>>> index 00..e84a2c0f09
>>> --- /dev/null
>>> +++ b/disas/loongson2f.cpp
>>> @@ -0,0 +1,8154 @@
>>> +/*
>>> + *  Source file for Loongson 2F disassembler component of QEMU
>>> + *
>>> + *  Copyright (C) 2020  Stefan Brankovic 
>>> + *
>>> + *  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 <
>>> https://www.gnu.org/licenses/>.
>>> + *
>>> + */
>>> +
>>> +extern "C" {
>>> +#include "qemu/osdep.h"
>>> +#include "qemu/bitops.h"
>>> +#include "disas/dis-asm.h"
>>> +}
>>> +
>>> +#include "loongson2f.h"
>>> +
>>> +int print_insn_loo

Re: [PATCH v2 1/1] disas: mips: Add Loongson 2F disassembler

2020-07-05 Thread Aleksandar Markovic
On Saturday, July 4, 2020, Aleksandar Markovic <
aleksandar.qemu.de...@gmail.com> wrote:

>
>
> On Friday, July 3, 2020, Stefan Brankovic 
> wrote:
>
>> Add disassembler for Loongson 2F instruction set.
>>
>> Testing is done by comparing qemu disassembly output, obtained by
>> using -d in_asm command line option, with appropriate objdump output.
>>
>> This disassembler is written as a generic disassembler that can be
>> integrated into other projects. In this case, it is integrated into
>> QEMU. One of initial key requirements was that it uses C++ as its
>> language.
>>
>> Signed-off-by: Stefan Brankovic 
>> ---
>
>
>
I did some basic tests, and the output matches objdump's.

Apart from the mentioned cosmetic changes with ALIAS_MAX_LEN, there is one
function invocation that should be under "ifdef", similar to the nanomips
counterpart case.

Otherwise:

Reviewed-by: Aleksandar Markovic 



> Thank you, Stefan!
>
> I am going to dor some independant testing in next few days, including
> building on systems without g++ (build should be successful, and the
> disassembler should fallback on the current one).
>
> I noticed some cosmetic improvements may still be done, like, for example,
> using [ALIAS_MAX_LEN] instead of [5] in numerous places. But, there is no
> need to respin (send a new version) just for this. Overall, the code looks
> well-organized and clean.
>
> An interesting topic for future work would be the automation of QEMU
> disassembler testing. Not only for this dissasembler, but for any supported
> disassembler in QEMU. I don't say you should do it, this is just a
> brainstorming idea, somebody may hopefully pick it up.
>
> Congratulations on this interesting work!
>
> Aleksandar
>
>
>
>
>>  MAINTAINERS |1 +
>>  configure   |1 +
>>  disas/Makefile.objs |1 +
>>  disas/loongson2f.cpp| 8154 +++
>>  disas/loongson2f.h  | 2562 
>>  include/disas/dis-asm.h |1 +
>>  include/exec/poison.h   |1 +
>>  target/mips/cpu.c   |4 +
>>  8 files changed, 10725 insertions(+)
>>  create mode 100644 disas/loongson2f.cpp
>>  create mode 100644 disas/loongson2f.h
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 3abe3faa4e..913ed2a6d3 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -219,6 +219,7 @@ S: Maintained
>>  F: target/mips/
>>  F: default-configs/*mips*
>>  F: disas/*mips*
>> +F: disas/loongson*
>>  F: docs/system/cpu-models-mips.rst.inc
>>  F: hw/intc/mips_gic.c
>>  F: hw/mips/
>> diff --git a/configure b/configure
>> index 597e909b53..e163dac53e 100755
>> --- a/configure
>> +++ b/configure
>> @@ -8102,6 +8102,7 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
>>  disas_config "MIPS"
>>  if test -n "${cxx}"; then
>>disas_config "NANOMIPS"
>> +  disas_config "LOONGSON2F"
>>  fi
>>;;
>>moxie*)
>> diff --git a/disas/Makefile.objs b/disas/Makefile.objs
>> index 3c1cdce026..0d5ee1e038 100644
>> --- a/disas/Makefile.objs
>> +++ b/disas/Makefile.objs
>> @@ -14,6 +14,7 @@ common-obj-$(CONFIG_I386_DIS) += i386.o
>>  common-obj-$(CONFIG_M68K_DIS) += m68k.o
>>  common-obj-$(CONFIG_MICROBLAZE_DIS) += microblaze.o
>>  common-obj-$(CONFIG_MIPS_DIS) += mips.o
>> +common-obj-$(CONFIG_LOONGSON2F_DIS) += loongson2f.o
>>  common-obj-$(CONFIG_NANOMIPS_DIS) += nanomips.o
>>  common-obj-$(CONFIG_NIOS2_DIS) += nios2.o
>>  common-obj-$(CONFIG_MOXIE_DIS) += moxie.o
>> diff --git a/disas/loongson2f.cpp b/disas/loongson2f.cpp
>> new file mode 100644
>> index 00..e84a2c0f09
>> --- /dev/null
>> +++ b/disas/loongson2f.cpp
>> @@ -0,0 +1,8154 @@
>> +/*
>> + *  Source file for Loongson 2F disassembler component of QEMU
>> + *
>> + *  Copyright (C) 2020  Stefan Brankovic 
>> + *
>> + *  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 > >.
>> + *
>> + */
>> +
>> +extern "C" {
>> +#include "qemu/osdep.h"
>> +#include "qemu/bitops.h"
>> +#include "disas/dis-asm.h"
>> +}
>> +
>> +#include "loongson2f.h"
>> +
>> +int print_insn_loongson2f(bfd_vma addr, disassemble_info *info)
>> +{
>> +bfd_byte buffer[4];
>> +uint32_t insn32;
>> +int status;
>> +Decoder *decoder = new Decoder();
>> +
>> +status = info->read_memory_func(addr, buffer, 4, info);
>> +if (status != 0) {
>> +info->memory_error_func(status, addr, info);
>> +retu

Re: [PATCH rc6 00/30] target/avr merger

2020-07-05 Thread no-reply
Patchew URL: 
https://patchew.org/QEMU/20200705140315.260514-1-h...@tuxfamily.org/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Subject: [PATCH rc6 00/30] target/avr merger
Type: series
Message-id: 20200705140315.260514-1-h...@tuxfamily.org

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 - [tag update]  patchew/20200703184952.4918-1-f4...@amsat.org -> 
patchew/20200703184952.4918-1-f4...@amsat.org
 - [tag update]  patchew/20200703200459.23294-1-f4...@amsat.org -> 
patchew/20200703200459.23294-1-f4...@amsat.org
 - [tag update]  patchew/20200704153908.12118-1-phi...@redhat.com -> 
patchew/20200704153908.12118-1-phi...@redhat.com
 * [new tag] patchew/20200705140315.260514-1-h...@tuxfamily.org -> 
patchew/20200705140315.260514-1-h...@tuxfamily.org
Switched to a new branch 'test'
faad775 target/avr: Add section into QEMU documentation
8857615 tests/acceptance: Test the Arduino MEGA2560 board
b564682 tests/boot-serial: Test some Arduino boards (AVR based)
d5e4699 tests/machine-none: Add AVR support
bba1e34 target/avr: Update build system
29dd29c hw/avr: Add limited support for some Arduino boards
3d1640f hw/avr: Add some ATmega microcontrollers
43b47a1 hw/avr: Add support for loading ELF/raw binaries
1ae4d9e target/avr: Register AVR support with the rest of QEMU
a523aa8 hw/misc: avr: Add limited support for power reduction device
d673e4a hw/timer: avr: Add limited support for 16-bit timer peripheral
3cb5e31 hw/char: avr: Add limited support for USART peripheral
81ef8ef target/avr: Add support for disassembling via option '-d in_asm'
e2c7a47 target/avr: Initialize TCG register variables
31793f5 target/avr: Add instruction translation - CPU main translation function
03b0b1e target/avr: Add instruction translation - MCU Control Instructions
dd26299 target/avr: Add instruction translation - Bit and Bit-test Instructions
cf3dbfd target/avr: Add instruction translation - Data Transfer Instructions
22d4651 target/avr: Add instruction translation - Branch Instructions
120a956 target/avr: Add instruction translation - Arithmetic and Logic 
Instructions
28a91ea target/avr: Add instruction translation - Register definitions
b61b514 target/avr: Add instruction helpers
74089c9 target/avr: Add defintions of AVR core types
9c7e675 target/avr: Introduce enumeration AVRFeature
1fd82d4 target/avr: CPU class: Add GDB support
3c788c7 target/avr: CPU class: Add migration support
cb72169 target/avr: CPU class: Add memory menagement support
0758ca1 target/avr: CPU class: Add interrupt handling support
bf938b7 target/avr: Introduce basic CPU class object
b5e3116 target/avr: Add basic parameters of the new platform

=== OUTPUT BEGIN ===
1/30 Checking commit b5e3116a3591 (target/avr: Add basic parameters of the new 
platform)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#42: 
new file mode 100644

total: 0 errors, 1 warnings, 115 lines checked

Patch 1/30 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
2/30 Checking commit bf938b75dc12 (target/avr: Introduce basic CPU class object)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#25: 
new file mode 100644

total: 0 errors, 1 warnings, 412 lines checked

Patch 2/30 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
3/30 Checking commit 0758ca106cc4 (target/avr: CPU class: Add interrupt 
handling support)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#37: 
new file mode 100644

total: 0 errors, 1 warnings, 97 lines checked

Patch 3/30 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
4/30 Checking commit cb72169d4881 (target/avr: CPU class: Add memory menagement 
support)
5/30 Checking commit 3c788c7f7b46 (target/avr: CPU class: Add migration support)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#48: 
new file mode 100644

total: 0 errors, 1 warnings, 136 lines checked

Patch 5/30 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
6/30 Checking commit 1fd82d47f5a7 (target/avr: CPU class: Add GDB support)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#37: 
new file mode 100644

total: 0 errors, 1 warnings, 156 lines checked

Patch 6/30 has style problems, please review.  If any of these errors
are false positives

Re: [PATCH v2 1/1] disas: mips: Add Loongson 2F disassembler

2020-07-05 Thread Jiaxun Yang




在 2020/7/5 4:04, Philippe Mathieu-Daudé 写道:

Hi Stefan,

On 7/3/20 12:44 PM, Stefan Brankovic wrote:

Add disassembler for Loongson 2F instruction set.

Testing is done by comparing qemu disassembly output, obtained by
using -d in_asm command line option, with appropriate objdump output.

This disassembler is written as a generic disassembler that can be
integrated into other projects. In this case, it is integrated into
QEMU. One of initial key requirements was that it uses C++ as its
language.

Wow, this is a huge contribution!

QEMU uses the libcapstone as backend to disassemble some architectures.
I see the project [1] do support MIPS [2], but they don't support
neither nanoMIPS nor the Loongson 2F instruction set. As the library is
used by other projects, it might be worthwhile have a look if your
disassembler could fit there instead.
Don't take this as a negative comment please, this is the opposite:
more users would be able to use your work.
My comment doesn't say neither that I am against your proposal. I
wanted to be sure you are aware of the capstone engine project.


Capstone relies on an ancient version of LLVM MC, however, Loongson 
instructions

never got upstreamed in LLVM.

But... Yeah, upstream capstone looks like a better idea for the future.

I cc'ed Jiaxun Yang who has more experience with the Loongson 2F ISA
and might be able to test your patch.


Thanks, will do some review and test later.



Regards,

Phil.

[1] http://www.capstone-engine.org/
[2] http://www.capstone-engine.org/arch.html


Signed-off-by: Stefan Brankovic 
---
  MAINTAINERS |1 +
  configure   |1 +
  disas/Makefile.objs |1 +
  disas/loongson2f.cpp| 8154 +++
  disas/loongson2f.h  | 2562 
  include/disas/dis-asm.h |1 +
  include/exec/poison.h   |1 +
  target/mips/cpu.c   |4 +
  8 files changed, 10725 insertions(+)
  create mode 100644 disas/loongson2f.cpp
  create mode 100644 disas/loongson2f.h




[PATCH rc6 27/30] tests/machine-none: Add AVR support

2020-07-05 Thread Thomas Huth
From: Michael Rolnik 

Add a single code line that will automatically provide 'machine none'
test.

Signed-off-by: Michael Rolnik 
Signed-off-by: Richard Henderson 
Signed-off-by: Aleksandar Markovic 
Tested-by: Philippe Mathieu-Daudé 
Reviewed-by: Aleksandar Markovic 
Reviewed-by: Thomas Huth 
Signed-off-by: Thomas Huth 
---
 tests/qtest/machine-none-test.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/qtest/machine-none-test.c b/tests/qtest/machine-none-test.c
index 8b7abea8af..57107f1aec 100644
--- a/tests/qtest/machine-none-test.c
+++ b/tests/qtest/machine-none-test.c
@@ -27,6 +27,7 @@ static struct arch2cpu cpus_map[] = {
 /* tested targets list */
 { "arm", "cortex-a15" },
 { "aarch64", "cortex-a57" },
+{ "avr", "avr6-avr-cpu" },
 { "x86_64", "qemu64,apic-id=0" },
 { "i386", "qemu32,apic-id=0" },
 { "alpha", "ev67" },
-- 
2.26.2




[PATCH rc6 19/30] hw/char: avr: Add limited support for USART peripheral

2020-07-05 Thread Thomas Huth
From: Michael Rolnik 

These were designed to facilitate testing but should provide enough
function to be useful in other contexts.  Only a subset of the functions
of each peripheral is implemented, mainly due to the lack of a standard
way to handle electrical connections (like GPIO pins).

[AM: Remove word 'Atmel' from filenames and all elements of code]
Suggested-by: Aleksandar Markovic 
Signed-off-by: Michael Rolnik 
Signed-off-by: Sarah Harris 
Signed-off-by: Philippe Mathieu-Daudé 
[rth: Squash I/O size fix and file rename from f4bug]
Signed-off-by: Richard Henderson 
Signed-off-by: Aleksandar Markovic 
Reviewed-by: Aleksandar Markovic 
Signed-off-by: Thomas Huth 
---
 MAINTAINERS |  10 ++
 hw/char/Kconfig |   3 +
 hw/char/Makefile.objs   |   1 +
 hw/char/avr_usart.c | 320 
 include/hw/char/avr_usart.h |  93 +++
 5 files changed, 427 insertions(+)
 create mode 100644 hw/char/avr_usart.c
 create mode 100644 include/hw/char/avr_usart.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 11a0611b3e..8c0cc4fbc6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -975,6 +975,16 @@ F: include/hw/*/nrf51*.h
 F: include/hw/*/microbit*.h
 F: tests/qtest/microbit-test.c
 
+AVR Machines
+-
+
+AVR MCUs
+M: Michael Rolnik 
+R: Sarah Harris 
+S: Maintained
+F: include/hw/char/avr_usart.h
+F: hw/char/avr_usart.c
+
 CRIS Machines
 -
 Axis Dev88
diff --git a/hw/char/Kconfig b/hw/char/Kconfig
index 874627520c..b7e0e4d5fa 100644
--- a/hw/char/Kconfig
+++ b/hw/char/Kconfig
@@ -49,3 +49,6 @@ config TERMINAL3270
 
 config RENESAS_SCI
 bool
+
+config AVR_USART
+bool
diff --git a/hw/char/Makefile.objs b/hw/char/Makefile.objs
index 8306c4a789..bf177ac41d 100644
--- a/hw/char/Makefile.objs
+++ b/hw/char/Makefile.objs
@@ -22,6 +22,7 @@ common-obj-$(CONFIG_DIGIC) += digic-uart.o
 common-obj-$(CONFIG_STM32F2XX_USART) += stm32f2xx_usart.o
 common-obj-$(CONFIG_RASPI) += bcm2835_aux.o
 common-obj-$(CONFIG_RENESAS_SCI) += renesas_sci.o
+common-obj-$(CONFIG_AVR_USART) += avr_usart.o
 
 common-obj-$(CONFIG_CMSDK_APB_UART) += cmsdk-apb-uart.o
 common-obj-$(CONFIG_ETRAXFS) += etraxfs_ser.o
diff --git a/hw/char/avr_usart.c b/hw/char/avr_usart.c
new file mode 100644
index 00..fbe2a112b7
--- /dev/null
+++ b/hw/char/avr_usart.c
@@ -0,0 +1,320 @@
+/*
+ * AVR USART
+ *
+ * Copyright (c) 2018 University of Kent
+ * Author: Sarah Harris
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * 
+ */
+
+#include "qemu/osdep.h"
+#include "hw/char/avr_usart.h"
+#include "qemu/log.h"
+#include "hw/irq.h"
+#include "hw/qdev-properties.h"
+
+static int avr_usart_can_receive(void *opaque)
+{
+AVRUsartState *usart = opaque;
+
+if (usart->data_valid || !(usart->csrb & USART_CSRB_RXEN)) {
+return 0;
+}
+return 1;
+}
+
+static void avr_usart_receive(void *opaque, const uint8_t *buffer, int size)
+{
+AVRUsartState *usart = opaque;
+assert(size == 1);
+assert(!usart->data_valid);
+usart->data = buffer[0];
+usart->data_valid = true;
+usart->csra |= USART_CSRA_RXC;
+if (usart->csrb & USART_CSRB_RXCIE) {
+qemu_set_irq(usart->rxc_irq, 1);
+}
+}
+
+static void update_char_mask(AVRUsartState *usart)
+{
+uint8_t mode = ((usart->csrc & USART_CSRC_CSZ0) ? 1 : 0) |
+((usart->csrc & USART_CSRC_CSZ1) ? 2 : 0) |
+((usart->csrb & USART_CSRB_CSZ2) ? 4 : 0);
+switch (mode) {
+case 0:
+usart->char_mask = 0b1;
+break;
+case 1:
+usart->char_mask = 0b11;
+break;
+case 2:
+usart->char_mask = 0b111;
+break;
+case 3:
+usart->char_mask = 0b;
+break;
+case 4:
+/* Fallthrough. */
+case 5:
+/* Fallthrough. */
+case 6:
+qemu_log_mask(
+LOG_GUEST_ERROR,
+"%s: Reserved character size 0x%x\n",
+__func__,
+mode);
+break;
+case 7:
+qemu_log_mask(
+LOG_GUEST_ERROR,
+"%s: Nine bit character size not supported (forcing eight)\n",
+__func__);
+usart->char_mask = 0b;
+break;
+default:
+assert(0);
+}
+}
+
+static void avr_usart_reset(DeviceState *dev)
+{
+AVRUsartState *usart = AVR_USART(dev);

[PATCH rc6 13/30] target/avr: Add instruction translation - Data Transfer Instructions

2020-07-05 Thread Thomas Huth
From: Michael Rolnik 

This includes:
- MOV, MOVW
- LDI, LDS LDX LDY LDZ
- LDDY, LDDZ
- STS, STX STY STZ
- STDY, STDZ
- LPM, LPMX
- ELPM, ELPMX
- SPM, SPMX
- IN, OUT
- PUSH, POP
- XCH
- LAS, LAC LAT

Signed-off-by: Michael Rolnik 
Signed-off-by: Richard Henderson 
Signed-off-by: Aleksandar Markovic 
Tested-by: Philippe Mathieu-Daudé 
Reviewed-by: Aleksandar Markovic 
Signed-off-by: Thomas Huth 
---
 target/avr/insn.decode |  56 +++
 target/avr/translate.c | 992 +
 2 files changed, 1048 insertions(+)

diff --git a/target/avr/insn.decode b/target/avr/insn.decode
index 8b00d8807c..341b55210c 100644
--- a/target/avr/insn.decode
+++ b/target/avr/insn.decode
@@ -107,3 +107,59 @@ SBIC1001 1001 reg:5 bit:3
 SBIS1001 1011 reg:5 bit:3
 BRBS 00 ... ... @op_bit_imm
 BRBC 01 ... ... @op_bit_imm
+
+#
+# Data Transfer Instructions
+#
+
+%rd_d   4:4 !function=to_regs_00_30_by_two
+%rr_d   0:4 !function=to_regs_00_30_by_two
+
+@io_rd_imm   . .. . &rd_imm rd=%rd imm=%io_imm
+@ldst_d .. . . .. . rd:5  . ... &rd_imm imm=%ldst_d_imm
+
+# The 16-bit immediate is completely in the next word.
+# Fields cannot be defined with no bits, so we cannot play
+# the same trick and append to a zero-bit value.
+# Defer reading the immediate until trans_{LDS,STS}.
+@ldst_s  ... rd:5   imm=0
+
+MOV 0010 11 . . @op_rd_rr
+MOVW 0001   &rd_rr  rd=%rd_d rr=%rr_d
+LDI 1110    @op_rd_imm8
+LDS 1001 000 .  @ldst_s
+LDX11001 000 rd:5 1100
+LDX21001 000 rd:5 1101
+LDX31001 000 rd:5 1110
+LDY21001 000 rd:5 1001
+LDY31001 000 rd:5 1010
+LDZ21001 000 rd:5 0001
+LDZ31001 000 rd:5 0010
+LDDY10 . 0 .. 0 . 1 ... @ldst_d
+LDDZ10 . 0 .. 0 . 0 ... @ldst_d
+STS 1001 001 .  @ldst_s
+STX11001 001 rr:5 1100
+STX21001 001 rr:5 1101
+STX31001 001 rr:5 1110
+STY21001 001 rd:5 1001
+STY31001 001 rd:5 1010
+STZ21001 001 rd:5 0001
+STZ31001 001 rd:5 0010
+STDY10 . 0 .. 1 . 1 ... @ldst_d
+STDZ10 . 0 .. 1 . 0 ... @ldst_d
+LPM11001 0101 1100 1000
+LPM21001 000 rd:5 0100
+LPMX1001 000 rd:5 0101
+ELPM1   1001 0101 1101 1000
+ELPM2   1001 000 rd:5 0110
+ELPMX   1001 000 rd:5 0111
+SPM 1001 0101 1110 1000
+SPMX1001 0101  1000
+IN  1011 0 .. . @io_rd_imm
+OUT 1011 1 .. . @io_rd_imm
+PUSH1001 001 rd:5 
+POP 1001 000 rd:5 
+XCH 1001 001 rd:5 0100
+LAC 1001 001 rd:5 0110
+LAS 1001 001 rd:5 0101
+LAT 1001 001 rd:5 0111
diff --git a/target/avr/translate.c b/target/avr/translate.c
index 6db9f74a02..63b4e16169 100644
--- a/target/avr/translate.c
+++ b/target/avr/translate.c
@@ -144,6 +144,11 @@ static int to_regs_24_30_by_two(DisasContext *ctx, int 
indx)
 return 24 + (indx % 4) * 2;
 }
 
+static int to_regs_00_30_by_two(DisasContext *ctx, int indx)
+{
+return (indx % 16) * 2;
+}
+
 
 static uint16_t next_word(DisasContext *ctx)
 {
@@ -1508,3 +1513,990 @@ static bool trans_BRBS(DisasContext *ctx, arg_BRBS *a)
 ctx->bstate = DISAS_CHAIN;
 return true;
 }
+
+/*
+ * Data Transfer Instructions
+ */
+
+/*
+ *  in the gen_set_addr & gen_get_addr functions
+ *  H assumed to be in 0x00ff format
+ *  M assumed to be in 0x00ff format
+ *  L assumed to be in 0x00ff format
+ */
+static void gen_set_addr(TCGv addr, TCGv H, TCGv M, TCGv L)
+{
+
+tcg_gen_andi_tl(L, addr, 0x00ff);
+
+tcg_gen_andi_tl(M, addr, 0xff00);
+tcg_gen_shri_tl(M, M, 8);
+
+tcg_gen_andi_tl(H, addr, 0x00ff);
+}
+
+static void gen_set_xaddr(TCGv addr)
+{
+gen_set_addr(addr, cpu_rampX, cpu_r[27], cpu_r[26]);
+}
+
+static void gen_set_yaddr(TCGv addr)
+{
+gen_set_addr(addr, cpu_rampY, cpu_r[29], cpu_r[28]);
+}
+
+static void gen_set_zaddr(TCGv addr)
+{
+gen_set_addr(addr, cpu_rampZ, cpu_r[31], cpu_r[30]);
+}
+
+static TCGv gen_get_addr(TCGv H, TCGv M, TCGv L)
+{
+TCGv addr = tcg_temp_new_i32();
+
+tcg_gen_deposit_tl(addr, M, H, 8, 8);
+tcg_gen_deposit_tl(addr, L, addr, 8, 16);
+
+return addr;
+}
+
+static TCGv gen_get_xaddr(void)
+{
+return gen_get_addr(cpu_rampX, cpu_r[27], cpu_r[26]);
+}
+
+static TCGv gen_get_yaddr(void)
+{
+return gen_get_addr(cpu_rampY, cpu_r[29], cpu_r[28]);
+}
+
+static TCGv gen_get_zaddr(void)
+{
+return ge

[PATCH rc6 12/30] target/avr: Add instruction translation - Branch Instructions

2020-07-05 Thread Thomas Huth
From: Michael Rolnik 

This includes:
- RJMP, IJMP, EIJMP, JMP
- RCALL, ICALL, EICALL, CALL
- RET, RETI
- CPSE, CP, CPC, CPI
- SBRC, SBRS, SBIC, SBIS
- BRBC, BRBS

Signed-off-by: Michael Rolnik 
Signed-off-by: Richard Henderson 
Signed-off-by: Aleksandar Markovic 
Tested-by: Philippe Mathieu-Daudé 
Reviewed-by: Aleksandar Markovic 
Signed-off-by: Thomas Huth 
---
 target/avr/insn.decode |  33 +++
 target/avr/translate.c | 544 +
 2 files changed, 577 insertions(+)

diff --git a/target/avr/insn.decode b/target/avr/insn.decode
index 43baf6d92f..8b00d8807c 100644
--- a/target/avr/insn.decode
+++ b/target/avr/insn.decode
@@ -74,3 +74,36 @@ FMUL 0011 0 ... 1 ...   @fmul
 FMULS    0011 1 ... 0 ...   @fmul
 FMULSU   0011 1 ... 1 ...   @fmul
 DES 1001 0100 imm:4 1011
+
+#
+# Branch Instructions
+#
+
+# The 22-bit immediate is partially in the opcode word,
+# and partially in the next.  Use append_16 to build the
+# complete 22-bit value.
+%imm_call   4:5 0:1 !function=append_16
+
+@op_bit   . bit:3 
+@op_bit_imm  .. imm:s7 bit:3
+
+RJMP1100 imm:s12
+IJMP1001 0100  1001
+EIJMP   1001 0100 0001 1001
+JMP 1001 010 . 110 .imm=%imm_call
+RCALL   1101 imm:s12
+ICALL   1001 0101  1001
+EICALL  1001 0101 0001 1001
+CALL1001 010 . 111 .imm=%imm_call
+RET 1001 0101  1000
+RETI1001 0101 0001 1000
+CPSE0001 00 . . @op_rd_rr
+CP  0001 01 . . @op_rd_rr
+CPC  01 . . @op_rd_rr
+CPI 0011    @op_rd_imm8
+SBRC 110 rr:5 0 bit:3
+SBRS 111 rr:5 0 bit:3
+SBIC1001 1001 reg:5 bit:3
+SBIS1001 1011 reg:5 bit:3
+BRBS 00 ... ... @op_bit_imm
+BRBC 01 ... ... @op_bit_imm
diff --git a/target/avr/translate.c b/target/avr/translate.c
index d81bfaa04b..6db9f74a02 100644
--- a/target/avr/translate.c
+++ b/target/avr/translate.c
@@ -145,6 +145,17 @@ static int to_regs_24_30_by_two(DisasContext *ctx, int 
indx)
 }
 
 
+static uint16_t next_word(DisasContext *ctx)
+{
+return cpu_lduw_code(ctx->env, ctx->npc++ * 2);
+}
+
+static int append_16(DisasContext *ctx, int x)
+{
+return x << 16 | next_word(ctx);
+}
+
+
 static bool avr_have_feature(DisasContext *ctx, int feature)
 {
 if (!avr_feature(ctx->env, feature)) {
@@ -964,3 +975,536 @@ static bool trans_DES(DisasContext *ctx, arg_DES *a)
 
 return true;
 }
+
+/*
+ * Branch Instructions
+ */
+static void gen_jmp_ez(DisasContext *ctx)
+{
+tcg_gen_deposit_tl(cpu_pc, cpu_r[30], cpu_r[31], 8, 8);
+tcg_gen_or_tl(cpu_pc, cpu_pc, cpu_eind);
+ctx->bstate = DISAS_LOOKUP;
+}
+
+static void gen_jmp_z(DisasContext *ctx)
+{
+tcg_gen_deposit_tl(cpu_pc, cpu_r[30], cpu_r[31], 8, 8);
+ctx->bstate = DISAS_LOOKUP;
+}
+
+static void gen_push_ret(DisasContext *ctx, int ret)
+{
+if (avr_feature(ctx->env, AVR_FEATURE_1_BYTE_PC)) {
+
+TCGv t0 = tcg_const_i32((ret & 0xff));
+
+tcg_gen_qemu_st_tl(t0, cpu_sp, MMU_DATA_IDX, MO_UB);
+tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
+
+tcg_temp_free_i32(t0);
+} else if (avr_feature(ctx->env, AVR_FEATURE_2_BYTE_PC)) {
+
+TCGv t0 = tcg_const_i32((ret & 0x00));
+
+tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
+tcg_gen_qemu_st_tl(t0, cpu_sp, MMU_DATA_IDX, MO_BEUW);
+tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
+
+tcg_temp_free_i32(t0);
+
+} else if (avr_feature(ctx->env, AVR_FEATURE_3_BYTE_PC)) {
+
+TCGv lo = tcg_const_i32((ret & 0xff));
+TCGv hi = tcg_const_i32((ret & 0x00) >> 8);
+
+tcg_gen_qemu_st_tl(lo, cpu_sp, MMU_DATA_IDX, MO_UB);
+tcg_gen_subi_tl(cpu_sp, cpu_sp, 2);
+tcg_gen_qemu_st_tl(hi, cpu_sp, MMU_DATA_IDX, MO_BEUW);
+tcg_gen_subi_tl(cpu_sp, cpu_sp, 1);
+
+tcg_temp_free_i32(lo);
+tcg_temp_free_i32(hi);
+}
+}
+
+static void gen_pop_ret(DisasContext *ctx, TCGv ret)
+{
+if (avr_feature(ctx->env, AVR_FEATURE_1_BYTE_PC)) {
+tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
+tcg_gen_qemu_ld_tl(ret, cpu_sp, MMU_DATA_IDX, MO_UB);
+} else if (avr_feature(ctx->env, AVR_FEATURE_2_BYTE_PC)) {
+tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
+tcg_gen_qemu_ld_tl(ret, cpu_sp, MMU_DATA_IDX, MO_BEUW);
+tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
+} else if (avr_feature(ctx->env, AVR_FEATURE_3_BYTE_PC)) {
+TCGv lo = tcg_temp_new_i32();
+TCGv hi = tcg_temp_new_i32();
+
+tcg_gen_addi_tl(cpu_sp, cpu_sp, 1);
+tcg_gen_qemu_ld_tl(hi, cpu_sp, MMU_DATA_IDX, MO_BEUW);
+
+tcg_gen_addi_tl(cpu_sp, cpu_sp, 2);
+tcg_gen_qemu_ld_tl(lo,

[PATCH rc6 11/30] target/avr: Add instruction translation - Arithmetic and Logic Instructions

2020-07-05 Thread Thomas Huth
From: Michael Rolnik 

This includes:
- ADD, ADC, ADIW
- SBIW, SUB, SUBI, SBC, SBCI
- AND, ANDI
- OR, ORI, EOR
- COM, NEG
- INC, DEC
- MUL, MULS, MULSU
- FMUL, FMULS, FMULSU
- DES

Signed-off-by: Michael Rolnik 
Signed-off-by: Richard Henderson 
Signed-off-by: Aleksandar Markovic 
Tested-by: Philippe Mathieu-Daudé 
Reviewed-by: Aleksandar Markovic 
Signed-off-by: Thomas Huth 
---
 target/avr/insn.decode |  76 
 target/avr/translate.c | 823 +
 2 files changed, 899 insertions(+)
 create mode 100644 target/avr/insn.decode

diff --git a/target/avr/insn.decode b/target/avr/insn.decode
new file mode 100644
index 00..43baf6d92f
--- /dev/null
+++ b/target/avr/insn.decode
@@ -0,0 +1,76 @@
+#
+# AVR instruction decode definitions.
+#
+# Copyright (c) 2019 Michael Rolnik 
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, see .
+#
+
+#
+#   regs_16_31_by_one = [16 .. 31]
+#   regs_16_23_by_one = [16 .. 23]
+#   regs_24_30_by_two = [24, 26, 28, 30]
+#   regs_00_30_by_two = [0, 2, 4, 6, 8, .. 30]
+
+%rd 4:5
+%rr 9:1 0:4
+
+%rd_a   4:4 !function=to_regs_16_31_by_one
+%rd_b   4:3 !function=to_regs_16_23_by_one
+%rd_c   4:2 !function=to_regs_24_30_by_two
+%rr_a   0:4 !function=to_regs_16_31_by_one
+%rr_b   0:3 !function=to_regs_16_23_by_one
+
+%imm6   6:2 0:4
+%imm8   8:4 0:4
+
+%io_imm 9:2 0:4
+%ldst_d_imm 13:1 10:2 0:3
+
+
+&rd_rr  rd rr
+&rd_imm rd imm
+
+@op_rd_rr    .. . . &rd_rr  rd=%rd rr=%rr
+@op_rd_imm6   .. .. &rd_imm rd=%rd_c imm=%imm6
+@op_rd_imm8     &rd_imm rd=%rd_a imm=%imm8
+@fmul     . ... . ...   &rd_rr  rd=%rd_b rr=%rr_b
+
+#
+# Arithmetic Instructions
+#
+ADD  11 . . @op_rd_rr
+ADC 0001 11 . . @op_rd_rr
+ADIW1001 0110 .. .. @op_rd_imm6
+SUB 0001 10 . . @op_rd_rr
+SUBI0101    @op_rd_imm8
+SBC  10 . . @op_rd_rr
+SBCI0100    @op_rd_imm8
+SBIW1001 0111 .. .. @op_rd_imm6
+AND 0010 00 . . @op_rd_rr
+ANDI0111    @op_rd_imm8
+OR  0010 10 . . @op_rd_rr
+ORI 0110    @op_rd_imm8
+EOR 0010 01 . . @op_rd_rr
+COM 1001 010 rd:5 
+NEG 1001 010 rd:5 0001
+INC 1001 010 rd:5 0011
+DEC 1001 010 rd:5 1010
+MUL 1001 11 . . @op_rd_rr
+MULS 0010   &rd_rr  rd=%rd_a rr=%rr_a
+MULSU    0011 0 ... 0 ...   @fmul
+FMUL 0011 0 ... 1 ...   @fmul
+FMULS    0011 1 ... 0 ...   @fmul
+FMULSU   0011 1 ... 1 ...   @fmul
+DES 1001 0100 imm:4 1011
diff --git a/target/avr/translate.c b/target/avr/translate.c
index 44ee8849f0..d81bfaa04b 100644
--- a/target/avr/translate.c
+++ b/target/avr/translate.c
@@ -129,6 +129,22 @@ struct DisasContext {
 };
 
 
+static int to_regs_16_31_by_one(DisasContext *ctx, int indx)
+{
+return 16 + (indx % 16);
+}
+
+static int to_regs_16_23_by_one(DisasContext *ctx, int indx)
+{
+return 16 + (indx % 8);
+}
+
+static int to_regs_24_30_by_two(DisasContext *ctx, int indx)
+{
+return 24 + (indx % 4) * 2;
+}
+
+
 static bool avr_have_feature(DisasContext *ctx, int feature)
 {
 if (!avr_feature(ctx->env, feature)) {
@@ -141,3 +157,810 @@ static bool avr_have_feature(DisasContext *ctx, int 
feature)
 
 static bool decode_insn(DisasContext *ctx, uint16_t insn);
 #include "decode_insn.inc.c"
+
+/*
+ * Arithmetic Instructions
+ */
+
+/*
+ * Utility functions for updating status registers:
+ *
+ *   - gen_add_CHf()
+ *   - gen_add_Vf()
+ *   - gen_sub_CHf()
+ *   - gen_sub_Vf()
+ *   - gen_NSf()
+ *   - gen_ZNSf()
+ *
+ */
+
+static void gen_add_CHf(TCGv R, TCGv Rd, TCGv Rr)
+{
+TCGv t1 = tcg_temp_new_i32();
+TCGv t2 = tcg_temp_new_i32();
+TCGv 

[PATCH rc6 30/30] target/avr: Add section into QEMU documentation

2020-07-05 Thread Thomas Huth
The new section explains basic ways of using AVR target in QEMU.

Signed-off-by: Michael Rolnik 
[thuth: Converted doc from texi to Sphinx syntax]
Signed-off-by: Thomas Huth 
---
 docs/system/target-avr.rst | 37 +
 docs/system/targets.rst|  1 +
 2 files changed, 38 insertions(+)
 create mode 100644 docs/system/target-avr.rst

diff --git a/docs/system/target-avr.rst b/docs/system/target-avr.rst
new file mode 100644
index 00..40d212a9a7
--- /dev/null
+++ b/docs/system/target-avr.rst
@@ -0,0 +1,37 @@
+.. _AVR-System-emulator:
+
+AVR System emulator
+---
+
+Use the executable ``qemu-system-avr`` to emulate a AVR 8 bit based machine.
+These can have one of the following cores: avr1, avr2, avr25, avr3, avr31,
+avr35, avr4, avr5, avr51, avr6, avrtiny, xmega2, xmega3, xmega4, xmega5,
+xmega6 and xmega7.
+
+As for now it supports few Arduino boards for educational and testing purposes.
+These boards use a ATmega controller, which model is limited to USART & 16-bit
+timer devices, enought to run FreeRTOS based applications (like
+https://github.com/seharris/qemu-avr-tests/blob/master/free-rtos/Demo/AVR_ATMega2560_GCC/demo.elf
+).
+
+Following are examples of possible usages, assuming demo.elf is compiled for
+AVR cpu
+
+ - Continuous non interrupted execution: 
+   ``qemu-system-avr -machine mega2560 -bios demo.elf``
+
+ - Continuous non interrupted execution with serial output into telnet window:
+   ``qemu-system-avr -machine mega2560 -bios demo.elf -serial
+   tcp::5678,server,nowait -nographic``
+   and then in another shell
+   ``telnet localhost 5678``
+
+ - Debugging wit GDB debugger:
+   ``qemu-system-avr -machine mega2560 -bios demo.elf -s -S``
+   and then in another shell
+   ``avr-gdb demo.elf``
+   and then within GDB shell
+   ``target remote :1234``
+
+ - Print out executed instructions:
+   ``qemu-system-avr -machine mega2560 -bios demo.elf -d in_asm``
diff --git a/docs/system/targets.rst b/docs/system/targets.rst
index 99435a3eba..560783644d 100644
--- a/docs/system/targets.rst
+++ b/docs/system/targets.rst
@@ -19,3 +19,4 @@ Contents:
target-xtensa
target-s390x
target-rx
+   target-avr
-- 
2.26.2




[PATCH rc6 28/30] tests/boot-serial: Test some Arduino boards (AVR based)

2020-07-05 Thread Thomas Huth
From: Michael Rolnik 

Print out 'T' through serial port.

The Arduino Duemilanove is based on a AVR5 CPU, while the
Arduino MEGA2560 on a AVR6 CPU.

Signed-off-by: Michael Rolnik 
Signed-off-by: Philippe Mathieu-Daudé 
[rth: Squash Arduino adjustments from f4bug]
Tested-by: Richard Henderson 
Signed-off-by: Richard Henderson 
Signed-off-by: Aleksandar Markovic 
Acked-by: Thomas Huth 
Tested-by: Philippe Mathieu-Daudé 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Thomas Huth 
---
 tests/qtest/Makefile.include   |  2 ++
 tests/qtest/boot-serial-test.c | 11 +++
 2 files changed, 13 insertions(+)

diff --git a/tests/qtest/Makefile.include b/tests/qtest/Makefile.include
index 98af2c2d93..994ac47399 100644
--- a/tests/qtest/Makefile.include
+++ b/tests/qtest/Makefile.include
@@ -66,6 +66,8 @@ check-qtest-i386-y += numa-test
 
 check-qtest-x86_64-y += $(check-qtest-i386-y)
 
+check-qtest-avr-y += boot-serial-test
+
 check-qtest-alpha-y += boot-serial-test
 check-qtest-alpha-$(CONFIG_VGA) += display-vga-test
 
diff --git a/tests/qtest/boot-serial-test.c b/tests/qtest/boot-serial-test.c
index 85a3614286..bfe7624dc6 100644
--- a/tests/qtest/boot-serial-test.c
+++ b/tests/qtest/boot-serial-test.c
@@ -17,6 +17,15 @@
 #include "libqtest.h"
 #include "libqos/libqos-spapr.h"
 
+static const uint8_t bios_avr[] = {
+0x88, 0xe0, /* ldi r24, 0x08   */
+0x80, 0x93, 0xc1, 0x00, /* sts 0x00C1, r24 ; Enable tx */
+0x86, 0xe0, /* ldi r24, 0x06   */
+0x80, 0x93, 0xc2, 0x00, /* sts 0x00C2, r24 ; Set the data bits to 8 */
+0x84, 0xe5, /* ldi r24, 0x54   */
+0x80, 0x93, 0xc6, 0x00, /* sts 0x00C6, r24 ; Output 'T' */
+};
+
 static const uint8_t kernel_mcf5208[] = {
 0x41, 0xf9, 0xfc, 0x06, 0x00, 0x00, /* lea 0xfc06,%a0 */
 0x10, 0x3c, 0x00, 0x54, /* move.b #'T',%d0 */
@@ -104,6 +113,8 @@ typedef struct testdef {
 
 static testdef_t tests[] = {
 { "alpha", "clipper", "", "PCI:" },
+{ "avr", "arduino-duemilanove", "", "T", sizeof(bios_avr), NULL, bios_avr 
},
+{ "avr", "arduino-mega-2560-v3", "", "T", sizeof(bios_avr), NULL, 
bios_avr},
 { "ppc", "ppce500", "", "U-Boot" },
 { "ppc", "40p", "-vga none -boot d", "Trying cd:," },
 { "ppc", "g3beige", "", "PowerPC,750" },
-- 
2.26.2




[PATCH rc6 23/30] hw/avr: Add support for loading ELF/raw binaries

2020-07-05 Thread Thomas Huth
From: Philippe Mathieu-Daudé 

Add avr_load_firmware() function to load firmware in ELF or
raw binary format.

[AM: Corrected the type of the variable containing e_flags]
[AM: Moved definition of e_flags conversion function to boot.c]
Suggested-by: Aleksandar Markovic 
Signed-off-by: Philippe Mathieu-Daudé 
Signed-off-by: Aleksandar Markovic 
Reviewed-by: Aleksandar Markovic 
Signed-off-by: Thomas Huth 
---
 MAINTAINERS  |   1 +
 hw/avr/Makefile.objs |   1 +
 hw/avr/boot.c| 116 +++
 hw/avr/boot.h|  33 
 include/elf.h|   4 ++
 5 files changed, 155 insertions(+)
 create mode 100644 hw/avr/Makefile.objs
 create mode 100644 hw/avr/boot.c
 create mode 100644 hw/avr/boot.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 5b5f831cd7..e8e6ddcd37 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -982,6 +982,7 @@ AVR MCUs
 M: Michael Rolnik 
 R: Sarah Harris 
 S: Maintained
+F: hw/avr/
 F: include/hw/char/avr_usart.h
 F: hw/char/avr_usart.c
 F: include/hw/timer/avr_timer16.h
diff --git a/hw/avr/Makefile.objs b/hw/avr/Makefile.objs
new file mode 100644
index 00..123f174f0e
--- /dev/null
+++ b/hw/avr/Makefile.objs
@@ -0,0 +1 @@
+obj-y += boot.o
diff --git a/hw/avr/boot.c b/hw/avr/boot.c
new file mode 100644
index 00..a82508a428
--- /dev/null
+++ b/hw/avr/boot.c
@@ -0,0 +1,116 @@
+/*
+ * AVR loader helpers
+ *
+ * Copyright (c) 2019 Philippe Mathieu-Daudé
+ *
+ * This work is licensed under the terms of the GNU GPLv2 or later.
+ * See the COPYING file in the top-level directory.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "hw/loader.h"
+#include "elf.h"
+#include "boot.h"
+#include "qemu/error-report.h"
+
+static const char *avr_elf_e_flags_to_cpu_type(uint32_t flags)
+{
+switch (flags & EF_AVR_MACH) {
+case bfd_mach_avr1:
+return AVR_CPU_TYPE_NAME("avr1");
+case bfd_mach_avr2:
+return AVR_CPU_TYPE_NAME("avr2");
+case bfd_mach_avr25:
+return AVR_CPU_TYPE_NAME("avr25");
+case bfd_mach_avr3:
+return AVR_CPU_TYPE_NAME("avr3");
+case bfd_mach_avr31:
+return AVR_CPU_TYPE_NAME("avr31");
+case bfd_mach_avr35:
+return AVR_CPU_TYPE_NAME("avr35");
+case bfd_mach_avr4:
+return AVR_CPU_TYPE_NAME("avr4");
+case bfd_mach_avr5:
+return AVR_CPU_TYPE_NAME("avr5");
+case bfd_mach_avr51:
+return AVR_CPU_TYPE_NAME("avr51");
+case bfd_mach_avr6:
+return AVR_CPU_TYPE_NAME("avr6");
+case bfd_mach_avrtiny:
+return AVR_CPU_TYPE_NAME("avrtiny");
+case bfd_mach_avrxmega2:
+return AVR_CPU_TYPE_NAME("xmega2");
+case bfd_mach_avrxmega3:
+return AVR_CPU_TYPE_NAME("xmega3");
+case bfd_mach_avrxmega4:
+return AVR_CPU_TYPE_NAME("xmega4");
+case bfd_mach_avrxmega5:
+return AVR_CPU_TYPE_NAME("xmega5");
+case bfd_mach_avrxmega6:
+return AVR_CPU_TYPE_NAME("xmega6");
+case bfd_mach_avrxmega7:
+return AVR_CPU_TYPE_NAME("xmega7");
+default:
+return NULL;
+}
+}
+
+bool avr_load_firmware(AVRCPU *cpu, MachineState *ms,
+   MemoryRegion *mr, const char *firmware)
+{
+const char *filename;
+int bytes_loaded;
+uint64_t entry;
+uint32_t e_flags;
+
+filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, firmware);
+if (filename == NULL) {
+error_report("Unable to find %s", firmware);
+return false;
+}
+
+bytes_loaded = load_elf_ram_sym(filename,
+NULL, NULL, NULL,
+&entry, NULL, NULL,
+&e_flags, 0, EM_AVR, 0, 0,
+NULL, true, NULL);
+if (bytes_loaded >= 0) {
+/* If ELF file is provided, determine CPU type reading ELF e_flags. */
+const char *elf_cpu = avr_elf_e_flags_to_cpu_type(e_flags);
+const char *mcu_cpu_type = object_get_typename(OBJECT(cpu));
+int cpu_len = strlen(mcu_cpu_type) - strlen(AVR_CPU_TYPE_SUFFIX);
+
+if (entry) {
+error_report("BIOS entry_point must be 0x "
+ "(ELF image '%s' has entry_point 0x%04" PRIx64 ")",
+ firmware, entry);
+return false;
+}
+if (!elf_cpu) {
+warn_report("Could not determine CPU type for ELF image '%s', "
+"assuming '%.*s' CPU",
+ firmware, cpu_len, mcu_cpu_type);
+return true;
+}
+if (strcmp(elf_cpu, mcu_cpu_type)) {
+error_report("Current machine: %s with '%.*s' CPU",
+ MACHINE_GET_CLASS(ms)->desc, cpu_len, mcu_cpu_type);
+error_report("ELF image '%s' is for '%.*s' CPU",
+ firmware,
+ (int)(strlen(elf_cpu) - strlen(AVR_CPU_TYPE_SUFF

[PATCH rc6 10/30] target/avr: Add instruction translation - Register definitions

2020-07-05 Thread Thomas Huth
From: Michael Rolnik 

Start implementation of instructions by adding register definitions.

Signed-off-by: Michael Rolnik 
Signed-off-by: Richard Henderson 
Signed-off-by: Aleksandar Markovic 
Tested-by: Philippe Mathieu-Daudé 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Aleksandar Markovic 
Signed-off-by: Thomas Huth 
---
 target/avr/translate.c | 143 +
 1 file changed, 143 insertions(+)
 create mode 100644 target/avr/translate.c

diff --git a/target/avr/translate.c b/target/avr/translate.c
new file mode 100644
index 00..44ee8849f0
--- /dev/null
+++ b/target/avr/translate.c
@@ -0,0 +1,143 @@
+/*
+ * QEMU AVR CPU
+ *
+ * Copyright (c) 2019 Michael Rolnik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * 
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/qemu-print.h"
+#include "tcg/tcg.h"
+#include "cpu.h"
+#include "exec/exec-all.h"
+#include "tcg/tcg-op.h"
+#include "exec/cpu_ldst.h"
+#include "exec/helper-proto.h"
+#include "exec/helper-gen.h"
+#include "exec/log.h"
+#include "exec/translator.h"
+#include "exec/gen-icount.h"
+
+/*
+ *  Define if you want a BREAK instruction translated to a breakpoint
+ *  Active debugging connection is assumed
+ *  This is for
+ *  https://github.com/seharris/qemu-avr-tests/tree/master/instruction-tests
+ *  tests
+ */
+#undef BREAKPOINT_ON_BREAK
+
+static TCGv cpu_pc;
+
+static TCGv cpu_Cf;
+static TCGv cpu_Zf;
+static TCGv cpu_Nf;
+static TCGv cpu_Vf;
+static TCGv cpu_Sf;
+static TCGv cpu_Hf;
+static TCGv cpu_Tf;
+static TCGv cpu_If;
+
+static TCGv cpu_rampD;
+static TCGv cpu_rampX;
+static TCGv cpu_rampY;
+static TCGv cpu_rampZ;
+
+static TCGv cpu_r[NUMBER_OF_CPU_REGISTERS];
+static TCGv cpu_eind;
+static TCGv cpu_sp;
+
+static TCGv cpu_skip;
+
+static const char reg_names[NUMBER_OF_CPU_REGISTERS][8] = {
+"r0",  "r1",  "r2",  "r3",  "r4",  "r5",  "r6",  "r7",
+"r8",  "r9",  "r10", "r11", "r12", "r13", "r14", "r15",
+"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+};
+#define REG(x) (cpu_r[x])
+
+enum {
+DISAS_EXIT   = DISAS_TARGET_0,  /* We want return to the cpu main loop.  */
+DISAS_LOOKUP = DISAS_TARGET_1,  /* We have a variable condition exit.  */
+DISAS_CHAIN  = DISAS_TARGET_2,  /* We have a single condition exit.  */
+};
+
+typedef struct DisasContext DisasContext;
+
+/* This is the state at translation time. */
+struct DisasContext {
+TranslationBlock *tb;
+
+CPUAVRState *env;
+CPUState *cs;
+
+target_long npc;
+uint32_t opcode;
+
+/* Routine used to access memory */
+int memidx;
+int bstate;
+int singlestep;
+
+/*
+ * some AVR instructions can make the following instruction to be skipped
+ * Let's name those instructions
+ * A   - instruction that can skip the next one
+ * B   - instruction that can be skipped. this depends on execution of 
A
+ * there are two scenarios
+ * 1. A and B belong to the same translation block
+ * 2. A is the last instruction in the translation block and B is the last
+ *
+ * following variables are used to simplify the skipping logic, they are
+ * used in the following manner (sketch)
+ *
+ * TCGLabel *skip_label = NULL;
+ * if (ctx.skip_cond != TCG_COND_NEVER) {
+ * skip_label = gen_new_label();
+ * tcg_gen_brcond_tl(skip_cond, skip_var0, skip_var1, skip_label);
+ * }
+ *
+ * if (free_skip_var0) {
+ * tcg_temp_free(skip_var0);
+ * free_skip_var0 = false;
+ * }
+ *
+ * translate(&ctx);
+ *
+ * if (skip_label) {
+ * gen_set_label(skip_label);
+ * }
+ */
+TCGv skip_var0;
+TCGv skip_var1;
+TCGCond skip_cond;
+bool free_skip_var0;
+};
+
+
+static bool avr_have_feature(DisasContext *ctx, int feature)
+{
+if (!avr_feature(ctx->env, feature)) {
+gen_helper_unsupported(cpu_env);
+ctx->bstate = DISAS_NORETURN;
+return false;
+}
+return true;
+}
+
+static bool decode_insn(DisasContext *ctx, uint16_t insn);
+#include "decode_insn.inc.c"
-- 
2.26.2




[PATCH rc6 29/30] tests/acceptance: Test the Arduino MEGA2560 board

2020-07-05 Thread Thomas Huth
From: Michael Rolnik 

The test is based on
https://github.com/seharris/qemu-avr-tests/tree/master/free-rtos/Demo
demo which. If working correctly, prints 'ABCDEFGHIJKLMNOPQRSTUVWX' out.
it also demostrates that timer and IRQ are working

As the path name demonstrates, the FreeRTOS tests target a
board based on a ATMega2560 MCU. We have one, the Arduino
MEGA2560.

Complementary documentation:

https://feilipu.me/2012/01/15/ethermega-arduino-mega-2560-and-freertos/
https://feilipu.me/2015/11/24/arduino_freertos/ (see 'Compatibility')

Signed-off-by: Michael Rolnik 
Signed-off-by: Philippe Mathieu-Daudé 
[rth: Squash multiple avocado fixups from f4bug]
Signed-off-by: Richard Henderson 
Signed-off-by: Aleksandar Markovic 
Tested-by: Richard Henderson 
Tested-by: Philippe Mathieu-Daudé 
Acked-by: Thomas Huth 
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Thomas Huth 
---
 MAINTAINERS  |  1 +
 tests/acceptance/machine_avr6.py | 50 
 2 files changed, 51 insertions(+)
 create mode 100644 tests/acceptance/machine_avr6.py

diff --git a/MAINTAINERS b/MAINTAINERS
index 79e7470f5c..8b90bb7b49 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -996,6 +996,7 @@ M: Philippe Mathieu-Daudé 
 R: Sarah Harris 
 S: Maintained
 F: hw/avr/arduino.c
+F: tests/acceptance/machine_avr6.py
 
 CRIS Machines
 -
diff --git a/tests/acceptance/machine_avr6.py b/tests/acceptance/machine_avr6.py
new file mode 100644
index 00..b644d2a81c
--- /dev/null
+++ b/tests/acceptance/machine_avr6.py
@@ -0,0 +1,50 @@
+#
+# QEMU AVR
+#
+# Copyright (c) 2019 Michael Rolnik 
+#
+# 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 .
+#
+
+import time
+
+from avocado_qemu import Test
+
+class AVR6Machine(Test):
+timeout = 5
+
+def test_freertos(self):
+"""
+:avocado: tags=arch:avr
+:avocado: tags=machine:arduino-mega-2560-v3
+"""
+"""
+
https://github.com/seharris/qemu-avr-tests/raw/master/free-rtos/Demo/AVR_ATMega2560_GCC/demo.elf
+constantly prints out 
'ABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWX'
+"""
+rom_url = ('https://github.com/seharris/qemu-avr-tests'
+   '/raw/36c3e67b8755dcf/free-rtos/Demo'
+   '/AVR_ATMega2560_GCC/demo.elf')
+rom_hash = '7eb521f511ca8f2622e0a3c5e8dd686efbb911d4'
+rom_path = self.fetch_asset(rom_url, asset_hash=rom_hash)
+
+self.vm.add_args('-bios', rom_path)
+self.vm.add_args('-nographic')
+self.vm.launch()
+
+time.sleep(2)
+self.vm.shutdown()
+
+self.assertIn('ABCDEFGHIJKLMNOPQRSTUVWXABCDEFGHIJKLMNOPQRSTUVWX',
+self.vm.get_log())
-- 
2.26.2




[PATCH rc6 09/30] target/avr: Add instruction helpers

2020-07-05 Thread Thomas Huth
From: Michael Rolnik 

Add helpers for instructions that need to interact with QEMU. Also,
add stubs for unimplemented instructions. Instructions SPM and WDR
are left unimplemented because they require emulation of complex
peripherals. The implementation of instruction SLEEP is very limited
due to the lack of peripherals to generate wake interrupts. Memory
access instructions are implemented here because some address ranges
actually refer to CPU registers.

Signed-off-by: Michael Rolnik 
Signed-off-by: Richard Henderson 
Signed-off-by: Aleksandar Markovic 
Tested-by: Philippe Mathieu-Daudé 
Reviewed-by: Aleksandar Markovic 
Signed-off-by: Thomas Huth 
---
 target/avr/helper.c | 203 
 target/avr/helper.h |  29 +++
 2 files changed, 232 insertions(+)
 create mode 100644 target/avr/helper.h

diff --git a/target/avr/helper.c b/target/avr/helper.c
index 354def2a65..c582312d66 100644
--- a/target/avr/helper.c
+++ b/target/avr/helper.c
@@ -137,3 +137,206 @@ bool avr_cpu_tlb_fill(CPUState *cs, vaddr address, int 
size,
 
 return true;
 }
+
+/*
+ *  helpers
+ */
+
+void helper_sleep(CPUAVRState *env)
+{
+CPUState *cs = env_cpu(env);
+
+cs->exception_index = EXCP_HLT;
+cpu_loop_exit(cs);
+}
+
+void helper_unsupported(CPUAVRState *env)
+{
+CPUState *cs = env_cpu(env);
+
+/*
+ *  I count not find what happens on the real platform, so
+ *  it's EXCP_DEBUG for meanwhile
+ */
+cs->exception_index = EXCP_DEBUG;
+if (qemu_loglevel_mask(LOG_UNIMP)) {
+qemu_log("UNSUPPORTED\n");
+cpu_dump_state(cs, stderr, 0);
+}
+cpu_loop_exit(cs);
+}
+
+void helper_debug(CPUAVRState *env)
+{
+CPUState *cs = env_cpu(env);
+
+cs->exception_index = EXCP_DEBUG;
+cpu_loop_exit(cs);
+}
+
+void helper_break(CPUAVRState *env)
+{
+CPUState *cs = env_cpu(env);
+
+cs->exception_index = EXCP_DEBUG;
+cpu_loop_exit(cs);
+}
+
+void helper_wdr(CPUAVRState *env)
+{
+CPUState *cs = env_cpu(env);
+
+/* WD is not implemented yet, placeholder */
+cs->exception_index = EXCP_DEBUG;
+cpu_loop_exit(cs);
+}
+
+/*
+ * This function implements IN instruction
+ *
+ * It does the following
+ * a.  if an IO register belongs to CPU, its value is read and returned
+ * b.  otherwise io address is translated to mem address and physical memory
+ * is read.
+ * c.  it caches the value for sake of SBI, SBIC, SBIS & CBI implementation
+ *
+ */
+target_ulong helper_inb(CPUAVRState *env, uint32_t port)
+{
+target_ulong data = 0;
+
+switch (port) {
+case 0x38: /* RAMPD */
+data = 0xff & (env->rampD >> 16);
+break;
+case 0x39: /* RAMPX */
+data = 0xff & (env->rampX >> 16);
+break;
+case 0x3a: /* RAMPY */
+data = 0xff & (env->rampY >> 16);
+break;
+case 0x3b: /* RAMPZ */
+data = 0xff & (env->rampZ >> 16);
+break;
+case 0x3c: /* EIND */
+data = 0xff & (env->eind >> 16);
+break;
+case 0x3d: /* SPL */
+data = env->sp & 0x00ff;
+break;
+case 0x3e: /* SPH */
+data = env->sp >> 8;
+break;
+case 0x3f: /* SREG */
+data = cpu_get_sreg(env);
+break;
+default:
+/* not a special register, pass to normal memory access */
+cpu_physical_memory_read(OFFSET_IO_REGISTERS + port, &data, 1);
+}
+
+return data;
+}
+
+/*
+ *  This function implements OUT instruction
+ *
+ *  It does the following
+ *  a.  if an IO register belongs to CPU, its value is written into the 
register
+ *  b.  otherwise io address is translated to mem address and physical memory
+ *  is written.
+ *  c.  it caches the value for sake of SBI, SBIC, SBIS & CBI implementation
+ *
+ */
+void helper_outb(CPUAVRState *env, uint32_t port, uint32_t data)
+{
+data &= 0x00ff;
+
+switch (port) {
+case 0x38: /* RAMPD */
+if (avr_feature(env, AVR_FEATURE_RAMPD)) {
+env->rampD = (data & 0xff) << 16;
+}
+break;
+case 0x39: /* RAMPX */
+if (avr_feature(env, AVR_FEATURE_RAMPX)) {
+env->rampX = (data & 0xff) << 16;
+}
+break;
+case 0x3a: /* RAMPY */
+if (avr_feature(env, AVR_FEATURE_RAMPY)) {
+env->rampY = (data & 0xff) << 16;
+}
+break;
+case 0x3b: /* RAMPZ */
+if (avr_feature(env, AVR_FEATURE_RAMPZ)) {
+env->rampZ = (data & 0xff) << 16;
+}
+break;
+case 0x3c: /* EIDN */
+env->eind = (data & 0xff) << 16;
+break;
+case 0x3d: /* SPL */
+env->sp = (env->sp & 0xff00) | (data);
+break;
+case 0x3e: /* SPH */
+if (avr_feature(env, AVR_FEATURE_2_BYTE_SP)) {
+env->sp = (env->sp & 0x00ff) | (data << 8);
+}
+break;
+case 0x3f: /* SREG */
+cpu_set_sreg(env, data);
+break;
+default:
+/* not a special register, pass to normal m

[PATCH rc6 22/30] target/avr: Register AVR support with the rest of QEMU

2020-07-05 Thread Thomas Huth
From: Michael Rolnik 

Add AVR related definitions into QEMU.

[AM: Remove word 'Atmel' from filenames and all elements of code]
Suggested-by: Aleksandar Markovic 
Signed-off-by: Michael Rolnik 
Signed-off-by: Richard Henderson 
Signed-off-by: Aleksandar Markovic 
Tested-by: Philippe Mathieu-Daudé 
Reviewed-by: Aleksandar Markovic 
Signed-off-by: Thomas Huth 
---
 arch_init.c|  2 ++
 include/disas/dis-asm.h| 19 +++
 include/sysemu/arch_init.h |  1 +
 qapi/machine.json  |  2 +-
 4 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/arch_init.c b/arch_init.c
index 8afea4748b..7fd5c09b2b 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -90,6 +90,8 @@ int graphic_depth = 32;
 #define QEMU_ARCH QEMU_ARCH_UNICORE32
 #elif defined(TARGET_XTENSA)
 #define QEMU_ARCH QEMU_ARCH_XTENSA
+#elif defined(TARGET_AVR)
+#define QEMU_ARCH QEMU_ARCH_AVR
 #endif
 
 const uint32_t arch_type = QEMU_ARCH;
diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h
index c5f9fa08ab..9856bf7921 100644
--- a/include/disas/dis-asm.h
+++ b/include/disas/dis-asm.h
@@ -211,6 +211,25 @@ enum bfd_architecture
 #define bfd_mach_m32r  0  /* backwards compatibility */
   bfd_arch_mn10200,/* Matsushita MN10200 */
   bfd_arch_mn10300,/* Matsushita MN10300 */
+  bfd_arch_avr,/* AVR microcontrollers */
+#define bfd_mach_avr1   1
+#define bfd_mach_avr2   2
+#define bfd_mach_avr25  25
+#define bfd_mach_avr3   3
+#define bfd_mach_avr31  31
+#define bfd_mach_avr35  35
+#define bfd_mach_avr4   4
+#define bfd_mach_avr5   5
+#define bfd_mach_avr51  51
+#define bfd_mach_avr6   6
+#define bfd_mach_avrtiny100
+#define bfd_mach_avrxmega1  101
+#define bfd_mach_avrxmega2  102
+#define bfd_mach_avrxmega3  103
+#define bfd_mach_avrxmega4  104
+#define bfd_mach_avrxmega5  105
+#define bfd_mach_avrxmega6  106
+#define bfd_mach_avrxmega7  107
   bfd_arch_cris,   /* Axis CRIS */
 #define bfd_mach_cris_v0_v10   255
 #define bfd_mach_cris_v32  32
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
index 71a7a285ee..54f069d491 100644
--- a/include/sysemu/arch_init.h
+++ b/include/sysemu/arch_init.h
@@ -25,6 +25,7 @@ enum {
 QEMU_ARCH_HPPA = (1 << 18),
 QEMU_ARCH_RISCV = (1 << 19),
 QEMU_ARCH_RX = (1 << 20),
+QEMU_ARCH_AVR = (1 << 21),
 
 QEMU_ARCH_NONE = (1 << 31),
 };
diff --git a/qapi/machine.json b/qapi/machine.json
index ff7b5032e3..39b6b6d089 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -25,7 +25,7 @@
 # Since: 3.0
 ##
 { 'enum' : 'SysEmuTarget',
-  'data' : [ 'aarch64', 'alpha', 'arm', 'cris', 'hppa', 'i386', 'lm32',
+  'data' : [ 'aarch64', 'alpha', 'arm', 'avr', 'cris', 'hppa', 'i386', 'lm32',
  'm68k', 'microblaze', 'microblazeel', 'mips', 'mips64',
  'mips64el', 'mipsel', 'moxie', 'nios2', 'or1k', 'ppc',
  'ppc64', 'riscv32', 'riscv64', 'rx', 's390x', 'sh4',
-- 
2.26.2




[PATCH rc6 24/30] hw/avr: Add some ATmega microcontrollers

2020-07-05 Thread Thomas Huth
From: Philippe Mathieu-Daudé 

Add some AVR microcontrollers from the ATmega family:

  - middle range: ATmega168 and ATmega328
  - high range: ATmega1280 and ATmega2560

For product comparison:
  https://www.microchip.com/wwwproducts/ProductCompare/ATmega168P/ATmega328P
  https://www.microchip.com/wwwproducts/ProductCompare/ATmega1280/ATmega2560

Datasheets:
  
http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf
  
http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2549-8-bit-AVR-Microcontroller-ATmega640-1280-1281-2560-2561_datasheet.pdf

[AM: Remove word 'Atmel' from filenames and all elements of code]
Suggested-by: Aleksandar Markovic 
Signed-off-by: Philippe Mathieu-Daudé 
Signed-off-by: Richard Henderson 
Signed-off-by: Aleksandar Markovic 
[thuth: Rebased to master, fixed object_initialize_child() calls etc.]
Signed-off-by: Thomas Huth 
---
 hw/avr/Kconfig   |   5 +
 hw/avr/Makefile.objs |   1 +
 hw/avr/atmega.c  | 458 +++
 hw/avr/atmega.h  |  48 +
 4 files changed, 512 insertions(+)
 create mode 100644 hw/avr/Kconfig
 create mode 100644 hw/avr/atmega.c
 create mode 100644 hw/avr/atmega.h

diff --git a/hw/avr/Kconfig b/hw/avr/Kconfig
new file mode 100644
index 00..9e6527e1f3
--- /dev/null
+++ b/hw/avr/Kconfig
@@ -0,0 +1,5 @@
+config AVR_ATMEGA_MCU
+bool
+select AVR_TIMER16
+select AVR_USART
+select AVR_POWER
diff --git a/hw/avr/Makefile.objs b/hw/avr/Makefile.objs
index 123f174f0e..af0fddeb13 100644
--- a/hw/avr/Makefile.objs
+++ b/hw/avr/Makefile.objs
@@ -1 +1,2 @@
 obj-y += boot.o
+obj-$(CONFIG_AVR_ATMEGA_MCU) += atmega.o
diff --git a/hw/avr/atmega.c b/hw/avr/atmega.c
new file mode 100644
index 00..72ee58bae2
--- /dev/null
+++ b/hw/avr/atmega.c
@@ -0,0 +1,458 @@
+/*
+ * QEMU ATmega MCU
+ *
+ * Copyright (c) 2019 Philippe Mathieu-Daudé
+ *
+ * This work is licensed under the terms of the GNU GPLv2 or later.
+ * See the COPYING file in the top-level directory.
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/module.h"
+#include "qemu/units.h"
+#include "qapi/error.h"
+#include "exec/memory.h"
+#include "exec/address-spaces.h"
+#include "sysemu/sysemu.h"
+#include "hw/qdev-properties.h"
+#include "hw/sysbus.h"
+#include "hw/boards.h" /* FIXME memory_region_allocate_system_memory for sram 
*/
+#include "hw/misc/unimp.h"
+#include "atmega.h"
+
+enum AtmegaPeripheral {
+POWER0, POWER1,
+GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF,
+GPIOG, GPIOH, GPIOI, GPIOJ, GPIOK, GPIOL,
+USART0, USART1, USART2, USART3,
+TIMER0, TIMER1, TIMER2, TIMER3, TIMER4, TIMER5,
+PERIFMAX
+};
+
+#define GPIO(n) (n + GPIOA)
+#define USART(n)(n + USART0)
+#define TIMER(n)(n + TIMER0)
+#define POWER(n)(n + POWER0)
+
+typedef struct {
+uint16_t addr;
+enum AtmegaPeripheral power_index;
+uint8_t power_bit;
+/* timer specific */
+uint16_t intmask_addr;
+uint16_t intflag_addr;
+bool is_timer16;
+} peripheral_cfg;
+
+typedef struct AtmegaMcuClass {
+/*< private >*/
+SysBusDeviceClass parent_class;
+/*< public >*/
+const char *uc_name;
+const char *cpu_type;
+size_t flash_size;
+size_t eeprom_size;
+size_t sram_size;
+size_t io_size;
+size_t gpio_count;
+size_t adc_count;
+const uint8_t *irq;
+const peripheral_cfg *dev;
+} AtmegaMcuClass;
+
+#define ATMEGA_MCU_CLASS(klass) \
+OBJECT_CLASS_CHECK(AtmegaMcuClass, (klass), TYPE_ATMEGA_MCU)
+#define ATMEGA_MCU_GET_CLASS(obj) \
+OBJECT_GET_CLASS(AtmegaMcuClass, (obj), TYPE_ATMEGA_MCU)
+
+static const peripheral_cfg dev168_328[PERIFMAX] = {
+[USART0]= {  0xc0, POWER0, 1 },
+[TIMER2]= {  0xb0, POWER0, 6, 0x70, 0x37, false },
+[TIMER1]= {  0x80, POWER0, 3, 0x6f, 0x36, true },
+[POWER0]= {  0x64 },
+[TIMER0]= {  0x44, POWER0, 5, 0x6e, 0x35, false },
+[GPIOD] = {  0x29 },
+[GPIOC] = {  0x26 },
+[GPIOB] = {  0x23 },
+}, dev1280_2560[PERIFMAX] = {
+[USART3]= { 0x130, POWER1, 2 },
+[TIMER5]= { 0x120, POWER1, 5, 0x73, 0x3a, true },
+[GPIOL] = { 0x109 },
+[GPIOK] = { 0x106 },
+[GPIOJ] = { 0x103 },
+[GPIOH] = { 0x100 },
+[USART2]= {  0xd0, POWER1, 1 },
+[USART1]= {  0xc8, POWER1, 0 },
+[USART0]= {  0xc0, POWER0, 1 },
+[TIMER2]= {  0xb0, POWER0, 6, 0x70, 0x37, false }, /* TODO async */
+[TIMER4]= {  0xa0, POWER1, 4, 0x72, 0x39, true },
+[TIMER3]= {  0x90, POWER1, 3, 0x71, 0x38, true },
+[TIMER1]= {  0x80, POWER0, 3, 0x6f, 0x36, true },
+[POWER1]= {  0x65 },
+[POWER0]= {  0x64 },
+[TIMER0]= {  0x44, POWER0, 5, 0x6e, 0x35, false },
+[GPIOG] = {  0x32 },
+[GPIOF] = {  0x2f },
+[GPIOE] =

  1   2   >