aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-07-09 14:57:13 +0100
committerPeter Maydell <peter.maydell@linaro.org>2018-07-09 14:57:13 +0100
commit6d1d4276aea9773af97fed651cb205aab4f1b163 (patch)
tree5fa7bf1c3d687cb75a751030a05705482630d65f
parenta98ff0ec2ba3538dd766b349518ee18d03942ed8 (diff)
parent8fad0a65582c0a6e324580f45516461e9b6aa439 (diff)
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180709' into staging
target-arm queue: * hw/net/dp8393x: don't make prom region 'nomigrate' * boards.h: Remove doc comment reference to nonexistent function * hw/sd/omap_mmc: Split 'pseudo-reset' from 'power-on-reset' * target/arm: Fix do_predset for large VL * tcg: Restrict check_size_impl to multiples of the line size * target/arm: Suppress Coverity warning for PRF * hw/timer/cmsdk-apb-timer: fix minor corner-case bugs and suppress spurious warnings when running Linux's timer driver * hw/arm/smmu-common: Fix devfn computation in smmu_iommu_mr # gpg: Signature made Mon 09 Jul 2018 14:53:38 BST # gpg: using RSA key 3C2525ED14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" # gpg: aka "Peter Maydell <pmaydell@gmail.com>" # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20180709: hw/net/dp8393x: don't make prom region 'nomigrate' boards.h: Remove doc comment reference to nonexistent function hw/sd/omap_mmc: Split 'pseudo-reset' from 'power-on-reset' target/arm: Fix do_predset for large VL tcg: Restrict check_size_impl to multiples of the line size target/arm: Suppress Coverity warning for PRF hw/timer/cmsdk-apb-timer: run or stop timer on writes to RELOAD and VALUE hw/timer/cmsdk-apb-timer: Correctly identify and set one-shot mode hw/timer/cmsdk-apb-timer: Correct ptimer policy settings ptimer: Add TRIGGER_ONLY_ON_DECREMENT policy option hw/arm/smmu-common: Fix devfn computation in smmu_iommu_mr Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--hw/arm/smmu-common.c2
-rw-r--r--hw/core/ptimer.c22
-rw-r--r--hw/net/dp8393x.c2
-rw-r--r--hw/sd/omap_mmc.c14
-rw-r--r--hw/timer/cmsdk-apb-timer.c20
-rw-r--r--include/hw/arm/smmu-common.h1
-rw-r--r--include/hw/boards.h3
-rw-r--r--include/hw/ptimer.h9
-rw-r--r--target/arm/translate-sve.c14
-rw-r--r--tcg/tcg-op-gvec.c7
-rw-r--r--tests/ptimer-test.c25
11 files changed, 91 insertions, 28 deletions
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
index 3098915d07..55c75d65d2 100644
--- a/hw/arm/smmu-common.c
+++ b/hw/arm/smmu-common.c
@@ -351,7 +351,7 @@ IOMMUMemoryRegion *smmu_iommu_mr(SMMUState *s, uint32_t sid)
bus_n = PCI_BUS_NUM(sid);
smmu_bus = smmu_find_smmu_pcibus(s, bus_n);
if (smmu_bus) {
- devfn = sid & 0x7;
+ devfn = SMMU_PCI_DEVFN(sid);
smmu = smmu_bus->pbdev[devfn];
if (smmu) {
return &smmu->iommu;
diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c
index 7221c68a98..170fd34d8b 100644
--- a/hw/core/ptimer.c
+++ b/hw/core/ptimer.c
@@ -45,8 +45,20 @@ static void ptimer_reload(ptimer_state *s, int delta_adjust)
uint32_t period_frac = s->period_frac;
uint64_t period = s->period;
uint64_t delta = s->delta;
+ bool suppress_trigger = false;
- if (delta == 0 && !(s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER)) {
+ /*
+ * Note that if delta_adjust is 0 then we must be here because of
+ * a count register write or timer start, not because of timer expiry.
+ * In that case the policy might require us to suppress the timer trigger
+ * that we would otherwise generate for a zero delta.
+ */
+ if (delta_adjust == 0 &&
+ (s->policy_mask & PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT)) {
+ suppress_trigger = true;
+ }
+ if (delta == 0 && !(s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER)
+ && !suppress_trigger) {
ptimer_trigger(s);
}
@@ -353,6 +365,14 @@ ptimer_state *ptimer_init(QEMUBH *bh, uint8_t policy_mask)
s->bh = bh;
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ptimer_tick, s);
s->policy_mask = policy_mask;
+
+ /*
+ * These two policies are incompatible -- trigger-on-decrement implies
+ * a timer trigger when the count becomes 0, but no-immediate-trigger
+ * implies a trigger when the count stops being 0.
+ */
+ assert(!((policy_mask & PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT) &&
+ (policy_mask & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER)));
return s;
}
diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index f2d2ce344c..b53fcaa8bc 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -887,7 +887,7 @@ static void dp8393x_realize(DeviceState *dev, Error **errp)
s->watchdog = timer_new_ns(QEMU_CLOCK_VIRTUAL, dp8393x_watchdog, s);
s->regs[SONIC_SR] = 0x0004; /* only revision recognized by Linux */
- memory_region_init_ram_nomigrate(&s->prom, OBJECT(dev),
+ memory_region_init_ram(&s->prom, OBJECT(dev),
"dp8393x-prom", SONIC_PROM_SIZE, &local_err);
if (local_err) {
error_propagate(errp, local_err);
diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c
index 671264b650..d0c98ca021 100644
--- a/hw/sd/omap_mmc.c
+++ b/hw/sd/omap_mmc.c
@@ -1,6 +1,8 @@
/*
* OMAP on-chip MMC/SD host emulation.
*
+ * Datasheet: TI Multimedia Card (MMC/SD/SDIO) Interface (SPRU765A)
+ *
* Copyright (C) 2006-2007 Andrzej Zaborowski <balrog@zabor.org>
*
* This program is free software; you can redistribute it and/or
@@ -278,6 +280,12 @@ static void omap_mmc_update(void *opaque)
omap_mmc_interrupts_update(s);
}
+static void omap_mmc_pseudo_reset(struct omap_mmc_s *host)
+{
+ host->status = 0;
+ host->fifo_len = 0;
+}
+
void omap_mmc_reset(struct omap_mmc_s *host)
{
host->last_cmd = 0;
@@ -286,11 +294,9 @@ void omap_mmc_reset(struct omap_mmc_s *host)
host->dw = 0;
host->mode = 0;
host->enable = 0;
- host->status = 0;
host->mask = 0;
host->cto = 0;
host->dto = 0;
- host->fifo_len = 0;
host->blen = 0;
host->blen_counter = 0;
host->nblk = 0;
@@ -305,6 +311,8 @@ void omap_mmc_reset(struct omap_mmc_s *host)
qemu_set_irq(host->coverswitch, host->cdet_state);
host->clkdiv = 0;
+ omap_mmc_pseudo_reset(host);
+
/* Since we're still using the legacy SD API the card is not plugged
* into any bus, and we must reset it manually. When omap_mmc is
* QOMified this must move into the QOM reset function.
@@ -459,7 +467,7 @@ static void omap_mmc_write(void *opaque, hwaddr offset,
if (s->dw != 0 && s->lines < 4)
printf("4-bit SD bus enabled\n");
if (!s->enable)
- omap_mmc_reset(s);
+ omap_mmc_pseudo_reset(s);
break;
case 0x10: /* MMC_STAT */
diff --git a/hw/timer/cmsdk-apb-timer.c b/hw/timer/cmsdk-apb-timer.c
index 9878746609..801d1dba74 100644
--- a/hw/timer/cmsdk-apb-timer.c
+++ b/hw/timer/cmsdk-apb-timer.c
@@ -119,17 +119,33 @@ static void cmsdk_apb_timer_write(void *opaque, hwaddr offset, uint64_t value,
}
s->ctrl = value & 0xf;
if (s->ctrl & R_CTRL_EN_MASK) {
- ptimer_run(s->timer, 0);
+ ptimer_run(s->timer, ptimer_get_limit(s->timer) == 0);
} else {
ptimer_stop(s->timer);
}
break;
case A_RELOAD:
/* Writing to reload also sets the current timer value */
+ if (!value) {
+ ptimer_stop(s->timer);
+ }
ptimer_set_limit(s->timer, value, 1);
+ if (value && (s->ctrl & R_CTRL_EN_MASK)) {
+ /*
+ * Make sure timer is running (it might have stopped if this
+ * was an expired one-shot timer)
+ */
+ ptimer_run(s->timer, 0);
+ }
break;
case A_VALUE:
+ if (!value && !ptimer_get_limit(s->timer)) {
+ ptimer_stop(s->timer);
+ }
ptimer_set_count(s->timer, value);
+ if (value && (s->ctrl & R_CTRL_EN_MASK)) {
+ ptimer_run(s->timer, ptimer_get_limit(s->timer) == 0);
+ }
break;
case A_INTSTATUS:
/* Just one bit, which is W1C. */
@@ -201,7 +217,7 @@ static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
bh = qemu_bh_new(cmsdk_apb_timer_tick, s);
s->timer = ptimer_init(bh,
PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |
- PTIMER_POLICY_NO_IMMEDIATE_TRIGGER |
+ PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT |
PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
index 50e2912a95..b07cadd0ef 100644
--- a/include/hw/arm/smmu-common.h
+++ b/include/hw/arm/smmu-common.h
@@ -24,6 +24,7 @@
#define SMMU_PCI_BUS_MAX 256
#define SMMU_PCI_DEVFN_MAX 256
+#define SMMU_PCI_DEVFN(sid) (sid & 0xFF)
#define SMMU_MAX_VA_BITS 48
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 79069ddcbe..d139a431a6 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -35,8 +35,7 @@
*
* Smaller pieces of memory (display RAM, static RAMs, etc) don't need
* to be backed via the -mem-path memory backend and can simply
- * be created via memory_region_allocate_aux_memory() or
- * memory_region_init_ram().
+ * be created via memory_region_init_ram().
*/
void memory_region_allocate_system_memory(MemoryRegion *mr, Object *owner,
const char *name,
diff --git a/include/hw/ptimer.h b/include/hw/ptimer.h
index fc4ef5cc1d..0731d9aef1 100644
--- a/include/hw/ptimer.h
+++ b/include/hw/ptimer.h
@@ -69,6 +69,15 @@
* not the one less. */
#define PTIMER_POLICY_NO_COUNTER_ROUND_DOWN (1 << 4)
+/*
+ * Starting to run with a zero counter, or setting the counter to "0" via
+ * ptimer_set_count() or ptimer_set_limit() will not trigger the timer
+ * (though it will cause a reload). Only a counter decrement to "0"
+ * will cause a trigger. Not compatible with NO_IMMEDIATE_TRIGGER;
+ * ptimer_init() will assert() that you don't set both.
+ */
+#define PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT (1 << 5)
+
/* ptimer.c */
typedef struct ptimer_state ptimer_state;
typedef void (*ptimer_cb)(void *opaque);
diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c
index c080345b9c..374051cd20 100644
--- a/target/arm/translate-sve.c
+++ b/target/arm/translate-sve.c
@@ -1438,7 +1438,7 @@ static bool do_predset(DisasContext *s, int esz, int rd, int pat, bool setflag)
setsz = numelem << esz;
lastword = word = pred_esz_masks[esz];
if (setsz % 64) {
- lastword &= ~(-1ull << (setsz % 64));
+ lastword &= MAKE_64BIT_MASK(0, setsz % 64);
}
}
@@ -1457,19 +1457,13 @@ static bool do_predset(DisasContext *s, int esz, int rd, int pat, bool setflag)
tcg_gen_gvec_dup64i(ofs, oprsz, maxsz, word);
goto done;
}
- if (oprsz * 8 == setsz + 8) {
- tcg_gen_gvec_dup64i(ofs, oprsz, maxsz, word);
- tcg_gen_movi_i64(t, 0);
- tcg_gen_st_i64(t, cpu_env, ofs + oprsz - 8);
- goto done;
- }
}
setsz /= 8;
fullsz /= 8;
tcg_gen_movi_i64(t, word);
- for (i = 0; i < setsz; i += 8) {
+ for (i = 0; i < QEMU_ALIGN_DOWN(setsz, 8); i += 8) {
tcg_gen_st_i64(t, cpu_env, ofs + i);
}
if (lastword != word) {
@@ -5164,7 +5158,7 @@ static bool trans_ST1_zpiz(DisasContext *s, arg_ST1_zpiz *a, uint32_t insn)
static bool trans_PRF(DisasContext *s, arg_PRF *a, uint32_t insn)
{
/* Prefetch is a nop within QEMU. */
- sve_access_check(s);
+ (void)sve_access_check(s);
return true;
}
@@ -5174,7 +5168,7 @@ static bool trans_PRF_rr(DisasContext *s, arg_PRF_rr *a, uint32_t insn)
return false;
}
/* Prefetch is a nop within QEMU. */
- sve_access_check(s);
+ (void)sve_access_check(s);
return true;
}
diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c
index 22db1590d5..61c25f5784 100644
--- a/tcg/tcg-op-gvec.c
+++ b/tcg/tcg-op-gvec.c
@@ -287,8 +287,11 @@ void tcg_gen_gvec_4_ptr(uint32_t dofs, uint32_t aofs, uint32_t bofs,
in units of LNSZ. This limits the expansion of inline code. */
static inline bool check_size_impl(uint32_t oprsz, uint32_t lnsz)
{
- uint32_t lnct = oprsz / lnsz;
- return lnct >= 1 && lnct <= MAX_UNROLL;
+ if (oprsz % lnsz == 0) {
+ uint32_t lnct = oprsz / lnsz;
+ return lnct >= 1 && lnct <= MAX_UNROLL;
+ }
+ return false;
}
static void expand_clr(uint32_t dofs, uint32_t maxsz);
diff --git a/tests/ptimer-test.c b/tests/ptimer-test.c
index 41488896f7..b30aad0737 100644
--- a/tests/ptimer-test.c
+++ b/tests/ptimer-test.c
@@ -208,6 +208,7 @@ static void check_periodic(gconstpointer arg)
bool no_immediate_trigger = (*policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER);
bool no_immediate_reload = (*policy & PTIMER_POLICY_NO_IMMEDIATE_RELOAD);
bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
+ bool trig_only_on_dec = (*policy & PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT);
triggered = false;
@@ -311,7 +312,7 @@ static void check_periodic(gconstpointer arg)
g_assert_cmpuint(ptimer_get_count(ptimer), ==,
no_immediate_reload ? 0 : 10);
- if (no_immediate_trigger) {
+ if (no_immediate_trigger || trig_only_on_dec) {
g_assert_false(triggered);
} else {
g_assert_true(triggered);
@@ -506,6 +507,7 @@ static void check_run_with_delta_0(gconstpointer arg)
bool no_immediate_trigger = (*policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER);
bool no_immediate_reload = (*policy & PTIMER_POLICY_NO_IMMEDIATE_RELOAD);
bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
+ bool trig_only_on_dec = (*policy & PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT);
triggered = false;
@@ -515,7 +517,7 @@ static void check_run_with_delta_0(gconstpointer arg)
g_assert_cmpuint(ptimer_get_count(ptimer), ==,
no_immediate_reload ? 0 : 99);
- if (no_immediate_trigger) {
+ if (no_immediate_trigger || trig_only_on_dec) {
g_assert_false(triggered);
} else {
g_assert_true(triggered);
@@ -563,7 +565,7 @@ static void check_run_with_delta_0(gconstpointer arg)
g_assert_cmpuint(ptimer_get_count(ptimer), ==,
no_immediate_reload ? 0 : 99);
- if (no_immediate_trigger) {
+ if (no_immediate_trigger || trig_only_on_dec) {
g_assert_false(triggered);
} else {
g_assert_true(triggered);
@@ -609,6 +611,7 @@ static void check_periodic_with_load_0(gconstpointer arg)
ptimer_state *ptimer = ptimer_init(bh, *policy);
bool continuous_trigger = (*policy & PTIMER_POLICY_CONTINUOUS_TRIGGER);
bool no_immediate_trigger = (*policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER);
+ bool trig_only_on_dec = (*policy & PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT);
triggered = false;
@@ -617,7 +620,7 @@ static void check_periodic_with_load_0(gconstpointer arg)
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
- if (no_immediate_trigger) {
+ if (no_immediate_trigger || trig_only_on_dec) {
g_assert_false(triggered);
} else {
g_assert_true(triggered);
@@ -667,6 +670,7 @@ static void check_oneshot_with_load_0(gconstpointer arg)
QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
ptimer_state *ptimer = ptimer_init(bh, *policy);
bool no_immediate_trigger = (*policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER);
+ bool trig_only_on_dec = (*policy & PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT);
triggered = false;
@@ -675,7 +679,7 @@ static void check_oneshot_with_load_0(gconstpointer arg)
g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
- if (no_immediate_trigger) {
+ if (no_immediate_trigger || trig_only_on_dec) {
g_assert_false(triggered);
} else {
g_assert_true(triggered);
@@ -725,6 +729,10 @@ static void add_ptimer_tests(uint8_t policy)
g_strlcat(policy_name, "no_counter_rounddown,", 256);
}
+ if (policy & PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT) {
+ g_strlcat(policy_name, "trigger_only_on_decrement,", 256);
+ }
+
g_test_add_data_func_full(
tmp = g_strdup_printf("/ptimer/set_count policy=%s", policy_name),
g_memdup(&policy, 1), check_set_count, g_free);
@@ -790,10 +798,15 @@ static void add_ptimer_tests(uint8_t policy)
static void add_all_ptimer_policies_comb_tests(void)
{
- int last_policy = PTIMER_POLICY_NO_COUNTER_ROUND_DOWN;
+ int last_policy = PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT;
int policy = PTIMER_POLICY_DEFAULT;
for (; policy < (last_policy << 1); policy++) {
+ if ((policy & PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT) &&
+ (policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER)) {
+ /* Incompatible policy flag settings -- don't try to test them */
+ continue;
+ }
add_ptimer_tests(policy);
}
}