1
Target-arm queue...
1
Arm queue built up to a point where it seems worth sending:
2
various bug fixes, plus RTH's refactoring in preparation for SVE.
2
3
3
thanks
4
thanks
4
-- PMM
5
-- PMM
6
7
8
The following changes since commit 0f79bfe38a2cf0f43c7ea4959da7f8ebd7858f3d:
5
9
6
The following changes since commit 735286a4f88255e1463d42ce28d8d14181fd32d4:
10
Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-2.12-pull-request' into staging (2018-01-25 09:53:53 +0000)
7
8
Merge remote-tracking branch 'remotes/juanquintela/tags/migration/20170613' into staging (2017-06-13 13:51:29 +0100)
9
11
10
are available in the git repository at:
12
are available in the git repository at:
11
13
12
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20170613
14
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180125
13
15
14
for you to fetch changes up to 252a7a6a968c279a4636a86b0559ba3a930a90b5:
16
for you to fetch changes up to 24da047af0e99a83fcc0d50b86c0f2627f7418b3:
15
17
16
hw/intc/arm_gicv3_its: Allow save/restore (2017-06-13 14:57:01 +0100)
18
pl110: Implement vertical compare/next base interrupts (2018-01-25 11:45:30 +0000)
17
19
18
----------------------------------------------------------------
20
----------------------------------------------------------------
19
target-arm queue:
21
target-arm queue:
20
* vITS: Support save/restore
22
* target/arm: Fix address truncation in 64-bit pagetable walks
21
* timer/aspeed: Fix timer enablement when reload is not set
23
* i.MX: Fix FEC/ENET receive functions
22
* aspped: add temperature sensor device
24
* target/arm: preparatory refactoring for SVE emulation
23
* timer.h: Provide better monotonic time on ARM hosts
25
* hw/intc/arm_gic: Prevent the GIC from signaling an IRQ when it's "active and pending"
24
* exynos4210: various cleanups
26
* hw/intc/arm_gic: Fix C_RPR value on idle priority
25
* exynos4210: support system poweroff
27
* hw/intc/arm_gic: Fix group priority computation for group 1 IRQs
28
* hw/intc/arm_gic: Fix the NS view of C_BPR when C_CTRL.CBPR is 1
29
* hw/arm/virt: Check that the CPU realize method succeeded
30
* sdhci: fix a NULL pointer dereference due to uninitialized AddressSpace object
31
* xilinx_spips: Correct usage of an uninitialized local variable
32
* pl110: Implement vertical compare/next base interrupts
26
33
27
----------------------------------------------------------------
34
----------------------------------------------------------------
28
Cédric Le Goater (3):
35
Ard Biesheuvel (1):
29
hw/misc: add a TMP42{1, 2, 3} device model
36
target/arm: Fix 32-bit address truncation
30
aspeed: add a temp sensor device on I2C bus 3
31
timer/aspeed: fix timer enablement when a reload is not set
32
37
33
Eric Auger (4):
38
Francisco Iglesias (1):
34
kvm-all: Pass an error object to kvm_device_access
39
xilinx_spips: Correct usage of an uninitialized local variable
35
hw/intc/arm_gicv3_its: Implement state save/restore
36
hw/intc/arm_gicv3_kvm: Implement pending table save
37
hw/intc/arm_gicv3_its: Allow save/restore
38
40
39
Krzysztof Kozlowski (9):
41
Jean-Christophe Dubois (1):
40
hw/intc/exynos4210_gic: Use more meaningful name for local variable
42
i.MX: Fix FEC/ENET receive funtions
41
hw/timer/exynos4210_mct: Fix checkpatch style errors
42
hw/timer/exynos4210_mct: Cleanup indentation and empty new lines
43
hw/timer/exynos4210_mct: Remove unused defines
44
hw/arm/exynos: Move DRAM initialization next boards
45
hw/arm/exynos: Declare local variables in some order
46
hw/arm/exynos: Use type define instead of hard-coded a9mpcore_priv string
47
hw/intc/exynos4210_gic: Constify array of combiner interrupts
48
hw/misc/exynos4210_pmu: Add support for system poweroff
49
43
50
Pranith Kumar (1):
44
Linus Walleij (1):
51
timer.h: Provide better monotonic time
45
pl110: Implement vertical compare/next base interrupts
52
46
53
hw/misc/Makefile.objs | 1 +
47
Luc MICHEL (4):
54
include/hw/arm/exynos4210.h | 5 +-
48
hw/intc/arm_gic: Prevent the GIC from signaling an IRQ when it's "active and pending"
55
include/hw/intc/arm_gicv3_its_common.h | 8 +
49
hw/intc/arm_gic: Fix C_RPR value on idle priority
56
include/migration/vmstate.h | 2 +
50
hw/intc/arm_gic: Fix group priority computation for group 1 IRQs
57
include/qemu/timer.h | 5 +-
51
hw/intc/arm_gic: Fix the NS view of C_BPR when C_CTRL.CBPR is 1
58
include/sysemu/kvm.h | 11 +-
59
hw/arm/aspeed.c | 9 +
60
hw/arm/exynos4210.c | 27 +--
61
hw/arm/exynos4_boards.c | 50 +++-
62
hw/intc/arm_gic_kvm.c | 9 +-
63
hw/intc/arm_gicv3_common.c | 1 +
64
hw/intc/arm_gicv3_its_common.c | 12 +-
65
hw/intc/arm_gicv3_its_kvm.c | 131 +++++++++--
66
hw/intc/arm_gicv3_kvm.c | 48 +++-
67
hw/intc/exynos4210_gic.c | 14 +-
68
hw/misc/exynos4210_pmu.c | 20 +-
69
hw/misc/tmp421.c | 402 +++++++++++++++++++++++++++++++++
70
hw/timer/aspeed_timer.c | 37 ++-
71
hw/timer/exynos4210_mct.c | 50 ++--
72
kvm-all.c | 14 +-
73
default-configs/arm-softmmu.mak | 1 +
74
21 files changed, 741 insertions(+), 116 deletions(-)
75
create mode 100644 hw/misc/tmp421.c
76
52
53
Peter Maydell (1):
54
hw/arm/virt: Check that the CPU realize method succeeded
55
56
Philippe Mathieu-Daudé (1):
57
sdhci: fix a NULL pointer dereference due to uninitialized AddresSpace object
58
59
Richard Henderson (11):
60
target/arm: Mark disas_set_insn_syndrome inline
61
target/arm: Use pointers in crypto helpers
62
target/arm: Use pointers in neon zip/uzp helpers
63
target/arm: Use pointers in neon tbl helper
64
target/arm: Change the type of vfp.regs
65
target/arm: Add aa{32, 64}_vfp_{dreg, qreg} helpers
66
vmstate: Add VMSTATE_UINT64_SUB_ARRAY
67
target/arm: Add ARM_FEATURE_SVE
68
target/arm: Move cpu_get_tb_cpu_state out of line
69
target/arm: Hoist store to flags output in cpu_get_tb_cpu_state
70
target/arm: Simplify fp_exception_el for user-only
71
72
include/hw/sd/sdhci.h | 1 +
73
include/migration/vmstate.h | 9 ++-
74
target/arm/cpu.h | 157 ++++++++-----------------------------
75
target/arm/helper.h | 46 +++++------
76
target/arm/translate.h | 2 +-
77
hw/arm/virt.c | 2 +-
78
hw/display/pl110.c | 30 +++++++-
79
hw/intc/arm_gic.c | 25 +++++-
80
hw/net/imx_fec.c | 8 +-
81
hw/sd/sdhci.c | 1 +
82
hw/ssi/xilinx_spips.c | 18 ++++-
83
linux-user/signal.c | 22 +++---
84
target/arm/arch_dump.c | 8 +-
85
target/arm/crypto_helper.c | 184 +++++++++++++++++---------------------------
86
target/arm/helper-a64.c | 5 +-
87
target/arm/helper.c | 164 +++++++++++++++++++++++++++++++++++----
88
target/arm/kvm32.c | 4 +-
89
target/arm/kvm64.c | 31 +++-----
90
target/arm/machine.c | 2 +-
91
target/arm/neon_helper.c | 162 ++++++++++++++++++++------------------
92
target/arm/op_helper.c | 17 ++--
93
target/arm/translate-a64.c | 100 ++++++++++++------------
94
target/arm/translate.c | 134 +++++++++++++++++---------------
95
23 files changed, 607 insertions(+), 525 deletions(-)
96
diff view generated by jsdifflib
New patch
1
From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
1
2
3
Commit ("3b39d734141a target/arm: Handle page table walk load failures
4
correctly") modified both versions of the page table walking code (i.e.,
5
arm_ldl_ptw and arm_ldq_ptw) to record the result of the translation in
6
a temporary 'data' variable so that it can be inspected before being
7
returned. However, arm_ldq_ptw() returns an uint64_t, and using a
8
temporary uint32_t variable truncates the upper bits, corrupting the
9
result. This causes problems when using more than 4 GB of memory in
10
a TCG guest. So use a uint64_t instead.
11
12
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
13
Message-id: 20180119194648.25501-1-ard.biesheuvel@linaro.org
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
target/arm/helper.c | 2 +-
18
1 file changed, 1 insertion(+), 1 deletion(-)
19
20
diff --git a/target/arm/helper.c b/target/arm/helper.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/helper.c
23
+++ b/target/arm/helper.c
24
@@ -XXX,XX +XXX,XX @@ static uint64_t arm_ldq_ptw(CPUState *cs, hwaddr addr, bool is_secure,
25
MemTxAttrs attrs = {};
26
MemTxResult result = MEMTX_OK;
27
AddressSpace *as;
28
- uint32_t data;
29
+ uint64_t data;
30
31
attrs.secure = is_secure;
32
as = arm_addressspace(cs, attrs);
33
--
34
2.7.4
35
36
diff view generated by jsdifflib
1
From: Cédric Le Goater <clg@kaod.org>
1
From: Jean-Christophe Dubois <jcd@tribudubois.net>
2
2
3
Temperatures can be changed from the monitor with :
3
The actual imx_eth_enable_rx() function is buggy.
4
4
5
    (qemu) qom-set /machine/unattached/device[2] temperature0 12000
5
It updates s->regs[ENET_RDAR] after calling qemu_flush_queued_packets().
6
6
7
Signed-off-by: Cédric Le Goater <clg@kaod.org>
7
qemu_flush_queued_packets() is going to call imx_XXX_receive() which itself
8
Message-id: 1496739230-32109-3-git-send-email-clg@kaod.org
8
is going to call imx_eth_enable_rx().
9
10
By updating s->regs[ENET_RDAR] after calling qemu_flush_queued_packets()
11
we end up updating the register with an outdated value which might
12
lead to disabling the receive function in the i.MX FEC/ENET device.
13
14
This patch change the place where the register update is done so that the
15
register value stays up to date and the receive function can keep
16
running.
17
18
Reported-by: Fyleo <fyleo45@gmail.com>
19
Tested-by: Fyleo <fyleo45@gmail.com>
20
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
21
Message-id: 20180113113445.2705-1-jcd@tribudubois.net
22
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
23
Reviewed-by: Andrey Smirnov <andrew.smirnov@gmail.com>
24
Tested-by: Andrey Smirnov <andrew.smirnov@gmail.com>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
---
26
---
12
hw/arm/aspeed.c | 9 +++++++++
27
hw/net/imx_fec.c | 8 ++------
13
1 file changed, 9 insertions(+)
28
1 file changed, 2 insertions(+), 6 deletions(-)
14
29
15
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
30
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
16
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/aspeed.c
32
--- a/hw/net/imx_fec.c
18
+++ b/hw/arm/aspeed.c
33
+++ b/hw/net/imx_fec.c
19
@@ -XXX,XX +XXX,XX @@ static void aspeed_board_init(MachineState *machine,
34
@@ -XXX,XX +XXX,XX @@ static void imx_eth_do_tx(IMXFECState *s, uint32_t index)
20
static void palmetto_bmc_i2c_init(AspeedBoardState *bmc)
35
static void imx_eth_enable_rx(IMXFECState *s, bool flush)
21
{
36
{
22
AspeedSoCState *soc = &bmc->soc;
37
IMXFECBufDesc bd;
23
+ DeviceState *dev;
38
- bool rx_ring_full;
24
39
25
/* The palmetto platform expects a ds3231 RTC but a ds1338 is
40
imx_fec_read_bd(&bd, s->rx_descriptor);
26
* enough to provide basic RTC features. Alarms will be missing */
41
27
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 0), "ds1338", 0x68);
42
- rx_ring_full = !(bd.flags & ENET_BD_E);
28
+
43
+ s->regs[ENET_RDAR] = (bd.flags & ENET_BD_E) ? ENET_RDAR_RDAR : 0;
29
+ /* add a TMP423 temperature sensor */
44
30
+ dev = i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 2),
45
- if (rx_ring_full) {
31
+ "tmp423", 0x4c);
46
+ if (!s->regs[ENET_RDAR]) {
32
+ object_property_set_int(OBJECT(dev), 31000, "temperature0", &error_abort);
47
FEC_PRINTF("RX buffer full\n");
33
+ object_property_set_int(OBJECT(dev), 28000, "temperature1", &error_abort);
48
} else if (flush) {
34
+ object_property_set_int(OBJECT(dev), 20000, "temperature2", &error_abort);
49
qemu_flush_queued_packets(qemu_get_queue(s->nic));
35
+ object_property_set_int(OBJECT(dev), 110000, "temperature3", &error_abort);
50
}
51
-
52
- s->regs[ENET_RDAR] = rx_ring_full ? 0 : ENET_RDAR_RDAR;
36
}
53
}
37
54
38
static void palmetto_bmc_init(MachineState *machine)
55
static void imx_eth_reset(DeviceState *d)
56
@@ -XXX,XX +XXX,XX @@ static void imx_eth_write(void *opaque, hwaddr offset, uint64_t value,
57
case ENET_RDAR:
58
if (s->regs[ENET_ECR] & ENET_ECR_ETHEREN) {
59
if (!s->regs[index]) {
60
- s->regs[index] = ENET_RDAR_RDAR;
61
imx_eth_enable_rx(s, true);
62
}
63
} else {
39
--
64
--
40
2.7.4
65
2.7.4
41
66
42
67
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
If it isn't used when translate.h is included,
4
we'll get a compiler Werror.
5
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
Message-id: 20180119045438.28582-2-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
target/arm/translate.h | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/target/arm/translate.h b/target/arm/translate.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate.h
19
+++ b/target/arm/translate.h
20
@@ -XXX,XX +XXX,XX @@ static inline int default_exception_el(DisasContext *s)
21
? 3 : MAX(1, s->current_el);
22
}
23
24
-static void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
25
+static inline void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
26
{
27
/* We don't need to save all of the syndrome so we mask and shift
28
* out unneeded bits to help the sleb128 encoder do a better job.
29
--
30
2.7.4
31
32
diff view generated by jsdifflib
1
From: Krzysztof Kozlowski <krzk@kernel.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
On all Exynos-based boards, the system powers down itself by driving
3
Rather than passing regnos to the helpers, pass pointers to the
4
PS_HOLD signal low - eight bit in PS_HOLD_CONTROL register of PMU.
4
vector registers directly. This eliminates the need to pass in
5
Handle writing to respective PMU register to fix power off failure:
5
the environment pointer and reduces the number of places that
6
directly access env->vfp.regs[].
6
7
7
reboot: Power down
8
Unable to poweroff system
9
shutdown: 31 output lines suppressed due to ratelimiting
10
Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000000
11
12
CPU: 0 PID: 1 Comm: shutdown Not tainted 4.11.0-rc8 #846
13
Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
14
[<c031050c>] (unwind_backtrace) from [<c030ba6c>] (show_stack+0x10/0x14)
15
[<c030ba6c>] (show_stack) from [<c05b2800>] (dump_stack+0x88/0x9c)
16
[<c05b2800>] (dump_stack) from [<c03d3140>] (panic+0xdc/0x268)
17
[<c03d3140>] (panic) from [<c0343614>] (do_exit+0xa90/0xab4)
18
[<c0343614>] (do_exit) from [<c035f2dc>] (SyS_reboot+0x164/0x1d0)
19
[<c035f2dc>] (SyS_reboot) from [<c0307c80>] (ret_fast_syscall+0x0/0x3c)
20
21
Additionally the initial value of PS_HOLD has to be changed because
22
recent Linux kernel (v4.12-rc1) uses regmap cache for this access.
23
When the register is kept at reset value, the kernel will not issue a
24
write to it. Usually the bootloader sets the eight bit of PS_HOLD high
25
so mimic its existence here.
26
27
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
28
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
29
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Message-id: 20180119045438.28582-3-richard.henderson@linaro.org
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
31
---
13
---
32
hw/misc/exynos4210_pmu.c | 20 +++++++++++++++++++-
14
target/arm/helper.h | 18 ++---
33
1 file changed, 19 insertions(+), 1 deletion(-)
15
target/arm/crypto_helper.c | 184 +++++++++++++++++----------------------------
16
target/arm/translate-a64.c | 75 ++++++++++--------
17
target/arm/translate.c | 68 +++++++++--------
18
4 files changed, 161 insertions(+), 184 deletions(-)
34
19
35
diff --git a/hw/misc/exynos4210_pmu.c b/hw/misc/exynos4210_pmu.c
20
diff --git a/target/arm/helper.h b/target/arm/helper.h
36
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/misc/exynos4210_pmu.c
22
--- a/target/arm/helper.h
38
+++ b/hw/misc/exynos4210_pmu.c
23
+++ b/target/arm/helper.h
39
@@ -XXX,XX +XXX,XX @@
24
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(neon_qzip8, void, env, i32, i32)
40
25
DEF_HELPER_3(neon_qzip16, void, env, i32, i32)
41
#include "qemu/osdep.h"
26
DEF_HELPER_3(neon_qzip32, void, env, i32, i32)
42
#include "hw/sysbus.h"
27
43
+#include "sysemu/sysemu.h"
28
-DEF_HELPER_4(crypto_aese, void, env, i32, i32, i32)
44
29
-DEF_HELPER_4(crypto_aesmc, void, env, i32, i32, i32)
45
#ifndef DEBUG_PMU
30
+DEF_HELPER_FLAGS_3(crypto_aese, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
46
#define DEBUG_PMU 0
31
+DEF_HELPER_FLAGS_3(crypto_aesmc, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
47
@@ -XXX,XX +XXX,XX @@ static const Exynos4210PmuReg exynos4210_pmu_regs[] = {
32
48
{"PAD_RETENTION_MMCB_OPTION", PAD_RETENTION_MMCB_OPTION, 0x00000000},
33
-DEF_HELPER_5(crypto_sha1_3reg, void, env, i32, i32, i32, i32)
49
{"PAD_RETENTION_EBIA_OPTION", PAD_RETENTION_EBIA_OPTION, 0x00000000},
34
-DEF_HELPER_3(crypto_sha1h, void, env, i32, i32)
50
{"PAD_RETENTION_EBIB_OPTION", PAD_RETENTION_EBIB_OPTION, 0x00000000},
35
-DEF_HELPER_3(crypto_sha1su1, void, env, i32, i32)
51
- {"PS_HOLD_CONTROL", PS_HOLD_CONTROL, 0x00005200},
36
+DEF_HELPER_FLAGS_4(crypto_sha1_3reg, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
52
+ /*
37
+DEF_HELPER_FLAGS_2(crypto_sha1h, TCG_CALL_NO_RWG, void, ptr, ptr)
53
+ * PS_HOLD_CONTROL: reset value and manually toggle high the DATA bit.
38
+DEF_HELPER_FLAGS_2(crypto_sha1su1, TCG_CALL_NO_RWG, void, ptr, ptr)
54
+ * DATA bit high, set usually by bootloader, keeps system on.
39
55
+ */
40
-DEF_HELPER_4(crypto_sha256h, void, env, i32, i32, i32)
56
+ {"PS_HOLD_CONTROL", PS_HOLD_CONTROL, 0x00005200 | BIT(8)},
41
-DEF_HELPER_4(crypto_sha256h2, void, env, i32, i32, i32)
57
{"XUSBXTI_CONFIGURATION", XUSBXTI_CONFIGURATION, 0x00000001},
42
-DEF_HELPER_3(crypto_sha256su0, void, env, i32, i32)
58
{"XUSBXTI_STATUS", XUSBXTI_STATUS, 0x00000001},
43
-DEF_HELPER_4(crypto_sha256su1, void, env, i32, i32, i32)
59
{"XUSBXTI_DURATION", XUSBXTI_DURATION, 0xFFF00000},
44
+DEF_HELPER_FLAGS_3(crypto_sha256h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
60
@@ -XXX,XX +XXX,XX @@ typedef struct Exynos4210PmuState {
45
+DEF_HELPER_FLAGS_3(crypto_sha256h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
61
uint32_t reg[PMU_NUM_OF_REGISTERS];
46
+DEF_HELPER_FLAGS_2(crypto_sha256su0, TCG_CALL_NO_RWG, void, ptr, ptr)
62
} Exynos4210PmuState;
47
+DEF_HELPER_FLAGS_3(crypto_sha256su1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
63
48
64
+static void exynos4210_pmu_poweroff(void)
49
DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
50
DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
51
diff --git a/target/arm/crypto_helper.c b/target/arm/crypto_helper.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/crypto_helper.c
54
+++ b/target/arm/crypto_helper.c
55
@@ -XXX,XX +XXX,XX @@ union CRYPTO_STATE {
56
#define CR_ST_WORD(state, i) (state.words[i])
57
#endif
58
59
-void HELPER(crypto_aese)(CPUARMState *env, uint32_t rd, uint32_t rm,
60
- uint32_t decrypt)
61
+void HELPER(crypto_aese)(void *vd, void *vm, uint32_t decrypt)
62
{
63
static uint8_t const * const sbox[2] = { AES_sbox, AES_isbox };
64
static uint8_t const * const shift[2] = { AES_shifts, AES_ishifts };
65
-
66
- union CRYPTO_STATE rk = { .l = {
67
- float64_val(env->vfp.regs[rm]),
68
- float64_val(env->vfp.regs[rm + 1])
69
- } };
70
- union CRYPTO_STATE st = { .l = {
71
- float64_val(env->vfp.regs[rd]),
72
- float64_val(env->vfp.regs[rd + 1])
73
- } };
74
+ uint64_t *rd = vd;
75
+ uint64_t *rm = vm;
76
+ union CRYPTO_STATE rk = { .l = { rm[0], rm[1] } };
77
+ union CRYPTO_STATE st = { .l = { rd[0], rd[1] } };
78
int i;
79
80
assert(decrypt < 2);
81
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_aese)(CPUARMState *env, uint32_t rd, uint32_t rm,
82
CR_ST_BYTE(st, i) = sbox[decrypt][CR_ST_BYTE(rk, shift[decrypt][i])];
83
}
84
85
- env->vfp.regs[rd] = make_float64(st.l[0]);
86
- env->vfp.regs[rd + 1] = make_float64(st.l[1]);
87
+ rd[0] = st.l[0];
88
+ rd[1] = st.l[1];
89
}
90
91
-void HELPER(crypto_aesmc)(CPUARMState *env, uint32_t rd, uint32_t rm,
92
- uint32_t decrypt)
93
+void HELPER(crypto_aesmc)(void *vd, void *vm, uint32_t decrypt)
94
{
95
static uint32_t const mc[][256] = { {
96
/* MixColumns lookup table */
97
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_aesmc)(CPUARMState *env, uint32_t rd, uint32_t rm,
98
0x92b479a7, 0x99b970a9, 0x84ae6bbb, 0x8fa362b5,
99
0xbe805d9f, 0xb58d5491, 0xa89a4f83, 0xa397468d,
100
} };
101
- union CRYPTO_STATE st = { .l = {
102
- float64_val(env->vfp.regs[rm]),
103
- float64_val(env->vfp.regs[rm + 1])
104
- } };
105
+
106
+ uint64_t *rd = vd;
107
+ uint64_t *rm = vm;
108
+ union CRYPTO_STATE st = { .l = { rm[0], rm[1] } };
109
int i;
110
111
assert(decrypt < 2);
112
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_aesmc)(CPUARMState *env, uint32_t rd, uint32_t rm,
113
rol32(mc[decrypt][CR_ST_BYTE(st, i + 3)], 24);
114
}
115
116
- env->vfp.regs[rd] = make_float64(st.l[0]);
117
- env->vfp.regs[rd + 1] = make_float64(st.l[1]);
118
+ rd[0] = st.l[0];
119
+ rd[1] = st.l[1];
120
}
121
122
/*
123
@@ -XXX,XX +XXX,XX @@ static uint32_t maj(uint32_t x, uint32_t y, uint32_t z)
124
return (x & y) | ((x | y) & z);
125
}
126
127
-void HELPER(crypto_sha1_3reg)(CPUARMState *env, uint32_t rd, uint32_t rn,
128
- uint32_t rm, uint32_t op)
129
+void HELPER(crypto_sha1_3reg)(void *vd, void *vn, void *vm, uint32_t op)
130
{
131
- union CRYPTO_STATE d = { .l = {
132
- float64_val(env->vfp.regs[rd]),
133
- float64_val(env->vfp.regs[rd + 1])
134
- } };
135
- union CRYPTO_STATE n = { .l = {
136
- float64_val(env->vfp.regs[rn]),
137
- float64_val(env->vfp.regs[rn + 1])
138
- } };
139
- union CRYPTO_STATE m = { .l = {
140
- float64_val(env->vfp.regs[rm]),
141
- float64_val(env->vfp.regs[rm + 1])
142
- } };
143
+ uint64_t *rd = vd;
144
+ uint64_t *rn = vn;
145
+ uint64_t *rm = vm;
146
+ union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
147
+ union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
148
+ union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
149
150
if (op == 3) { /* sha1su0 */
151
d.l[0] ^= d.l[1] ^ m.l[0];
152
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha1_3reg)(CPUARMState *env, uint32_t rd, uint32_t rn,
153
CR_ST_WORD(d, 0) = t;
154
}
155
}
156
- env->vfp.regs[rd] = make_float64(d.l[0]);
157
- env->vfp.regs[rd + 1] = make_float64(d.l[1]);
158
+ rd[0] = d.l[0];
159
+ rd[1] = d.l[1];
160
}
161
162
-void HELPER(crypto_sha1h)(CPUARMState *env, uint32_t rd, uint32_t rm)
163
+void HELPER(crypto_sha1h)(void *vd, void *vm)
164
{
165
- union CRYPTO_STATE m = { .l = {
166
- float64_val(env->vfp.regs[rm]),
167
- float64_val(env->vfp.regs[rm + 1])
168
- } };
169
+ uint64_t *rd = vd;
170
+ uint64_t *rm = vm;
171
+ union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
172
173
CR_ST_WORD(m, 0) = ror32(CR_ST_WORD(m, 0), 2);
174
CR_ST_WORD(m, 1) = CR_ST_WORD(m, 2) = CR_ST_WORD(m, 3) = 0;
175
176
- env->vfp.regs[rd] = make_float64(m.l[0]);
177
- env->vfp.regs[rd + 1] = make_float64(m.l[1]);
178
+ rd[0] = m.l[0];
179
+ rd[1] = m.l[1];
180
}
181
182
-void HELPER(crypto_sha1su1)(CPUARMState *env, uint32_t rd, uint32_t rm)
183
+void HELPER(crypto_sha1su1)(void *vd, void *vm)
184
{
185
- union CRYPTO_STATE d = { .l = {
186
- float64_val(env->vfp.regs[rd]),
187
- float64_val(env->vfp.regs[rd + 1])
188
- } };
189
- union CRYPTO_STATE m = { .l = {
190
- float64_val(env->vfp.regs[rm]),
191
- float64_val(env->vfp.regs[rm + 1])
192
- } };
193
+ uint64_t *rd = vd;
194
+ uint64_t *rm = vm;
195
+ union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
196
+ union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
197
198
CR_ST_WORD(d, 0) = rol32(CR_ST_WORD(d, 0) ^ CR_ST_WORD(m, 1), 1);
199
CR_ST_WORD(d, 1) = rol32(CR_ST_WORD(d, 1) ^ CR_ST_WORD(m, 2), 1);
200
CR_ST_WORD(d, 2) = rol32(CR_ST_WORD(d, 2) ^ CR_ST_WORD(m, 3), 1);
201
CR_ST_WORD(d, 3) = rol32(CR_ST_WORD(d, 3) ^ CR_ST_WORD(d, 0), 1);
202
203
- env->vfp.regs[rd] = make_float64(d.l[0]);
204
- env->vfp.regs[rd + 1] = make_float64(d.l[1]);
205
+ rd[0] = d.l[0];
206
+ rd[1] = d.l[1];
207
}
208
209
/*
210
@@ -XXX,XX +XXX,XX @@ static uint32_t s1(uint32_t x)
211
return ror32(x, 17) ^ ror32(x, 19) ^ (x >> 10);
212
}
213
214
-void HELPER(crypto_sha256h)(CPUARMState *env, uint32_t rd, uint32_t rn,
215
- uint32_t rm)
216
+void HELPER(crypto_sha256h)(void *vd, void *vn, void *vm)
217
{
218
- union CRYPTO_STATE d = { .l = {
219
- float64_val(env->vfp.regs[rd]),
220
- float64_val(env->vfp.regs[rd + 1])
221
- } };
222
- union CRYPTO_STATE n = { .l = {
223
- float64_val(env->vfp.regs[rn]),
224
- float64_val(env->vfp.regs[rn + 1])
225
- } };
226
- union CRYPTO_STATE m = { .l = {
227
- float64_val(env->vfp.regs[rm]),
228
- float64_val(env->vfp.regs[rm + 1])
229
- } };
230
+ uint64_t *rd = vd;
231
+ uint64_t *rn = vn;
232
+ uint64_t *rm = vm;
233
+ union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
234
+ union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
235
+ union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
236
int i;
237
238
for (i = 0; i < 4; i++) {
239
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha256h)(CPUARMState *env, uint32_t rd, uint32_t rn,
240
CR_ST_WORD(d, 0) = t;
241
}
242
243
- env->vfp.regs[rd] = make_float64(d.l[0]);
244
- env->vfp.regs[rd + 1] = make_float64(d.l[1]);
245
+ rd[0] = d.l[0];
246
+ rd[1] = d.l[1];
247
}
248
249
-void HELPER(crypto_sha256h2)(CPUARMState *env, uint32_t rd, uint32_t rn,
250
- uint32_t rm)
251
+void HELPER(crypto_sha256h2)(void *vd, void *vn, void *vm)
252
{
253
- union CRYPTO_STATE d = { .l = {
254
- float64_val(env->vfp.regs[rd]),
255
- float64_val(env->vfp.regs[rd + 1])
256
- } };
257
- union CRYPTO_STATE n = { .l = {
258
- float64_val(env->vfp.regs[rn]),
259
- float64_val(env->vfp.regs[rn + 1])
260
- } };
261
- union CRYPTO_STATE m = { .l = {
262
- float64_val(env->vfp.regs[rm]),
263
- float64_val(env->vfp.regs[rm + 1])
264
- } };
265
+ uint64_t *rd = vd;
266
+ uint64_t *rn = vn;
267
+ uint64_t *rm = vm;
268
+ union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
269
+ union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
270
+ union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
271
int i;
272
273
for (i = 0; i < 4; i++) {
274
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha256h2)(CPUARMState *env, uint32_t rd, uint32_t rn,
275
CR_ST_WORD(d, 0) = CR_ST_WORD(n, 3 - i) + t;
276
}
277
278
- env->vfp.regs[rd] = make_float64(d.l[0]);
279
- env->vfp.regs[rd + 1] = make_float64(d.l[1]);
280
+ rd[0] = d.l[0];
281
+ rd[1] = d.l[1];
282
}
283
284
-void HELPER(crypto_sha256su0)(CPUARMState *env, uint32_t rd, uint32_t rm)
285
+void HELPER(crypto_sha256su0)(void *vd, void *vm)
286
{
287
- union CRYPTO_STATE d = { .l = {
288
- float64_val(env->vfp.regs[rd]),
289
- float64_val(env->vfp.regs[rd + 1])
290
- } };
291
- union CRYPTO_STATE m = { .l = {
292
- float64_val(env->vfp.regs[rm]),
293
- float64_val(env->vfp.regs[rm + 1])
294
- } };
295
+ uint64_t *rd = vd;
296
+ uint64_t *rm = vm;
297
+ union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
298
+ union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
299
300
CR_ST_WORD(d, 0) += s0(CR_ST_WORD(d, 1));
301
CR_ST_WORD(d, 1) += s0(CR_ST_WORD(d, 2));
302
CR_ST_WORD(d, 2) += s0(CR_ST_WORD(d, 3));
303
CR_ST_WORD(d, 3) += s0(CR_ST_WORD(m, 0));
304
305
- env->vfp.regs[rd] = make_float64(d.l[0]);
306
- env->vfp.regs[rd + 1] = make_float64(d.l[1]);
307
+ rd[0] = d.l[0];
308
+ rd[1] = d.l[1];
309
}
310
311
-void HELPER(crypto_sha256su1)(CPUARMState *env, uint32_t rd, uint32_t rn,
312
- uint32_t rm)
313
+void HELPER(crypto_sha256su1)(void *vd, void *vn, void *vm)
314
{
315
- union CRYPTO_STATE d = { .l = {
316
- float64_val(env->vfp.regs[rd]),
317
- float64_val(env->vfp.regs[rd + 1])
318
- } };
319
- union CRYPTO_STATE n = { .l = {
320
- float64_val(env->vfp.regs[rn]),
321
- float64_val(env->vfp.regs[rn + 1])
322
- } };
323
- union CRYPTO_STATE m = { .l = {
324
- float64_val(env->vfp.regs[rm]),
325
- float64_val(env->vfp.regs[rm + 1])
326
- } };
327
+ uint64_t *rd = vd;
328
+ uint64_t *rn = vn;
329
+ uint64_t *rm = vm;
330
+ union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
331
+ union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
332
+ union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
333
334
CR_ST_WORD(d, 0) += s1(CR_ST_WORD(m, 2)) + CR_ST_WORD(n, 1);
335
CR_ST_WORD(d, 1) += s1(CR_ST_WORD(m, 3)) + CR_ST_WORD(n, 2);
336
CR_ST_WORD(d, 2) += s1(CR_ST_WORD(d, 0)) + CR_ST_WORD(n, 3);
337
CR_ST_WORD(d, 3) += s1(CR_ST_WORD(d, 1)) + CR_ST_WORD(m, 0);
338
339
- env->vfp.regs[rd] = make_float64(d.l[0]);
340
- env->vfp.regs[rd + 1] = make_float64(d.l[1]);
341
+ rd[0] = d.l[0];
342
+ rd[1] = d.l[1];
343
}
344
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
345
index XXXXXXX..XXXXXXX 100644
346
--- a/target/arm/translate-a64.c
347
+++ b/target/arm/translate-a64.c
348
@@ -XXX,XX +XXX,XX @@ typedef void NeonGenWidenFn(TCGv_i64, TCGv_i32);
349
typedef void NeonGenTwoSingleOPFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
350
typedef void NeonGenTwoDoubleOPFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr);
351
typedef void NeonGenOneOpFn(TCGv_i64, TCGv_i64);
352
-typedef void CryptoTwoOpEnvFn(TCGv_ptr, TCGv_i32, TCGv_i32);
353
-typedef void CryptoThreeOpEnvFn(TCGv_ptr, TCGv_i32, TCGv_i32, TCGv_i32);
354
+typedef void CryptoTwoOpFn(TCGv_ptr, TCGv_ptr);
355
+typedef void CryptoThreeOpIntFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
356
+typedef void CryptoThreeOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
357
358
/* initialize TCG globals. */
359
void a64_translate_init(void)
360
@@ -XXX,XX +XXX,XX @@ static inline int vec_reg_offset(DisasContext *s, int regno,
361
return offs;
362
}
363
364
+/* Return the offset info CPUARMState of the "whole" vector register Qn. */
365
+static inline int vec_full_reg_offset(DisasContext *s, int regno)
65
+{
366
+{
66
+ PRINT_DEBUG("QEMU PMU: PS_HOLD bit down, powering off\n");
367
+ assert_fp_access_checked(s);
67
+ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
368
+ return offsetof(CPUARMState, vfp.regs[regno * 2]);
68
+}
369
+}
69
+
370
+
70
static uint64_t exynos4210_pmu_read(void *opaque, hwaddr offset,
371
+/* Return a newly allocated pointer to the vector register. */
71
unsigned size)
372
+static TCGv_ptr vec_full_reg_ptr(DisasContext *s, int regno)
72
{
373
+{
73
@@ -XXX,XX +XXX,XX @@ static void exynos4210_pmu_write(void *opaque, hwaddr offset,
374
+ TCGv_ptr ret = tcg_temp_new_ptr();
74
PRINT_DEBUG_EXTEND("%s <0x%04x> <- 0x%04x\n", reg_p->name,
375
+ tcg_gen_addi_ptr(ret, cpu_env, vec_full_reg_offset(s, regno));
75
(uint32_t)offset, (uint32_t)val);
376
+ return ret;
76
s->reg[i] = val;
377
+}
77
+ if ((offset == PS_HOLD_CONTROL) && ((val & BIT(8)) == 0)) {
378
+
78
+ /*
379
/* Return the offset into CPUARMState of a slice (from
79
+ * We are interested only in setting data bit
380
* the least significant end) of FP register Qn (ie
80
+ * of PS_HOLD_CONTROL register to indicate power off request.
381
* Dn, Sn, Hn or Bn).
81
+ */
382
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_aes(DisasContext *s, uint32_t insn)
82
+ exynos4210_pmu_poweroff();
383
int rn = extract32(insn, 5, 5);
83
+ }
384
int rd = extract32(insn, 0, 5);
84
return;
385
int decrypt;
386
- TCGv_i32 tcg_rd_regno, tcg_rn_regno, tcg_decrypt;
387
- CryptoThreeOpEnvFn *genfn;
388
+ TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
389
+ TCGv_i32 tcg_decrypt;
390
+ CryptoThreeOpIntFn *genfn;
391
392
if (!arm_dc_feature(s, ARM_FEATURE_V8_AES)
393
|| size != 0) {
394
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_aes(DisasContext *s, uint32_t insn)
395
return;
396
}
397
398
- /* Note that we convert the Vx register indexes into the
399
- * index within the vfp.regs[] array, so we can share the
400
- * helper with the AArch32 instructions.
401
- */
402
- tcg_rd_regno = tcg_const_i32(rd << 1);
403
- tcg_rn_regno = tcg_const_i32(rn << 1);
404
+ tcg_rd_ptr = vec_full_reg_ptr(s, rd);
405
+ tcg_rn_ptr = vec_full_reg_ptr(s, rn);
406
tcg_decrypt = tcg_const_i32(decrypt);
407
408
- genfn(cpu_env, tcg_rd_regno, tcg_rn_regno, tcg_decrypt);
409
+ genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_decrypt);
410
411
- tcg_temp_free_i32(tcg_rd_regno);
412
- tcg_temp_free_i32(tcg_rn_regno);
413
+ tcg_temp_free_ptr(tcg_rd_ptr);
414
+ tcg_temp_free_ptr(tcg_rn_ptr);
415
tcg_temp_free_i32(tcg_decrypt);
416
}
417
418
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
419
int rm = extract32(insn, 16, 5);
420
int rn = extract32(insn, 5, 5);
421
int rd = extract32(insn, 0, 5);
422
- CryptoThreeOpEnvFn *genfn;
423
- TCGv_i32 tcg_rd_regno, tcg_rn_regno, tcg_rm_regno;
424
+ CryptoThreeOpFn *genfn;
425
+ TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
426
int feature = ARM_FEATURE_V8_SHA256;
427
428
if (size != 0) {
429
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
430
return;
431
}
432
433
- tcg_rd_regno = tcg_const_i32(rd << 1);
434
- tcg_rn_regno = tcg_const_i32(rn << 1);
435
- tcg_rm_regno = tcg_const_i32(rm << 1);
436
+ tcg_rd_ptr = vec_full_reg_ptr(s, rd);
437
+ tcg_rn_ptr = vec_full_reg_ptr(s, rn);
438
+ tcg_rm_ptr = vec_full_reg_ptr(s, rm);
439
440
if (genfn) {
441
- genfn(cpu_env, tcg_rd_regno, tcg_rn_regno, tcg_rm_regno);
442
+ genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr);
443
} else {
444
TCGv_i32 tcg_opcode = tcg_const_i32(opcode);
445
446
- gen_helper_crypto_sha1_3reg(cpu_env, tcg_rd_regno,
447
- tcg_rn_regno, tcg_rm_regno, tcg_opcode);
448
+ gen_helper_crypto_sha1_3reg(tcg_rd_ptr, tcg_rn_ptr,
449
+ tcg_rm_ptr, tcg_opcode);
450
tcg_temp_free_i32(tcg_opcode);
451
}
452
453
- tcg_temp_free_i32(tcg_rd_regno);
454
- tcg_temp_free_i32(tcg_rn_regno);
455
- tcg_temp_free_i32(tcg_rm_regno);
456
+ tcg_temp_free_ptr(tcg_rd_ptr);
457
+ tcg_temp_free_ptr(tcg_rn_ptr);
458
+ tcg_temp_free_ptr(tcg_rm_ptr);
459
}
460
461
/* Crypto two-reg SHA
462
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
463
int opcode = extract32(insn, 12, 5);
464
int rn = extract32(insn, 5, 5);
465
int rd = extract32(insn, 0, 5);
466
- CryptoTwoOpEnvFn *genfn;
467
+ CryptoTwoOpFn *genfn;
468
int feature;
469
- TCGv_i32 tcg_rd_regno, tcg_rn_regno;
470
+ TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
471
472
if (size != 0) {
473
unallocated_encoding(s);
474
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
475
return;
476
}
477
478
- tcg_rd_regno = tcg_const_i32(rd << 1);
479
- tcg_rn_regno = tcg_const_i32(rn << 1);
480
+ tcg_rd_ptr = vec_full_reg_ptr(s, rd);
481
+ tcg_rn_ptr = vec_full_reg_ptr(s, rn);
482
483
- genfn(cpu_env, tcg_rd_regno, tcg_rn_regno);
484
+ genfn(tcg_rd_ptr, tcg_rn_ptr);
485
486
- tcg_temp_free_i32(tcg_rd_regno);
487
- tcg_temp_free_i32(tcg_rn_regno);
488
+ tcg_temp_free_ptr(tcg_rd_ptr);
489
+ tcg_temp_free_ptr(tcg_rn_ptr);
490
}
491
492
/* C3.6 Data processing - SIMD, inc Crypto
493
diff --git a/target/arm/translate.c b/target/arm/translate.c
494
index XXXXXXX..XXXXXXX 100644
495
--- a/target/arm/translate.c
496
+++ b/target/arm/translate.c
497
@@ -XXX,XX +XXX,XX @@ static inline void neon_store_reg64(TCGv_i64 var, int reg)
498
tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
499
}
500
501
+static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
502
+{
503
+ TCGv_ptr ret = tcg_temp_new_ptr();
504
+ tcg_gen_addi_ptr(ret, cpu_env, vfp_reg_offset(dp, reg));
505
+ return ret;
506
+}
507
+
508
#define tcg_gen_ld_f32 tcg_gen_ld_i32
509
#define tcg_gen_ld_f64 tcg_gen_ld_i64
510
#define tcg_gen_st_f32 tcg_gen_st_i32
511
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
512
int u;
513
uint32_t imm, mask;
514
TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
515
+ TCGv_ptr ptr1, ptr2, ptr3;
516
TCGv_i64 tmp64;
517
518
/* FIXME: this access check should not take precedence over UNDEF
519
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
520
if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1)) {
521
return 1;
522
}
523
- tmp = tcg_const_i32(rd);
524
- tmp2 = tcg_const_i32(rn);
525
- tmp3 = tcg_const_i32(rm);
526
+ ptr1 = vfp_reg_ptr(true, rd);
527
+ ptr2 = vfp_reg_ptr(true, rn);
528
+ ptr3 = vfp_reg_ptr(true, rm);
529
tmp4 = tcg_const_i32(size);
530
- gen_helper_crypto_sha1_3reg(cpu_env, tmp, tmp2, tmp3, tmp4);
531
+ gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp4);
532
tcg_temp_free_i32(tmp4);
533
} else { /* SHA-256 */
534
if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA256) || size == 3) {
535
return 1;
536
}
537
- tmp = tcg_const_i32(rd);
538
- tmp2 = tcg_const_i32(rn);
539
- tmp3 = tcg_const_i32(rm);
540
+ ptr1 = vfp_reg_ptr(true, rd);
541
+ ptr2 = vfp_reg_ptr(true, rn);
542
+ ptr3 = vfp_reg_ptr(true, rm);
543
switch (size) {
544
case 0:
545
- gen_helper_crypto_sha256h(cpu_env, tmp, tmp2, tmp3);
546
+ gen_helper_crypto_sha256h(ptr1, ptr2, ptr3);
547
break;
548
case 1:
549
- gen_helper_crypto_sha256h2(cpu_env, tmp, tmp2, tmp3);
550
+ gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3);
551
break;
552
case 2:
553
- gen_helper_crypto_sha256su1(cpu_env, tmp, tmp2, tmp3);
554
+ gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3);
555
break;
556
}
557
}
558
- tcg_temp_free_i32(tmp);
559
- tcg_temp_free_i32(tmp2);
560
- tcg_temp_free_i32(tmp3);
561
+ tcg_temp_free_ptr(ptr1);
562
+ tcg_temp_free_ptr(ptr2);
563
+ tcg_temp_free_ptr(ptr3);
564
return 0;
85
}
565
}
86
reg_p++;
566
if (size == 3 && op != NEON_3R_LOGIC) {
567
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
568
|| ((rm | rd) & 1)) {
569
return 1;
570
}
571
- tmp = tcg_const_i32(rd);
572
- tmp2 = tcg_const_i32(rm);
573
+ ptr1 = vfp_reg_ptr(true, rd);
574
+ ptr2 = vfp_reg_ptr(true, rm);
575
576
/* Bit 6 is the lowest opcode bit; it distinguishes between
577
* encryption (AESE/AESMC) and decryption (AESD/AESIMC)
578
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
579
tmp3 = tcg_const_i32(extract32(insn, 6, 1));
580
581
if (op == NEON_2RM_AESE) {
582
- gen_helper_crypto_aese(cpu_env, tmp, tmp2, tmp3);
583
+ gen_helper_crypto_aese(ptr1, ptr2, tmp3);
584
} else {
585
- gen_helper_crypto_aesmc(cpu_env, tmp, tmp2, tmp3);
586
+ gen_helper_crypto_aesmc(ptr1, ptr2, tmp3);
587
}
588
- tcg_temp_free_i32(tmp);
589
- tcg_temp_free_i32(tmp2);
590
+ tcg_temp_free_ptr(ptr1);
591
+ tcg_temp_free_ptr(ptr2);
592
tcg_temp_free_i32(tmp3);
593
break;
594
case NEON_2RM_SHA1H:
595
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
596
|| ((rm | rd) & 1)) {
597
return 1;
598
}
599
- tmp = tcg_const_i32(rd);
600
- tmp2 = tcg_const_i32(rm);
601
+ ptr1 = vfp_reg_ptr(true, rd);
602
+ ptr2 = vfp_reg_ptr(true, rm);
603
604
- gen_helper_crypto_sha1h(cpu_env, tmp, tmp2);
605
+ gen_helper_crypto_sha1h(ptr1, ptr2);
606
607
- tcg_temp_free_i32(tmp);
608
- tcg_temp_free_i32(tmp2);
609
+ tcg_temp_free_ptr(ptr1);
610
+ tcg_temp_free_ptr(ptr2);
611
break;
612
case NEON_2RM_SHA1SU1:
613
if ((rm | rd) & 1) {
614
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
615
} else if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA1)) {
616
return 1;
617
}
618
- tmp = tcg_const_i32(rd);
619
- tmp2 = tcg_const_i32(rm);
620
+ ptr1 = vfp_reg_ptr(true, rd);
621
+ ptr2 = vfp_reg_ptr(true, rm);
622
if (q) {
623
- gen_helper_crypto_sha256su0(cpu_env, tmp, tmp2);
624
+ gen_helper_crypto_sha256su0(ptr1, ptr2);
625
} else {
626
- gen_helper_crypto_sha1su1(cpu_env, tmp, tmp2);
627
+ gen_helper_crypto_sha1su1(ptr1, ptr2);
628
}
629
- tcg_temp_free_i32(tmp);
630
- tcg_temp_free_i32(tmp2);
631
+ tcg_temp_free_ptr(ptr1);
632
+ tcg_temp_free_ptr(ptr2);
633
break;
634
default:
635
elementwise:
87
--
636
--
88
2.7.4
637
2.7.4
89
638
90
639
diff view generated by jsdifflib
1
From: Pranith Kumar <bobby.prani@gmail.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Tested and confirmed that the stretch i386 debian qcow2 image on a
3
Rather than passing regnos to the helpers, pass pointers to the
4
raspberry pi 2 works.
4
vector registers directly. This eliminates the need to pass in
5
the environment pointer and reduces the number of places that
6
directly access env->vfp.regs[].
5
7
6
Fixes: LP#: 893208 <https://bugs.launchpad.net/qemu/+bug/893208/>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Pranith Kumar <bobby.prani@gmail.com>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Message-id: 20170418191817.10430-1-bobby.prani@gmail.com
11
Message-id: 20180119045438.28582-4-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
13
---
12
include/qemu/timer.h | 5 ++---
14
target/arm/helper.h | 20 +++---
13
1 file changed, 2 insertions(+), 3 deletions(-)
15
target/arm/neon_helper.c | 162 +++++++++++++++++++++++++----------------------
16
target/arm/translate.c | 42 ++++++------
17
3 files changed, 120 insertions(+), 104 deletions(-)
14
18
15
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
19
diff --git a/target/arm/helper.h b/target/arm/helper.h
16
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
17
--- a/include/qemu/timer.h
21
--- a/target/arm/helper.h
18
+++ b/include/qemu/timer.h
22
+++ b/target/arm/helper.h
19
@@ -XXX,XX +XXX,XX @@ static inline int64_t cpu_get_host_ticks(void)
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(iwmmxt_muladdsl, i64, i64, i32, i32)
20
/* The host CPU doesn't have an easily accessible cycle counter.
24
DEF_HELPER_3(iwmmxt_muladdsw, i64, i64, i32, i32)
21
Just return a monotonically increasing value. This will be
25
DEF_HELPER_3(iwmmxt_muladdswl, i64, i64, i32, i32)
22
totally wrong, but hopefully better than nothing. */
26
23
-static inline int64_t cpu_get_host_ticks (void)
27
-DEF_HELPER_3(neon_unzip8, void, env, i32, i32)
24
+static inline int64_t cpu_get_host_ticks(void)
28
-DEF_HELPER_3(neon_unzip16, void, env, i32, i32)
25
{
29
-DEF_HELPER_3(neon_qunzip8, void, env, i32, i32)
26
- static int64_t ticks = 0;
30
-DEF_HELPER_3(neon_qunzip16, void, env, i32, i32)
27
- return ticks++;
31
-DEF_HELPER_3(neon_qunzip32, void, env, i32, i32)
28
+ return get_clock();
32
-DEF_HELPER_3(neon_zip8, void, env, i32, i32)
29
}
33
-DEF_HELPER_3(neon_zip16, void, env, i32, i32)
30
#endif
34
-DEF_HELPER_3(neon_qzip8, void, env, i32, i32)
35
-DEF_HELPER_3(neon_qzip16, void, env, i32, i32)
36
-DEF_HELPER_3(neon_qzip32, void, env, i32, i32)
37
+DEF_HELPER_FLAGS_2(neon_unzip8, TCG_CALL_NO_RWG, void, ptr, ptr)
38
+DEF_HELPER_FLAGS_2(neon_unzip16, TCG_CALL_NO_RWG, void, ptr, ptr)
39
+DEF_HELPER_FLAGS_2(neon_qunzip8, TCG_CALL_NO_RWG, void, ptr, ptr)
40
+DEF_HELPER_FLAGS_2(neon_qunzip16, TCG_CALL_NO_RWG, void, ptr, ptr)
41
+DEF_HELPER_FLAGS_2(neon_qunzip32, TCG_CALL_NO_RWG, void, ptr, ptr)
42
+DEF_HELPER_FLAGS_2(neon_zip8, TCG_CALL_NO_RWG, void, ptr, ptr)
43
+DEF_HELPER_FLAGS_2(neon_zip16, TCG_CALL_NO_RWG, void, ptr, ptr)
44
+DEF_HELPER_FLAGS_2(neon_qzip8, TCG_CALL_NO_RWG, void, ptr, ptr)
45
+DEF_HELPER_FLAGS_2(neon_qzip16, TCG_CALL_NO_RWG, void, ptr, ptr)
46
+DEF_HELPER_FLAGS_2(neon_qzip32, TCG_CALL_NO_RWG, void, ptr, ptr)
47
48
DEF_HELPER_FLAGS_3(crypto_aese, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
49
DEF_HELPER_FLAGS_3(crypto_aesmc, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
50
diff --git a/target/arm/neon_helper.c b/target/arm/neon_helper.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/neon_helper.c
53
+++ b/target/arm/neon_helper.c
54
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(neon_acgt_f64)(uint64_t a, uint64_t b, void *fpstp)
55
56
#define ELEM(V, N, SIZE) (((V) >> ((N) * (SIZE))) & ((1ull << (SIZE)) - 1))
57
58
-void HELPER(neon_qunzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
59
+void HELPER(neon_qunzip8)(void *vd, void *vm)
60
{
61
- uint64_t zm0 = float64_val(env->vfp.regs[rm]);
62
- uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
63
- uint64_t zd0 = float64_val(env->vfp.regs[rd]);
64
- uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
65
+ uint64_t *rd = vd, *rm = vm;
66
+ uint64_t zd0 = rd[0], zd1 = rd[1];
67
+ uint64_t zm0 = rm[0], zm1 = rm[1];
68
+
69
uint64_t d0 = ELEM(zd0, 0, 8) | (ELEM(zd0, 2, 8) << 8)
70
| (ELEM(zd0, 4, 8) << 16) | (ELEM(zd0, 6, 8) << 24)
71
| (ELEM(zd1, 0, 8) << 32) | (ELEM(zd1, 2, 8) << 40)
72
@@ -XXX,XX +XXX,XX @@ void HELPER(neon_qunzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
73
| (ELEM(zm0, 5, 8) << 16) | (ELEM(zm0, 7, 8) << 24)
74
| (ELEM(zm1, 1, 8) << 32) | (ELEM(zm1, 3, 8) << 40)
75
| (ELEM(zm1, 5, 8) << 48) | (ELEM(zm1, 7, 8) << 56);
76
- env->vfp.regs[rm] = make_float64(m0);
77
- env->vfp.regs[rm + 1] = make_float64(m1);
78
- env->vfp.regs[rd] = make_float64(d0);
79
- env->vfp.regs[rd + 1] = make_float64(d1);
80
+
81
+ rm[0] = m0;
82
+ rm[1] = m1;
83
+ rd[0] = d0;
84
+ rd[1] = d1;
85
}
86
87
-void HELPER(neon_qunzip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
88
+void HELPER(neon_qunzip16)(void *vd, void *vm)
89
{
90
- uint64_t zm0 = float64_val(env->vfp.regs[rm]);
91
- uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
92
- uint64_t zd0 = float64_val(env->vfp.regs[rd]);
93
- uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
94
+ uint64_t *rd = vd, *rm = vm;
95
+ uint64_t zd0 = rd[0], zd1 = rd[1];
96
+ uint64_t zm0 = rm[0], zm1 = rm[1];
97
+
98
uint64_t d0 = ELEM(zd0, 0, 16) | (ELEM(zd0, 2, 16) << 16)
99
| (ELEM(zd1, 0, 16) << 32) | (ELEM(zd1, 2, 16) << 48);
100
uint64_t d1 = ELEM(zm0, 0, 16) | (ELEM(zm0, 2, 16) << 16)
101
@@ -XXX,XX +XXX,XX @@ void HELPER(neon_qunzip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
102
| (ELEM(zd1, 1, 16) << 32) | (ELEM(zd1, 3, 16) << 48);
103
uint64_t m1 = ELEM(zm0, 1, 16) | (ELEM(zm0, 3, 16) << 16)
104
| (ELEM(zm1, 1, 16) << 32) | (ELEM(zm1, 3, 16) << 48);
105
- env->vfp.regs[rm] = make_float64(m0);
106
- env->vfp.regs[rm + 1] = make_float64(m1);
107
- env->vfp.regs[rd] = make_float64(d0);
108
- env->vfp.regs[rd + 1] = make_float64(d1);
109
+
110
+ rm[0] = m0;
111
+ rm[1] = m1;
112
+ rd[0] = d0;
113
+ rd[1] = d1;
114
}
115
116
-void HELPER(neon_qunzip32)(CPUARMState *env, uint32_t rd, uint32_t rm)
117
+void HELPER(neon_qunzip32)(void *vd, void *vm)
118
{
119
- uint64_t zm0 = float64_val(env->vfp.regs[rm]);
120
- uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
121
- uint64_t zd0 = float64_val(env->vfp.regs[rd]);
122
- uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
123
+ uint64_t *rd = vd, *rm = vm;
124
+ uint64_t zd0 = rd[0], zd1 = rd[1];
125
+ uint64_t zm0 = rm[0], zm1 = rm[1];
126
+
127
uint64_t d0 = ELEM(zd0, 0, 32) | (ELEM(zd1, 0, 32) << 32);
128
uint64_t d1 = ELEM(zm0, 0, 32) | (ELEM(zm1, 0, 32) << 32);
129
uint64_t m0 = ELEM(zd0, 1, 32) | (ELEM(zd1, 1, 32) << 32);
130
uint64_t m1 = ELEM(zm0, 1, 32) | (ELEM(zm1, 1, 32) << 32);
131
- env->vfp.regs[rm] = make_float64(m0);
132
- env->vfp.regs[rm + 1] = make_float64(m1);
133
- env->vfp.regs[rd] = make_float64(d0);
134
- env->vfp.regs[rd + 1] = make_float64(d1);
135
+
136
+ rm[0] = m0;
137
+ rm[1] = m1;
138
+ rd[0] = d0;
139
+ rd[1] = d1;
140
}
141
142
-void HELPER(neon_unzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
143
+void HELPER(neon_unzip8)(void *vd, void *vm)
144
{
145
- uint64_t zm = float64_val(env->vfp.regs[rm]);
146
- uint64_t zd = float64_val(env->vfp.regs[rd]);
147
+ uint64_t *rd = vd, *rm = vm;
148
+ uint64_t zd = rd[0], zm = rm[0];
149
+
150
uint64_t d0 = ELEM(zd, 0, 8) | (ELEM(zd, 2, 8) << 8)
151
| (ELEM(zd, 4, 8) << 16) | (ELEM(zd, 6, 8) << 24)
152
| (ELEM(zm, 0, 8) << 32) | (ELEM(zm, 2, 8) << 40)
153
@@ -XXX,XX +XXX,XX @@ void HELPER(neon_unzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
154
| (ELEM(zd, 5, 8) << 16) | (ELEM(zd, 7, 8) << 24)
155
| (ELEM(zm, 1, 8) << 32) | (ELEM(zm, 3, 8) << 40)
156
| (ELEM(zm, 5, 8) << 48) | (ELEM(zm, 7, 8) << 56);
157
- env->vfp.regs[rm] = make_float64(m0);
158
- env->vfp.regs[rd] = make_float64(d0);
159
+
160
+ rm[0] = m0;
161
+ rd[0] = d0;
162
}
163
164
-void HELPER(neon_unzip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
165
+void HELPER(neon_unzip16)(void *vd, void *vm)
166
{
167
- uint64_t zm = float64_val(env->vfp.regs[rm]);
168
- uint64_t zd = float64_val(env->vfp.regs[rd]);
169
+ uint64_t *rd = vd, *rm = vm;
170
+ uint64_t zd = rd[0], zm = rm[0];
171
+
172
uint64_t d0 = ELEM(zd, 0, 16) | (ELEM(zd, 2, 16) << 16)
173
| (ELEM(zm, 0, 16) << 32) | (ELEM(zm, 2, 16) << 48);
174
uint64_t m0 = ELEM(zd, 1, 16) | (ELEM(zd, 3, 16) << 16)
175
| (ELEM(zm, 1, 16) << 32) | (ELEM(zm, 3, 16) << 48);
176
- env->vfp.regs[rm] = make_float64(m0);
177
- env->vfp.regs[rd] = make_float64(d0);
178
+
179
+ rm[0] = m0;
180
+ rd[0] = d0;
181
}
182
183
-void HELPER(neon_qzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
184
+void HELPER(neon_qzip8)(void *vd, void *vm)
185
{
186
- uint64_t zm0 = float64_val(env->vfp.regs[rm]);
187
- uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
188
- uint64_t zd0 = float64_val(env->vfp.regs[rd]);
189
- uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
190
+ uint64_t *rd = vd, *rm = vm;
191
+ uint64_t zd0 = rd[0], zd1 = rd[1];
192
+ uint64_t zm0 = rm[0], zm1 = rm[1];
193
+
194
uint64_t d0 = ELEM(zd0, 0, 8) | (ELEM(zm0, 0, 8) << 8)
195
| (ELEM(zd0, 1, 8) << 16) | (ELEM(zm0, 1, 8) << 24)
196
| (ELEM(zd0, 2, 8) << 32) | (ELEM(zm0, 2, 8) << 40)
197
@@ -XXX,XX +XXX,XX @@ void HELPER(neon_qzip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
198
| (ELEM(zd1, 5, 8) << 16) | (ELEM(zm1, 5, 8) << 24)
199
| (ELEM(zd1, 6, 8) << 32) | (ELEM(zm1, 6, 8) << 40)
200
| (ELEM(zd1, 7, 8) << 48) | (ELEM(zm1, 7, 8) << 56);
201
- env->vfp.regs[rm] = make_float64(m0);
202
- env->vfp.regs[rm + 1] = make_float64(m1);
203
- env->vfp.regs[rd] = make_float64(d0);
204
- env->vfp.regs[rd + 1] = make_float64(d1);
205
+
206
+ rm[0] = m0;
207
+ rm[1] = m1;
208
+ rd[0] = d0;
209
+ rd[1] = d1;
210
}
211
212
-void HELPER(neon_qzip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
213
+void HELPER(neon_qzip16)(void *vd, void *vm)
214
{
215
- uint64_t zm0 = float64_val(env->vfp.regs[rm]);
216
- uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
217
- uint64_t zd0 = float64_val(env->vfp.regs[rd]);
218
- uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
219
+ uint64_t *rd = vd, *rm = vm;
220
+ uint64_t zd0 = rd[0], zd1 = rd[1];
221
+ uint64_t zm0 = rm[0], zm1 = rm[1];
222
+
223
uint64_t d0 = ELEM(zd0, 0, 16) | (ELEM(zm0, 0, 16) << 16)
224
| (ELEM(zd0, 1, 16) << 32) | (ELEM(zm0, 1, 16) << 48);
225
uint64_t d1 = ELEM(zd0, 2, 16) | (ELEM(zm0, 2, 16) << 16)
226
@@ -XXX,XX +XXX,XX @@ void HELPER(neon_qzip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
227
| (ELEM(zd1, 1, 16) << 32) | (ELEM(zm1, 1, 16) << 48);
228
uint64_t m1 = ELEM(zd1, 2, 16) | (ELEM(zm1, 2, 16) << 16)
229
| (ELEM(zd1, 3, 16) << 32) | (ELEM(zm1, 3, 16) << 48);
230
- env->vfp.regs[rm] = make_float64(m0);
231
- env->vfp.regs[rm + 1] = make_float64(m1);
232
- env->vfp.regs[rd] = make_float64(d0);
233
- env->vfp.regs[rd + 1] = make_float64(d1);
234
+
235
+ rm[0] = m0;
236
+ rm[1] = m1;
237
+ rd[0] = d0;
238
+ rd[1] = d1;
239
}
240
241
-void HELPER(neon_qzip32)(CPUARMState *env, uint32_t rd, uint32_t rm)
242
+void HELPER(neon_qzip32)(void *vd, void *vm)
243
{
244
- uint64_t zm0 = float64_val(env->vfp.regs[rm]);
245
- uint64_t zm1 = float64_val(env->vfp.regs[rm + 1]);
246
- uint64_t zd0 = float64_val(env->vfp.regs[rd]);
247
- uint64_t zd1 = float64_val(env->vfp.regs[rd + 1]);
248
+ uint64_t *rd = vd, *rm = vm;
249
+ uint64_t zd0 = rd[0], zd1 = rd[1];
250
+ uint64_t zm0 = rm[0], zm1 = rm[1];
251
+
252
uint64_t d0 = ELEM(zd0, 0, 32) | (ELEM(zm0, 0, 32) << 32);
253
uint64_t d1 = ELEM(zd0, 1, 32) | (ELEM(zm0, 1, 32) << 32);
254
uint64_t m0 = ELEM(zd1, 0, 32) | (ELEM(zm1, 0, 32) << 32);
255
uint64_t m1 = ELEM(zd1, 1, 32) | (ELEM(zm1, 1, 32) << 32);
256
- env->vfp.regs[rm] = make_float64(m0);
257
- env->vfp.regs[rm + 1] = make_float64(m1);
258
- env->vfp.regs[rd] = make_float64(d0);
259
- env->vfp.regs[rd + 1] = make_float64(d1);
260
+
261
+ rm[0] = m0;
262
+ rm[1] = m1;
263
+ rd[0] = d0;
264
+ rd[1] = d1;
265
}
266
267
-void HELPER(neon_zip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
268
+void HELPER(neon_zip8)(void *vd, void *vm)
269
{
270
- uint64_t zm = float64_val(env->vfp.regs[rm]);
271
- uint64_t zd = float64_val(env->vfp.regs[rd]);
272
+ uint64_t *rd = vd, *rm = vm;
273
+ uint64_t zd = rd[0], zm = rm[0];
274
+
275
uint64_t d0 = ELEM(zd, 0, 8) | (ELEM(zm, 0, 8) << 8)
276
| (ELEM(zd, 1, 8) << 16) | (ELEM(zm, 1, 8) << 24)
277
| (ELEM(zd, 2, 8) << 32) | (ELEM(zm, 2, 8) << 40)
278
@@ -XXX,XX +XXX,XX @@ void HELPER(neon_zip8)(CPUARMState *env, uint32_t rd, uint32_t rm)
279
| (ELEM(zd, 5, 8) << 16) | (ELEM(zm, 5, 8) << 24)
280
| (ELEM(zd, 6, 8) << 32) | (ELEM(zm, 6, 8) << 40)
281
| (ELEM(zd, 7, 8) << 48) | (ELEM(zm, 7, 8) << 56);
282
- env->vfp.regs[rm] = make_float64(m0);
283
- env->vfp.regs[rd] = make_float64(d0);
284
+
285
+ rm[0] = m0;
286
+ rd[0] = d0;
287
}
288
289
-void HELPER(neon_zip16)(CPUARMState *env, uint32_t rd, uint32_t rm)
290
+void HELPER(neon_zip16)(void *vd, void *vm)
291
{
292
- uint64_t zm = float64_val(env->vfp.regs[rm]);
293
- uint64_t zd = float64_val(env->vfp.regs[rd]);
294
+ uint64_t *rd = vd, *rm = vm;
295
+ uint64_t zd = rd[0], zm = rm[0];
296
+
297
uint64_t d0 = ELEM(zd, 0, 16) | (ELEM(zm, 0, 16) << 16)
298
| (ELEM(zd, 1, 16) << 32) | (ELEM(zm, 1, 16) << 48);
299
uint64_t m0 = ELEM(zd, 2, 16) | (ELEM(zm, 2, 16) << 16)
300
| (ELEM(zd, 3, 16) << 32) | (ELEM(zm, 3, 16) << 48);
301
- env->vfp.regs[rm] = make_float64(m0);
302
- env->vfp.regs[rd] = make_float64(d0);
303
+
304
+ rm[0] = m0;
305
+ rd[0] = d0;
306
}
307
308
/* Helper function for 64 bit polynomial multiply case:
309
diff --git a/target/arm/translate.c b/target/arm/translate.c
310
index XXXXXXX..XXXXXXX 100644
311
--- a/target/arm/translate.c
312
+++ b/target/arm/translate.c
313
@@ -XXX,XX +XXX,XX @@ static inline TCGv_i32 neon_get_scalar(int size, int reg)
314
315
static int gen_neon_unzip(int rd, int rm, int size, int q)
316
{
317
- TCGv_i32 tmp, tmp2;
318
+ TCGv_ptr pd, pm;
319
+
320
if (!q && size == 2) {
321
return 1;
322
}
323
- tmp = tcg_const_i32(rd);
324
- tmp2 = tcg_const_i32(rm);
325
+ pd = vfp_reg_ptr(true, rd);
326
+ pm = vfp_reg_ptr(true, rm);
327
if (q) {
328
switch (size) {
329
case 0:
330
- gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
331
+ gen_helper_neon_qunzip8(pd, pm);
332
break;
333
case 1:
334
- gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
335
+ gen_helper_neon_qunzip16(pd, pm);
336
break;
337
case 2:
338
- gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
339
+ gen_helper_neon_qunzip32(pd, pm);
340
break;
341
default:
342
abort();
343
@@ -XXX,XX +XXX,XX @@ static int gen_neon_unzip(int rd, int rm, int size, int q)
344
} else {
345
switch (size) {
346
case 0:
347
- gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
348
+ gen_helper_neon_unzip8(pd, pm);
349
break;
350
case 1:
351
- gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
352
+ gen_helper_neon_unzip16(pd, pm);
353
break;
354
default:
355
abort();
356
}
357
}
358
- tcg_temp_free_i32(tmp);
359
- tcg_temp_free_i32(tmp2);
360
+ tcg_temp_free_ptr(pd);
361
+ tcg_temp_free_ptr(pm);
362
return 0;
363
}
364
365
static int gen_neon_zip(int rd, int rm, int size, int q)
366
{
367
- TCGv_i32 tmp, tmp2;
368
+ TCGv_ptr pd, pm;
369
+
370
if (!q && size == 2) {
371
return 1;
372
}
373
- tmp = tcg_const_i32(rd);
374
- tmp2 = tcg_const_i32(rm);
375
+ pd = vfp_reg_ptr(true, rd);
376
+ pm = vfp_reg_ptr(true, rm);
377
if (q) {
378
switch (size) {
379
case 0:
380
- gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
381
+ gen_helper_neon_qzip8(pd, pm);
382
break;
383
case 1:
384
- gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
385
+ gen_helper_neon_qzip16(pd, pm);
386
break;
387
case 2:
388
- gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
389
+ gen_helper_neon_qzip32(pd, pm);
390
break;
391
default:
392
abort();
393
@@ -XXX,XX +XXX,XX @@ static int gen_neon_zip(int rd, int rm, int size, int q)
394
} else {
395
switch (size) {
396
case 0:
397
- gen_helper_neon_zip8(cpu_env, tmp, tmp2);
398
+ gen_helper_neon_zip8(pd, pm);
399
break;
400
case 1:
401
- gen_helper_neon_zip16(cpu_env, tmp, tmp2);
402
+ gen_helper_neon_zip16(pd, pm);
403
break;
404
default:
405
abort();
406
}
407
}
408
- tcg_temp_free_i32(tmp);
409
- tcg_temp_free_i32(tmp2);
410
+ tcg_temp_free_ptr(pd);
411
+ tcg_temp_free_ptr(pm);
412
return 0;
413
}
31
414
32
--
415
--
33
2.7.4
416
2.7.4
34
417
35
418
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Rather than passing a regno to the helper, pass pointers to the
4
vector register directly. This eliminates the need to pass in
5
the environment pointer and reduces the number of places that
6
directly access env->vfp.regs[].
7
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20180119045438.28582-5-richard.henderson@linaro.org
11
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
target/arm/helper.h | 2 +-
15
target/arm/op_helper.c | 17 +++++++----------
16
target/arm/translate.c | 8 ++++----
17
3 files changed, 12 insertions(+), 15 deletions(-)
18
19
diff --git a/target/arm/helper.h b/target/arm/helper.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/helper.h
22
+++ b/target/arm/helper.h
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(rsqrte_f32, TCG_CALL_NO_RWG, f32, f32, ptr)
24
DEF_HELPER_FLAGS_2(rsqrte_f64, TCG_CALL_NO_RWG, f64, f64, ptr)
25
DEF_HELPER_2(recpe_u32, i32, i32, ptr)
26
DEF_HELPER_FLAGS_2(rsqrte_u32, TCG_CALL_NO_RWG, i32, i32, ptr)
27
-DEF_HELPER_5(neon_tbl, i32, env, i32, i32, i32, i32)
28
+DEF_HELPER_FLAGS_4(neon_tbl, TCG_CALL_NO_RWG, i32, i32, i32, ptr, i32)
29
30
DEF_HELPER_3(shl_cc, i32, env, i32, i32)
31
DEF_HELPER_3(shr_cc, i32, env, i32, i32)
32
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/op_helper.c
35
+++ b/target/arm/op_helper.c
36
@@ -XXX,XX +XXX,XX @@ static int exception_target_el(CPUARMState *env)
37
return target_el;
38
}
39
40
-uint32_t HELPER(neon_tbl)(CPUARMState *env, uint32_t ireg, uint32_t def,
41
- uint32_t rn, uint32_t maxindex)
42
+uint32_t HELPER(neon_tbl)(uint32_t ireg, uint32_t def, void *vn,
43
+ uint32_t maxindex)
44
{
45
- uint32_t val;
46
- uint32_t tmp;
47
- int index;
48
- int shift;
49
- uint64_t *table;
50
- table = (uint64_t *)&env->vfp.regs[rn];
51
+ uint32_t val, shift;
52
+ uint64_t *table = vn;
53
+
54
val = 0;
55
for (shift = 0; shift < 32; shift += 8) {
56
- index = (ireg >> shift) & 0xff;
57
+ uint32_t index = (ireg >> shift) & 0xff;
58
if (index < maxindex) {
59
- tmp = (table[index >> 3] >> ((index & 7) << 3)) & 0xff;
60
+ uint32_t tmp = (table[index >> 3] >> ((index & 7) << 3)) & 0xff;
61
val |= tmp << shift;
62
} else {
63
val |= def & (0xff << shift);
64
diff --git a/target/arm/translate.c b/target/arm/translate.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/translate.c
67
+++ b/target/arm/translate.c
68
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
69
tcg_gen_movi_i32(tmp, 0);
70
}
71
tmp2 = neon_load_reg(rm, 0);
72
- tmp4 = tcg_const_i32(rn);
73
+ ptr1 = vfp_reg_ptr(true, rn);
74
tmp5 = tcg_const_i32(n);
75
- gen_helper_neon_tbl(tmp2, cpu_env, tmp2, tmp, tmp4, tmp5);
76
+ gen_helper_neon_tbl(tmp2, tmp2, tmp, ptr1, tmp5);
77
tcg_temp_free_i32(tmp);
78
if (insn & (1 << 6)) {
79
tmp = neon_load_reg(rd, 1);
80
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
81
tcg_gen_movi_i32(tmp, 0);
82
}
83
tmp3 = neon_load_reg(rm, 1);
84
- gen_helper_neon_tbl(tmp3, cpu_env, tmp3, tmp, tmp4, tmp5);
85
+ gen_helper_neon_tbl(tmp3, tmp3, tmp, ptr1, tmp5);
86
tcg_temp_free_i32(tmp5);
87
- tcg_temp_free_i32(tmp4);
88
+ tcg_temp_free_ptr(ptr1);
89
neon_store_reg(rd, 0, tmp2);
90
neon_store_reg(rd, 1, tmp3);
91
tcg_temp_free_i32(tmp);
92
--
93
2.7.4
94
95
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
All direct users of this field want an integral value. Drop all
4
of the extra casting between uint64_t and float64.
5
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180119045438.28582-6-richard.henderson@linaro.org
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/cpu.h | 2 +-
12
target/arm/arch_dump.c | 4 ++--
13
target/arm/helper.c | 20 ++++++++++----------
14
target/arm/machine.c | 2 +-
15
target/arm/translate-a64.c | 8 ++++----
16
target/arm/translate.c | 2 +-
17
6 files changed, 19 insertions(+), 19 deletions(-)
18
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu.h
22
+++ b/target/arm/cpu.h
23
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
24
* the two execution states, and means we do not need to explicitly
25
* map these registers when changing states.
26
*/
27
- float64 regs[64];
28
+ uint64_t regs[64];
29
30
uint32_t xregs[16];
31
/* We store these fpcsr fields separately for convenience. */
32
diff --git a/target/arm/arch_dump.c b/target/arm/arch_dump.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/arch_dump.c
35
+++ b/target/arm/arch_dump.c
36
@@ -XXX,XX +XXX,XX @@ static int aarch64_write_elf64_prfpreg(WriteCoreDumpFunction f,
37
aarch64_note_init(&note, s, "CORE", 5, NT_PRFPREG, sizeof(note.vfp));
38
39
for (i = 0; i < 64; ++i) {
40
- note.vfp.vregs[i] = cpu_to_dump64(s, float64_val(env->vfp.regs[i]));
41
+ note.vfp.vregs[i] = cpu_to_dump64(s, env->vfp.regs[i]);
42
}
43
44
if (s->dump_info.d_endian == ELFDATA2MSB) {
45
@@ -XXX,XX +XXX,XX @@ static int arm_write_elf32_vfp(WriteCoreDumpFunction f, CPUARMState *env,
46
arm_note_init(&note, s, "LINUX", 6, NT_ARM_VFP, sizeof(note.vfp));
47
48
for (i = 0; i < 32; ++i) {
49
- note.vfp.vregs[i] = cpu_to_dump64(s, float64_val(env->vfp.regs[i]));
50
+ note.vfp.vregs[i] = cpu_to_dump64(s, env->vfp.regs[i]);
51
}
52
53
note.vfp.fpscr = cpu_to_dump32(s, vfp_get_fpscr(env));
54
diff --git a/target/arm/helper.c b/target/arm/helper.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/target/arm/helper.c
57
+++ b/target/arm/helper.c
58
@@ -XXX,XX +XXX,XX @@ static int vfp_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
59
/* VFP data registers are always little-endian. */
60
nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16;
61
if (reg < nregs) {
62
- stfq_le_p(buf, env->vfp.regs[reg]);
63
+ stq_le_p(buf, env->vfp.regs[reg]);
64
return 8;
65
}
66
if (arm_feature(env, ARM_FEATURE_NEON)) {
67
/* Aliases for Q regs. */
68
nregs += 16;
69
if (reg < nregs) {
70
- stfq_le_p(buf, env->vfp.regs[(reg - 32) * 2]);
71
- stfq_le_p(buf + 8, env->vfp.regs[(reg - 32) * 2 + 1]);
72
+ stq_le_p(buf, env->vfp.regs[(reg - 32) * 2]);
73
+ stq_le_p(buf + 8, env->vfp.regs[(reg - 32) * 2 + 1]);
74
return 16;
75
}
76
}
77
@@ -XXX,XX +XXX,XX @@ static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
78
79
nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16;
80
if (reg < nregs) {
81
- env->vfp.regs[reg] = ldfq_le_p(buf);
82
+ env->vfp.regs[reg] = ldq_le_p(buf);
83
return 8;
84
}
85
if (arm_feature(env, ARM_FEATURE_NEON)) {
86
nregs += 16;
87
if (reg < nregs) {
88
- env->vfp.regs[(reg - 32) * 2] = ldfq_le_p(buf);
89
- env->vfp.regs[(reg - 32) * 2 + 1] = ldfq_le_p(buf + 8);
90
+ env->vfp.regs[(reg - 32) * 2] = ldq_le_p(buf);
91
+ env->vfp.regs[(reg - 32) * 2 + 1] = ldq_le_p(buf + 8);
92
return 16;
93
}
94
}
95
@@ -XXX,XX +XXX,XX @@ static int aarch64_fpu_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
96
switch (reg) {
97
case 0 ... 31:
98
/* 128 bit FP register */
99
- stfq_le_p(buf, env->vfp.regs[reg * 2]);
100
- stfq_le_p(buf + 8, env->vfp.regs[reg * 2 + 1]);
101
+ stq_le_p(buf, env->vfp.regs[reg * 2]);
102
+ stq_le_p(buf + 8, env->vfp.regs[reg * 2 + 1]);
103
return 16;
104
case 32:
105
/* FPSR */
106
@@ -XXX,XX +XXX,XX @@ static int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
107
switch (reg) {
108
case 0 ... 31:
109
/* 128 bit FP register */
110
- env->vfp.regs[reg * 2] = ldfq_le_p(buf);
111
- env->vfp.regs[reg * 2 + 1] = ldfq_le_p(buf + 8);
112
+ env->vfp.regs[reg * 2] = ldq_le_p(buf);
113
+ env->vfp.regs[reg * 2 + 1] = ldq_le_p(buf + 8);
114
return 16;
115
case 32:
116
/* FPSR */
117
diff --git a/target/arm/machine.c b/target/arm/machine.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/target/arm/machine.c
120
+++ b/target/arm/machine.c
121
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_vfp = {
122
.minimum_version_id = 3,
123
.needed = vfp_needed,
124
.fields = (VMStateField[]) {
125
- VMSTATE_FLOAT64_ARRAY(env.vfp.regs, ARMCPU, 64),
126
+ VMSTATE_UINT64_ARRAY(env.vfp.regs, ARMCPU, 64),
127
/* The xregs array is a little awkward because element 1 (FPSCR)
128
* requires a specific accessor, so we have to split it up in
129
* the vmstate:
130
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/target/arm/translate-a64.c
133
+++ b/target/arm/translate-a64.c
134
@@ -XXX,XX +XXX,XX @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
135
if (flags & CPU_DUMP_FPU) {
136
int numvfpregs = 32;
137
for (i = 0; i < numvfpregs; i += 2) {
138
- uint64_t vlo = float64_val(env->vfp.regs[i * 2]);
139
- uint64_t vhi = float64_val(env->vfp.regs[(i * 2) + 1]);
140
+ uint64_t vlo = env->vfp.regs[i * 2];
141
+ uint64_t vhi = env->vfp.regs[(i * 2) + 1];
142
cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 " ",
143
i, vhi, vlo);
144
- vlo = float64_val(env->vfp.regs[(i + 1) * 2]);
145
- vhi = float64_val(env->vfp.regs[((i + 1) * 2) + 1]);
146
+ vlo = env->vfp.regs[(i + 1) * 2];
147
+ vhi = env->vfp.regs[((i + 1) * 2) + 1];
148
cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 "\n",
149
i + 1, vhi, vlo);
150
}
151
diff --git a/target/arm/translate.c b/target/arm/translate.c
152
index XXXXXXX..XXXXXXX 100644
153
--- a/target/arm/translate.c
154
+++ b/target/arm/translate.c
155
@@ -XXX,XX +XXX,XX @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
156
numvfpregs += 16;
157
}
158
for (i = 0; i < numvfpregs; i++) {
159
- uint64_t v = float64_val(env->vfp.regs[i]);
160
+ uint64_t v = env->vfp.regs[i];
161
cpu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
162
i * 2, (uint32_t)v,
163
i * 2 + 1, (uint32_t)(v >> 32),
164
--
165
2.7.4
166
167
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We need to handle both registers and ITS tables. While
3
Helpers that return a pointer into env->vfp.regs so that we isolate
4
register handling is standard, ITS table handling is more
4
the logic of how to index the regs array for different cpu modes.
5
challenging since the kernel API is devised so that the
6
tables are flushed into guest RAM and not in vmstate buffers.
7
5
8
Flushing the ITS tables on device pre_save() is too late
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
since the guest RAM is already saved at this point.
7
Message-id: 20180119045438.28582-7-richard.henderson@linaro.org
10
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Table flushing needs to happen when we are sure the vcpus
12
are stopped and before the last dirty page saving. The
13
right point is RUN_STATE_FINISH_MIGRATE but sometimes the
14
VM gets stopped before migration launch so let's simply
15
flush the tables each time the VM gets stopped.
16
17
For regular ITS registers we just can use vmstate pre_save()
18
and post_load() callbacks.
19
20
Signed-off-by: Eric Auger <eric.auger@redhat.com>
21
Message-id: 1497023553-18411-3-git-send-email-eric.auger@redhat.com
22
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
---
10
---
25
include/hw/intc/arm_gicv3_its_common.h | 8 +++
11
target/arm/cpu.h | 27 +++++++++++++++++++++++++++
26
hw/intc/arm_gicv3_its_common.c | 10 ++++
12
linux-user/signal.c | 22 ++++++++++++----------
27
hw/intc/arm_gicv3_its_kvm.c | 105 +++++++++++++++++++++++++++++++++
13
target/arm/arch_dump.c | 8 +++++---
28
3 files changed, 123 insertions(+)
14
target/arm/helper-a64.c | 5 +++--
15
target/arm/helper.c | 32 ++++++++++++++++++++------------
16
target/arm/kvm32.c | 4 ++--
17
target/arm/kvm64.c | 31 ++++++++++---------------------
18
target/arm/translate-a64.c | 25 ++++++++-----------------
19
target/arm/translate.c | 16 +++++++++-------
20
9 files changed, 96 insertions(+), 74 deletions(-)
29
21
30
diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h
22
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
31
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX 100644
32
--- a/include/hw/intc/arm_gicv3_its_common.h
24
--- a/target/arm/cpu.h
33
+++ b/include/hw/intc/arm_gicv3_its_common.h
25
+++ b/target/arm/cpu.h
34
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@ static inline void *arm_get_el_change_hook_opaque(ARMCPU *cpu)
35
#define ITS_TRANS_SIZE 0x10000
27
return cpu->el_change_hook_opaque;
36
#define ITS_SIZE (ITS_CONTROL_SIZE + ITS_TRANS_SIZE)
37
38
+#define GITS_CTLR 0x0
39
+#define GITS_IIDR 0x4
40
+#define GITS_CBASER 0x80
41
+#define GITS_CWRITER 0x88
42
+#define GITS_CREADR 0x90
43
+#define GITS_BASER 0x100
44
+
45
struct GICv3ITSState {
46
SysBusDevice parent_obj;
47
48
@@ -XXX,XX +XXX,XX @@ struct GICv3ITSState {
49
50
/* Registers */
51
uint32_t ctlr;
52
+ uint32_t iidr;
53
uint64_t cbaser;
54
uint64_t cwriter;
55
uint64_t creadr;
56
diff --git a/hw/intc/arm_gicv3_its_common.c b/hw/intc/arm_gicv3_its_common.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/hw/intc/arm_gicv3_its_common.c
59
+++ b/hw/intc/arm_gicv3_its_common.c
60
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_its = {
61
.pre_save = gicv3_its_pre_save,
62
.post_load = gicv3_its_post_load,
63
.unmigratable = true,
64
+ .fields = (VMStateField[]) {
65
+ VMSTATE_UINT32(ctlr, GICv3ITSState),
66
+ VMSTATE_UINT32(iidr, GICv3ITSState),
67
+ VMSTATE_UINT64(cbaser, GICv3ITSState),
68
+ VMSTATE_UINT64(cwriter, GICv3ITSState),
69
+ VMSTATE_UINT64(creadr, GICv3ITSState),
70
+ VMSTATE_UINT64_ARRAY(baser, GICv3ITSState, 8),
71
+ VMSTATE_END_OF_LIST()
72
+ },
73
};
74
75
static MemTxResult gicv3_its_trans_read(void *opaque, hwaddr offset,
76
@@ -XXX,XX +XXX,XX @@ static void gicv3_its_common_reset(DeviceState *dev)
77
s->cbaser = 0;
78
s->cwriter = 0;
79
s->creadr = 0;
80
+ s->iidr = 0;
81
memset(&s->baser, 0, sizeof(s->baser));
82
83
gicv3_its_post_load(s, 0);
84
diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/hw/intc/arm_gicv3_its_kvm.c
87
+++ b/hw/intc/arm_gicv3_its_kvm.c
88
@@ -XXX,XX +XXX,XX @@ static int kvm_its_send_msi(GICv3ITSState *s, uint32_t value, uint16_t devid)
89
return kvm_vm_ioctl(kvm_state, KVM_SIGNAL_MSI, &msi);
90
}
28
}
91
29
92
+/**
30
+/**
93
+ * vm_change_state_handler - VM change state callback aiming at flushing
31
+ * aa32_vfp_dreg:
94
+ * ITS tables into guest RAM
32
+ * Return a pointer to the Dn register within env in 32-bit mode.
95
+ *
96
+ * The tables get flushed to guest RAM whenever the VM gets stopped.
97
+ */
33
+ */
98
+static void vm_change_state_handler(void *opaque, int running,
34
+static inline uint64_t *aa32_vfp_dreg(CPUARMState *env, unsigned regno)
99
+ RunState state)
100
+{
35
+{
101
+ GICv3ITSState *s = (GICv3ITSState *)opaque;
36
+ return &env->vfp.regs[regno];
102
+ Error *err = NULL;
103
+ int ret;
104
+
105
+ if (running) {
106
+ return;
107
+ }
108
+
109
+ ret = kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
110
+ KVM_DEV_ARM_ITS_SAVE_TABLES, NULL, true, &err);
111
+ if (err) {
112
+ error_report_err(err);
113
+ }
114
+ if (ret < 0 && ret != -EFAULT) {
115
+ abort();
116
+ }
117
+}
118
+
119
static void kvm_arm_its_realize(DeviceState *dev, Error **errp)
120
{
121
GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev);
122
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_its_realize(DeviceState *dev, Error **errp)
123
kvm_msi_use_devid = true;
124
kvm_gsi_direct_mapping = false;
125
kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled();
126
+
127
+ qemu_add_vm_change_state_handler(vm_change_state_handler, s);
128
}
129
130
static void kvm_arm_its_init(Object *obj)
131
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_its_init(Object *obj)
132
&error_abort);
133
}
134
135
+/**
136
+ * kvm_arm_its_pre_save - handles the saving of ITS registers.
137
+ * ITS tables are flushed into guest RAM separately and earlier,
138
+ * through the VM change state handler, since at the moment pre_save()
139
+ * is called, the guest RAM has already been saved.
140
+ */
141
+static void kvm_arm_its_pre_save(GICv3ITSState *s)
142
+{
143
+ int i;
144
+
145
+ for (i = 0; i < 8; i++) {
146
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
147
+ GITS_BASER + i * 8, &s->baser[i], false,
148
+ &error_abort);
149
+ }
150
+
151
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
152
+ GITS_CTLR, &s->ctlr, false, &error_abort);
153
+
154
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
155
+ GITS_CBASER, &s->cbaser, false, &error_abort);
156
+
157
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
158
+ GITS_CREADR, &s->creadr, false, &error_abort);
159
+
160
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
161
+ GITS_CWRITER, &s->cwriter, false, &error_abort);
162
+
163
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
164
+ GITS_IIDR, &s->iidr, false, &error_abort);
165
+}
37
+}
166
+
38
+
167
+/**
39
+/**
168
+ * kvm_arm_its_post_load - Restore both the ITS registers and tables
40
+ * aa32_vfp_qreg:
41
+ * Return a pointer to the Qn register within env in 32-bit mode.
169
+ */
42
+ */
170
+static void kvm_arm_its_post_load(GICv3ITSState *s)
43
+static inline uint64_t *aa32_vfp_qreg(CPUARMState *env, unsigned regno)
171
+{
44
+{
172
+ int i;
45
+ return &env->vfp.regs[2 * regno];
173
+
174
+ if (!s->iidr) {
175
+ return;
176
+ }
177
+
178
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
179
+ GITS_IIDR, &s->iidr, true, &error_abort);
180
+
181
+ /*
182
+ * must be written before GITS_CREADR since GITS_CBASER write
183
+ * access resets GITS_CREADR.
184
+ */
185
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
186
+ GITS_CBASER, &s->cbaser, true, &error_abort);
187
+
188
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
189
+ GITS_CREADR, &s->creadr, true, &error_abort);
190
+
191
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
192
+ GITS_CWRITER, &s->cwriter, true, &error_abort);
193
+
194
+
195
+ for (i = 0; i < 8; i++) {
196
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
197
+ GITS_BASER + i * 8, &s->baser[i], true,
198
+ &error_abort);
199
+ }
200
+
201
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
202
+ KVM_DEV_ARM_ITS_RESTORE_TABLES, NULL, true,
203
+ &error_abort);
204
+
205
+ kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
206
+ GITS_CTLR, &s->ctlr, true, &error_abort);
207
+}
46
+}
208
+
47
+
209
static void kvm_arm_its_class_init(ObjectClass *klass, void *data)
48
+/**
49
+ * aa64_vfp_qreg:
50
+ * Return a pointer to the Qn register within env in 64-bit mode.
51
+ */
52
+static inline uint64_t *aa64_vfp_qreg(CPUARMState *env, unsigned regno)
53
+{
54
+ return &env->vfp.regs[2 * regno];
55
+}
56
+
57
#endif
58
diff --git a/linux-user/signal.c b/linux-user/signal.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/linux-user/signal.c
61
+++ b/linux-user/signal.c
62
@@ -XXX,XX +XXX,XX @@ static int target_setup_sigframe(struct target_rt_sigframe *sf,
63
}
64
65
for (i = 0; i < 32; i++) {
66
+ uint64_t *q = aa64_vfp_qreg(env, i);
67
#ifdef TARGET_WORDS_BIGENDIAN
68
- __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
69
- __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
70
+ __put_user(q[0], &aux->fpsimd.vregs[i * 2 + 1]);
71
+ __put_user(q[1], &aux->fpsimd.vregs[i * 2]);
72
#else
73
- __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
74
- __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
75
+ __put_user(q[0], &aux->fpsimd.vregs[i * 2]);
76
+ __put_user(q[1], &aux->fpsimd.vregs[i * 2 + 1]);
77
#endif
78
}
79
__put_user(vfp_get_fpsr(env), &aux->fpsimd.fpsr);
80
@@ -XXX,XX +XXX,XX @@ static int target_restore_sigframe(CPUARMState *env,
81
}
82
83
for (i = 0; i < 32; i++) {
84
+ uint64_t *q = aa64_vfp_qreg(env, i);
85
#ifdef TARGET_WORDS_BIGENDIAN
86
- __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]);
87
- __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]);
88
+ __get_user(q[0], &aux->fpsimd.vregs[i * 2 + 1]);
89
+ __get_user(q[1], &aux->fpsimd.vregs[i * 2]);
90
#else
91
- __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]);
92
- __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]);
93
+ __get_user(q[0], &aux->fpsimd.vregs[i * 2]);
94
+ __get_user(q[1], &aux->fpsimd.vregs[i * 2 + 1]);
95
#endif
96
}
97
__get_user(fpsr, &aux->fpsimd.fpsr);
98
@@ -XXX,XX +XXX,XX @@ static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env)
99
__put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
100
__put_user(sizeof(*vfpframe), &vfpframe->size);
101
for (i = 0; i < 32; i++) {
102
- __put_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
103
+ __put_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
104
}
105
__put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
106
__put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
107
@@ -XXX,XX +XXX,XX @@ static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace)
108
return 0;
109
}
110
for (i = 0; i < 32; i++) {
111
- __get_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
112
+ __get_user(*aa32_vfp_dreg(env, i), &vfpframe->ufp.fpregs[i]);
113
}
114
__get_user(fpscr, &vfpframe->ufp.fpscr);
115
vfp_set_fpscr(env, fpscr);
116
diff --git a/target/arm/arch_dump.c b/target/arm/arch_dump.c
117
index XXXXXXX..XXXXXXX 100644
118
--- a/target/arm/arch_dump.c
119
+++ b/target/arm/arch_dump.c
120
@@ -XXX,XX +XXX,XX @@ static int aarch64_write_elf64_prfpreg(WriteCoreDumpFunction f,
121
122
aarch64_note_init(&note, s, "CORE", 5, NT_PRFPREG, sizeof(note.vfp));
123
124
- for (i = 0; i < 64; ++i) {
125
- note.vfp.vregs[i] = cpu_to_dump64(s, env->vfp.regs[i]);
126
+ for (i = 0; i < 32; ++i) {
127
+ uint64_t *q = aa64_vfp_qreg(env, i);
128
+ note.vfp.vregs[2*i + 0] = cpu_to_dump64(s, q[0]);
129
+ note.vfp.vregs[2*i + 1] = cpu_to_dump64(s, q[1]);
130
}
131
132
if (s->dump_info.d_endian == ELFDATA2MSB) {
133
@@ -XXX,XX +XXX,XX @@ static int arm_write_elf32_vfp(WriteCoreDumpFunction f, CPUARMState *env,
134
arm_note_init(&note, s, "LINUX", 6, NT_ARM_VFP, sizeof(note.vfp));
135
136
for (i = 0; i < 32; ++i) {
137
- note.vfp.vregs[i] = cpu_to_dump64(s, env->vfp.regs[i]);
138
+ note.vfp.vregs[i] = cpu_to_dump64(s, *aa32_vfp_dreg(env, i));
139
}
140
141
note.vfp.fpscr = cpu_to_dump32(s, vfp_get_fpscr(env));
142
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
143
index XXXXXXX..XXXXXXX 100644
144
--- a/target/arm/helper-a64.c
145
+++ b/target/arm/helper-a64.c
146
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(simd_tbl)(CPUARMState *env, uint64_t result, uint64_t indices,
147
if (index < 16 * numregs) {
148
/* Convert index (a byte offset into the virtual table
149
* which is a series of 128-bit vectors concatenated)
150
- * into the correct vfp.regs[] element plus a bit offset
151
+ * into the correct register element plus a bit offset
152
* into that element, bearing in mind that the table
153
* can wrap around from V31 to V0.
154
*/
155
int elt = (rn * 2 + (index >> 3)) % 64;
156
int bitidx = (index & 7) * 8;
157
- uint64_t val = extract64(env->vfp.regs[elt], bitidx, 8);
158
+ uint64_t *q = aa64_vfp_qreg(env, elt >> 1);
159
+ uint64_t val = extract64(q[elt & 1], bitidx, 8);
160
161
result = deposit64(result, shift, 8, val);
162
}
163
diff --git a/target/arm/helper.c b/target/arm/helper.c
164
index XXXXXXX..XXXXXXX 100644
165
--- a/target/arm/helper.c
166
+++ b/target/arm/helper.c
167
@@ -XXX,XX +XXX,XX @@ static int vfp_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
168
/* VFP data registers are always little-endian. */
169
nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16;
170
if (reg < nregs) {
171
- stq_le_p(buf, env->vfp.regs[reg]);
172
+ stq_le_p(buf, *aa32_vfp_dreg(env, reg));
173
return 8;
174
}
175
if (arm_feature(env, ARM_FEATURE_NEON)) {
176
/* Aliases for Q regs. */
177
nregs += 16;
178
if (reg < nregs) {
179
- stq_le_p(buf, env->vfp.regs[(reg - 32) * 2]);
180
- stq_le_p(buf + 8, env->vfp.regs[(reg - 32) * 2 + 1]);
181
+ uint64_t *q = aa32_vfp_qreg(env, reg - 32);
182
+ stq_le_p(buf, q[0]);
183
+ stq_le_p(buf + 8, q[1]);
184
return 16;
185
}
186
}
187
@@ -XXX,XX +XXX,XX @@ static int vfp_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
188
189
nregs = arm_feature(env, ARM_FEATURE_VFP3) ? 32 : 16;
190
if (reg < nregs) {
191
- env->vfp.regs[reg] = ldq_le_p(buf);
192
+ *aa32_vfp_dreg(env, reg) = ldq_le_p(buf);
193
return 8;
194
}
195
if (arm_feature(env, ARM_FEATURE_NEON)) {
196
nregs += 16;
197
if (reg < nregs) {
198
- env->vfp.regs[(reg - 32) * 2] = ldq_le_p(buf);
199
- env->vfp.regs[(reg - 32) * 2 + 1] = ldq_le_p(buf + 8);
200
+ uint64_t *q = aa32_vfp_qreg(env, reg - 32);
201
+ q[0] = ldq_le_p(buf);
202
+ q[1] = ldq_le_p(buf + 8);
203
return 16;
204
}
205
}
206
@@ -XXX,XX +XXX,XX @@ static int aarch64_fpu_gdb_get_reg(CPUARMState *env, uint8_t *buf, int reg)
207
switch (reg) {
208
case 0 ... 31:
209
/* 128 bit FP register */
210
- stq_le_p(buf, env->vfp.regs[reg * 2]);
211
- stq_le_p(buf + 8, env->vfp.regs[reg * 2 + 1]);
212
- return 16;
213
+ {
214
+ uint64_t *q = aa64_vfp_qreg(env, reg);
215
+ stq_le_p(buf, q[0]);
216
+ stq_le_p(buf + 8, q[1]);
217
+ return 16;
218
+ }
219
case 32:
220
/* FPSR */
221
stl_p(buf, vfp_get_fpsr(env));
222
@@ -XXX,XX +XXX,XX @@ static int aarch64_fpu_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
223
switch (reg) {
224
case 0 ... 31:
225
/* 128 bit FP register */
226
- env->vfp.regs[reg * 2] = ldq_le_p(buf);
227
- env->vfp.regs[reg * 2 + 1] = ldq_le_p(buf + 8);
228
- return 16;
229
+ {
230
+ uint64_t *q = aa64_vfp_qreg(env, reg);
231
+ q[0] = ldq_le_p(buf);
232
+ q[1] = ldq_le_p(buf + 8);
233
+ return 16;
234
+ }
235
case 32:
236
/* FPSR */
237
vfp_set_fpsr(env, ldl_p(buf));
238
diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c
239
index XXXXXXX..XXXXXXX 100644
240
--- a/target/arm/kvm32.c
241
+++ b/target/arm/kvm32.c
242
@@ -XXX,XX +XXX,XX @@ int kvm_arch_put_registers(CPUState *cs, int level)
243
/* VFP registers */
244
r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
245
for (i = 0; i < 32; i++) {
246
- r.addr = (uintptr_t)(&env->vfp.regs[i]);
247
+ r.addr = (uintptr_t)aa32_vfp_dreg(env, i);
248
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &r);
249
if (ret) {
250
return ret;
251
@@ -XXX,XX +XXX,XX @@ int kvm_arch_get_registers(CPUState *cs)
252
/* VFP registers */
253
r.id = KVM_REG_ARM | KVM_REG_SIZE_U64 | KVM_REG_ARM_VFP;
254
for (i = 0; i < 32; i++) {
255
- r.addr = (uintptr_t)(&env->vfp.regs[i]);
256
+ r.addr = (uintptr_t)aa32_vfp_dreg(env, i);
257
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &r);
258
if (ret) {
259
return ret;
260
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
261
index XXXXXXX..XXXXXXX 100644
262
--- a/target/arm/kvm64.c
263
+++ b/target/arm/kvm64.c
264
@@ -XXX,XX +XXX,XX @@ int kvm_arch_put_registers(CPUState *cs, int level)
265
}
266
}
267
268
- /* Advanced SIMD and FP registers
269
- * We map Qn = regs[2n+1]:regs[2n]
270
- */
271
+ /* Advanced SIMD and FP registers. */
272
for (i = 0; i < 32; i++) {
273
- int rd = i << 1;
274
- uint64_t fp_val[2];
275
+ uint64_t *q = aa64_vfp_qreg(env, i);
276
#ifdef HOST_WORDS_BIGENDIAN
277
- fp_val[0] = env->vfp.regs[rd + 1];
278
- fp_val[1] = env->vfp.regs[rd];
279
+ uint64_t fp_val[2] = { q[1], q[0] };
280
+ reg.addr = (uintptr_t)fp_val;
281
#else
282
- fp_val[1] = env->vfp.regs[rd + 1];
283
- fp_val[0] = env->vfp.regs[rd];
284
+ reg.addr = (uintptr_t)q;
285
#endif
286
reg.id = AARCH64_SIMD_CORE_REG(fp_regs.vregs[i]);
287
- reg.addr = (uintptr_t)(&fp_val);
288
ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
289
if (ret) {
290
return ret;
291
@@ -XXX,XX +XXX,XX @@ int kvm_arch_get_registers(CPUState *cs)
292
env->spsr = env->banked_spsr[i];
293
}
294
295
- /* Advanced SIMD and FP registers
296
- * We map Qn = regs[2n+1]:regs[2n]
297
- */
298
+ /* Advanced SIMD and FP registers */
299
for (i = 0; i < 32; i++) {
300
- uint64_t fp_val[2];
301
+ uint64_t *q = aa64_vfp_qreg(env, i);
302
reg.id = AARCH64_SIMD_CORE_REG(fp_regs.vregs[i]);
303
- reg.addr = (uintptr_t)(&fp_val);
304
+ reg.addr = (uintptr_t)q;
305
ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
306
if (ret) {
307
return ret;
308
} else {
309
- int rd = i << 1;
310
#ifdef HOST_WORDS_BIGENDIAN
311
- env->vfp.regs[rd + 1] = fp_val[0];
312
- env->vfp.regs[rd] = fp_val[1];
313
-#else
314
- env->vfp.regs[rd + 1] = fp_val[1];
315
- env->vfp.regs[rd] = fp_val[0];
316
+ uint64_t t;
317
+ t = q[0], q[0] = q[1], q[1] = t;
318
#endif
319
}
320
}
321
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
322
index XXXXXXX..XXXXXXX 100644
323
--- a/target/arm/translate-a64.c
324
+++ b/target/arm/translate-a64.c
325
@@ -XXX,XX +XXX,XX @@ void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
326
327
if (flags & CPU_DUMP_FPU) {
328
int numvfpregs = 32;
329
- for (i = 0; i < numvfpregs; i += 2) {
330
- uint64_t vlo = env->vfp.regs[i * 2];
331
- uint64_t vhi = env->vfp.regs[(i * 2) + 1];
332
- cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 " ",
333
- i, vhi, vlo);
334
- vlo = env->vfp.regs[(i + 1) * 2];
335
- vhi = env->vfp.regs[((i + 1) * 2) + 1];
336
- cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 "\n",
337
- i + 1, vhi, vlo);
338
+ for (i = 0; i < numvfpregs; i++) {
339
+ uint64_t *q = aa64_vfp_qreg(env, i);
340
+ uint64_t vlo = q[0];
341
+ uint64_t vhi = q[1];
342
+ cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 "%c",
343
+ i, vhi, vlo, (i & 1 ? '\n' : ' '));
344
}
345
cpu_fprintf(f, "FPCR: %08x FPSR: %08x\n",
346
vfp_get_fpcr(env), vfp_get_fpsr(env));
347
@@ -XXX,XX +XXX,XX @@ static TCGv_ptr vec_full_reg_ptr(DisasContext *s, int regno)
348
*/
349
static inline int fp_reg_offset(DisasContext *s, int regno, TCGMemOp size)
210
{
350
{
211
DeviceClass *dc = DEVICE_CLASS(klass);
351
- int offs = offsetof(CPUARMState, vfp.regs[regno * 2]);
212
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_its_class_init(ObjectClass *klass, void *data)
352
-#ifdef HOST_WORDS_BIGENDIAN
213
353
- offs += (8 - (1 << size));
214
dc->realize = kvm_arm_its_realize;
354
-#endif
215
icc->send_msi = kvm_its_send_msi;
355
- assert_fp_access_checked(s);
216
+ icc->pre_save = kvm_arm_its_pre_save;
356
- return offs;
217
+ icc->post_load = kvm_arm_its_post_load;
357
+ return vec_reg_offset(s, regno, 0, size);
218
}
358
}
219
359
220
static const TypeInfo kvm_arm_its_info = {
360
/* Offset of the high half of the 128 bit vector Qn */
361
static inline int fp_reg_hi_offset(DisasContext *s, int regno)
362
{
363
- assert_fp_access_checked(s);
364
- return offsetof(CPUARMState, vfp.regs[regno * 2 + 1]);
365
+ return vec_reg_offset(s, regno, 1, MO_64);
366
}
367
368
/* Convenience accessors for reading and writing single and double
369
diff --git a/target/arm/translate.c b/target/arm/translate.c
370
index XXXXXXX..XXXXXXX 100644
371
--- a/target/arm/translate.c
372
+++ b/target/arm/translate.c
373
@@ -XXX,XX +XXX,XX @@ static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
374
static inline long
375
vfp_reg_offset (int dp, int reg)
376
{
377
- if (dp)
378
+ if (dp) {
379
return offsetof(CPUARMState, vfp.regs[reg]);
380
- else if (reg & 1) {
381
- return offsetof(CPUARMState, vfp.regs[reg >> 1])
382
- + offsetof(CPU_DoubleU, l.upper);
383
} else {
384
- return offsetof(CPUARMState, vfp.regs[reg >> 1])
385
- + offsetof(CPU_DoubleU, l.lower);
386
+ long ofs = offsetof(CPUARMState, vfp.regs[reg >> 1]);
387
+ if (reg & 1) {
388
+ ofs += offsetof(CPU_DoubleU, l.upper);
389
+ } else {
390
+ ofs += offsetof(CPU_DoubleU, l.lower);
391
+ }
392
+ return ofs;
393
}
394
}
395
396
@@ -XXX,XX +XXX,XX @@ void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
397
numvfpregs += 16;
398
}
399
for (i = 0; i < numvfpregs; i++) {
400
- uint64_t v = env->vfp.regs[i];
401
+ uint64_t v = *aa32_vfp_dreg(env, i);
402
cpu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
403
i * 2, (uint32_t)v,
404
i * 2 + 1, (uint32_t)(v >> 32),
221
--
405
--
222
2.7.4
406
2.7.4
223
407
224
408
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
We change the restoration priority of both the GICv3 and ITS. The
3
At the same time, move VMSTATE_UINT32_SUB_ARRAY
4
GICv3 must be restored before the ITS and the ITS needs to be restored
4
beside the other UINT32 definitions.
5
before PCIe devices since it translates their MSI transactions.
6
5
7
Signed-off-by: Eric Auger <eric.auger@redhat.com>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Juan Quintela <quintela@redhat.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 1497023553-18411-5-git-send-email-eric.auger@redhat.com
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20180119045438.28582-8-richard.henderson@linaro.org
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
include/migration/vmstate.h | 2 ++
13
include/migration/vmstate.h | 9 ++++++---
13
hw/intc/arm_gicv3_common.c | 1 +
14
1 file changed, 6 insertions(+), 3 deletions(-)
14
hw/intc/arm_gicv3_its_common.c | 2 +-
15
hw/intc/arm_gicv3_its_kvm.c | 24 ++++++++++++------------
16
4 files changed, 16 insertions(+), 13 deletions(-)
17
15
18
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
16
diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h
19
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
20
--- a/include/migration/vmstate.h
18
--- a/include/migration/vmstate.h
21
+++ b/include/migration/vmstate.h
19
+++ b/include/migration/vmstate.h
22
@@ -XXX,XX +XXX,XX @@ enum VMStateFlags {
20
@@ -XXX,XX +XXX,XX @@ extern const VMStateInfo vmstate_info_qtailq;
23
typedef enum {
21
#define VMSTATE_UINT32_ARRAY(_f, _s, _n) \
24
MIG_PRI_DEFAULT = 0,
22
VMSTATE_UINT32_ARRAY_V(_f, _s, _n, 0)
25
MIG_PRI_IOMMU, /* Must happen before PCI devices */
23
26
+ MIG_PRI_GICV3_ITS, /* Must happen before PCI devices */
24
+#define VMSTATE_UINT32_SUB_ARRAY(_f, _s, _start, _num) \
27
+ MIG_PRI_GICV3, /* Must happen before the ITS */
25
+ VMSTATE_SUB_ARRAY(_f, _s, _start, _num, 0, vmstate_info_uint32, uint32_t)
28
MIG_PRI_MAX,
26
+
29
} MigrationPriority;
27
#define VMSTATE_UINT32_2DARRAY(_f, _s, _n1, _n2) \
30
28
VMSTATE_UINT32_2DARRAY_V(_f, _s, _n1, _n2, 0)
31
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
29
32
index XXXXXXX..XXXXXXX 100644
30
@@ -XXX,XX +XXX,XX @@ extern const VMStateInfo vmstate_info_qtailq;
33
--- a/hw/intc/arm_gicv3_common.c
31
#define VMSTATE_UINT64_ARRAY(_f, _s, _n) \
34
+++ b/hw/intc/arm_gicv3_common.c
32
VMSTATE_UINT64_ARRAY_V(_f, _s, _n, 0)
35
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_gicv3 = {
33
36
.minimum_version_id = 1,
34
+#define VMSTATE_UINT64_SUB_ARRAY(_f, _s, _start, _num) \
37
.pre_save = gicv3_pre_save,
35
+ VMSTATE_SUB_ARRAY(_f, _s, _start, _num, 0, vmstate_info_uint64, uint64_t)
38
.post_load = gicv3_post_load,
36
+
39
+ .priority = MIG_PRI_GICV3,
37
#define VMSTATE_UINT64_2DARRAY(_f, _s, _n1, _n2) \
40
.fields = (VMStateField[]) {
38
VMSTATE_UINT64_2DARRAY_V(_f, _s, _n1, _n2, 0)
41
VMSTATE_UINT32(gicd_ctlr, GICv3State),
39
42
VMSTATE_UINT32_ARRAY(gicd_statusr, GICv3State, 2),
40
@@ -XXX,XX +XXX,XX @@ extern const VMStateInfo vmstate_info_qtailq;
43
diff --git a/hw/intc/arm_gicv3_its_common.c b/hw/intc/arm_gicv3_its_common.c
41
#define VMSTATE_INT32_ARRAY(_f, _s, _n) \
44
index XXXXXXX..XXXXXXX 100644
42
VMSTATE_INT32_ARRAY_V(_f, _s, _n, 0)
45
--- a/hw/intc/arm_gicv3_its_common.c
43
46
+++ b/hw/intc/arm_gicv3_its_common.c
44
-#define VMSTATE_UINT32_SUB_ARRAY(_f, _s, _start, _num) \
47
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_its = {
45
- VMSTATE_SUB_ARRAY(_f, _s, _start, _num, 0, vmstate_info_uint32, uint32_t)
48
.name = "arm_gicv3_its",
49
.pre_save = gicv3_its_pre_save,
50
.post_load = gicv3_its_post_load,
51
- .unmigratable = true,
52
+ .priority = MIG_PRI_GICV3_ITS,
53
.fields = (VMStateField[]) {
54
VMSTATE_UINT32(ctlr, GICv3ITSState),
55
VMSTATE_UINT32(iidr, GICv3ITSState),
56
diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/hw/intc/arm_gicv3_its_kvm.c
59
+++ b/hw/intc/arm_gicv3_its_kvm.c
60
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_its_realize(DeviceState *dev, Error **errp)
61
GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev);
62
Error *local_err = NULL;
63
64
- /*
65
- * Block migration of a KVM GICv3 ITS device: the API for saving and
66
- * restoring the state in the kernel is not yet available
67
- */
68
- error_setg(&s->migration_blocker, "vITS migration is not implemented");
69
- migrate_add_blocker(s->migration_blocker, &local_err);
70
- if (local_err) {
71
- error_propagate(errp, local_err);
72
- error_free(s->migration_blocker);
73
- return;
74
- }
75
-
46
-
76
s->dev_fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_ITS, false);
47
#define VMSTATE_INT64_ARRAY_V(_f, _s, _n, _v) \
77
if (s->dev_fd < 0) {
48
VMSTATE_ARRAY(_f, _s, _n, _v, vmstate_info_int64, int64_t)
78
error_setg_errno(errp, -s->dev_fd, "error creating in-kernel ITS");
49
79
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_its_realize(DeviceState *dev, Error **errp)
80
81
gicv3_its_init_mmio(s, NULL);
82
83
+ if (!kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
84
+ GITS_CTLR)) {
85
+ error_setg(&s->migration_blocker, "This operating system kernel "
86
+ "does not support vITS migration");
87
+ migrate_add_blocker(s->migration_blocker, &local_err);
88
+ if (local_err) {
89
+ error_propagate(errp, local_err);
90
+ error_free(s->migration_blocker);
91
+ return;
92
+ }
93
+ }
94
+
95
kvm_msi_use_devid = true;
96
kvm_gsi_direct_mapping = false;
97
kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled();
98
--
50
--
99
2.7.4
51
2.7.4
100
52
101
53
diff view generated by jsdifflib
1
From: Krzysztof Kozlowski <krzk@kernel.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Bring some more readability by declaring local function variables: first
3
Not enabled anywhere so far.
4
initialized ones and then the rest (with reversed-christmas-tree order).
5
4
6
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20180119045438.28582-11-richard.henderson@linaro.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
hw/arm/exynos4210.c | 4 ++--
11
target/arm/cpu.h | 1 +
11
1 file changed, 2 insertions(+), 2 deletions(-)
12
1 file changed, 1 insertion(+)
12
13
13
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/exynos4210.c
16
--- a/target/arm/cpu.h
16
+++ b/hw/arm/exynos4210.c
17
+++ b/target/arm/cpu.h
17
@@ -XXX,XX +XXX,XX @@ static uint64_t exynos4210_calc_affinity(int cpu)
18
@@ -XXX,XX +XXX,XX @@ enum arm_features {
18
19
ARM_FEATURE_VBAR, /* has cp15 VBAR */
19
Exynos4210State *exynos4210_init(MemoryRegion *system_mem)
20
ARM_FEATURE_M_SECURITY, /* M profile Security Extension */
20
{
21
ARM_FEATURE_JAZELLE, /* has (trivial) Jazelle implementation */
21
- int i, n;
22
+ ARM_FEATURE_SVE, /* has Scalable Vector Extension */
22
Exynos4210State *s = g_new(Exynos4210State, 1);
23
};
23
qemu_irq gate_irq[EXYNOS4210_NCPUS][EXYNOS4210_IRQ_GATE_NINPUTS];
24
24
- DeviceState *dev;
25
static inline int arm_feature(CPUARMState *env, int feature)
25
SysBusDevice *busdev;
26
ObjectClass *cpu_oc;
27
+ DeviceState *dev;
28
+ int i, n;
29
30
cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, "cortex-a9");
31
assert(cpu_oc);
32
--
26
--
33
2.7.4
27
2.7.4
34
28
35
29
diff view generated by jsdifflib
1
From: Cédric Le Goater <clg@kaod.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Largely inspired by the TMP105 temperature sensor, here is a model for
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
the TMP42{1,2,3} temperature sensors.
4
Message-id: 20180119045438.28582-14-richard.henderson@linaro.org
5
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Specs can be found here :
7
8
    http://www.ti.com/lit/gpn/tmp421
9
10
Signed-off-by: Cédric Le Goater <clg@kaod.org>
11
Message-id: 1496739230-32109-2-git-send-email-clg@kaod.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
---
7
---
15
hw/misc/Makefile.objs | 1 +
8
target/arm/cpu.h | 127 +---------------------------------------------------
16
hw/misc/tmp421.c | 402 ++++++++++++++++++++++++++++++++++++++++
9
target/arm/helper.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++
17
default-configs/arm-softmmu.mak | 1 +
10
2 files changed, 128 insertions(+), 125 deletions(-)
18
3 files changed, 404 insertions(+)
11
19
create mode 100644 hw/misc/tmp421.c
12
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
21
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
22
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/misc/Makefile.objs
14
--- a/target/arm/cpu.h
24
+++ b/hw/misc/Makefile.objs
15
+++ b/target/arm/cpu.h
25
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ static inline bool bswap_code(bool sctlr_b)
26
common-obj-$(CONFIG_APPLESMC) += applesmc.o
17
#endif
27
common-obj-$(CONFIG_MAX111X) += max111x.o
18
}
28
common-obj-$(CONFIG_TMP105) += tmp105.o
19
29
+common-obj-$(CONFIG_TMP421) += tmp421.o
20
-/* Return the exception level to which FP-disabled exceptions should
30
common-obj-$(CONFIG_ISA_DEBUG) += debugexit.o
21
- * be taken, or 0 if FP is enabled.
31
common-obj-$(CONFIG_SGA) += sga.o
22
- */
32
common-obj-$(CONFIG_ISA_TESTDEV) += pc-testdev.o
23
-static inline int fp_exception_el(CPUARMState *env)
33
diff --git a/hw/misc/tmp421.c b/hw/misc/tmp421.c
24
-{
34
new file mode 100644
25
- int fpen;
35
index XXXXXXX..XXXXXXX
26
- int cur_el = arm_current_el(env);
36
--- /dev/null
27
-
37
+++ b/hw/misc/tmp421.c
28
- /* CPACR and the CPTR registers don't exist before v6, so FP is
38
@@ -XXX,XX +XXX,XX @@
29
- * always accessible
39
+/*
30
- */
40
+ * Texas Instruments TMP421 temperature sensor.
31
- if (!arm_feature(env, ARM_FEATURE_V6)) {
41
+ *
32
- return 0;
42
+ * Copyright (c) 2016 IBM Corporation.
33
- }
43
+ *
34
-
44
+ * Largely inspired by :
35
- /* The CPACR controls traps to EL1, or PL1 if we're 32 bit:
45
+ *
36
- * 0, 2 : trap EL0 and EL1/PL1 accesses
46
+ * Texas Instruments TMP105 temperature sensor.
37
- * 1 : trap only EL0 accesses
47
+ *
38
- * 3 : trap no accesses
48
+ * Copyright (C) 2008 Nokia Corporation
39
- */
49
+ * Written by Andrzej Zaborowski <andrew@openedhand.com>
40
- fpen = extract32(env->cp15.cpacr_el1, 20, 2);
50
+ *
41
- switch (fpen) {
51
+ * This program is free software; you can redistribute it and/or
42
- case 0:
52
+ * modify it under the terms of the GNU General Public License as
43
- case 2:
53
+ * published by the Free Software Foundation; either version 2 or
44
- if (cur_el == 0 || cur_el == 1) {
54
+ * (at your option) version 3 of the License.
45
- /* Trap to PL1, which might be EL1 or EL3 */
55
+ *
46
- if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
56
+ * This program is distributed in the hope that it will be useful,
47
- return 3;
57
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
48
- }
58
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
49
- return 1;
59
+ * GNU General Public License for more details.
50
- }
60
+ *
51
- if (cur_el == 3 && !is_a64(env)) {
61
+ * You should have received a copy of the GNU General Public License along
52
- /* Secure PL1 running at EL3 */
62
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
53
- return 3;
54
- }
55
- break;
56
- case 1:
57
- if (cur_el == 0) {
58
- return 1;
59
- }
60
- break;
61
- case 3:
62
- break;
63
- }
64
-
65
- /* For the CPTR registers we don't need to guard with an ARM_FEATURE
66
- * check because zero bits in the registers mean "don't trap".
67
- */
68
-
69
- /* CPTR_EL2 : present in v7VE or v8 */
70
- if (cur_el <= 2 && extract32(env->cp15.cptr_el[2], 10, 1)
71
- && !arm_is_secure_below_el3(env)) {
72
- /* Trap FP ops at EL2, NS-EL1 or NS-EL0 to EL2 */
73
- return 2;
74
- }
75
-
76
- /* CPTR_EL3 : present in v8 */
77
- if (extract32(env->cp15.cptr_el[3], 10, 1)) {
78
- /* Trap all FP ops to EL3 */
79
- return 3;
80
- }
81
-
82
- return 0;
83
-}
84
-
85
#ifdef CONFIG_USER_ONLY
86
static inline bool arm_cpu_bswap_data(CPUARMState *env)
87
{
88
@@ -XXX,XX +XXX,XX @@ static inline uint32_t arm_regime_tbi1(CPUARMState *env, ARMMMUIdx mmu_idx)
89
}
90
#endif
91
92
-static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
93
- target_ulong *cs_base, uint32_t *flags)
94
-{
95
- ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
96
- if (is_a64(env)) {
97
- *pc = env->pc;
98
- *flags = ARM_TBFLAG_AARCH64_STATE_MASK;
99
- /* Get control bits for tagged addresses */
100
- *flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT);
101
- *flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
102
- } else {
103
- *pc = env->regs[15];
104
- *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
105
- | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
106
- | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
107
- | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
108
- | (arm_sctlr_b(env) << ARM_TBFLAG_SCTLR_B_SHIFT);
109
- if (!(access_secure_reg(env))) {
110
- *flags |= ARM_TBFLAG_NS_MASK;
111
- }
112
- if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
113
- || arm_el_is_aa64(env, 1)) {
114
- *flags |= ARM_TBFLAG_VFPEN_MASK;
115
- }
116
- *flags |= (extract32(env->cp15.c15_cpar, 0, 2)
117
- << ARM_TBFLAG_XSCALE_CPAR_SHIFT);
118
- }
119
-
120
- *flags |= (arm_to_core_mmu_idx(mmu_idx) << ARM_TBFLAG_MMUIDX_SHIFT);
121
-
122
- /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
123
- * states defined in the ARM ARM for software singlestep:
124
- * SS_ACTIVE PSTATE.SS State
125
- * 0 x Inactive (the TB flag for SS is always 0)
126
- * 1 0 Active-pending
127
- * 1 1 Active-not-pending
128
- */
129
- if (arm_singlestep_active(env)) {
130
- *flags |= ARM_TBFLAG_SS_ACTIVE_MASK;
131
- if (is_a64(env)) {
132
- if (env->pstate & PSTATE_SS) {
133
- *flags |= ARM_TBFLAG_PSTATE_SS_MASK;
134
- }
135
- } else {
136
- if (env->uncached_cpsr & PSTATE_SS) {
137
- *flags |= ARM_TBFLAG_PSTATE_SS_MASK;
138
- }
139
- }
140
- }
141
- if (arm_cpu_data_is_big_endian(env)) {
142
- *flags |= ARM_TBFLAG_BE_DATA_MASK;
143
- }
144
- *flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
145
-
146
- if (arm_v7m_is_handler_mode(env)) {
147
- *flags |= ARM_TBFLAG_HANDLER_MASK;
148
- }
149
-
150
- *cs_base = 0;
151
-}
152
+void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
153
+ target_ulong *cs_base, uint32_t *flags);
154
155
enum {
156
QEMU_PSCI_CONDUIT_DISABLED = 0,
157
diff --git a/target/arm/helper.c b/target/arm/helper.c
158
index XXXXXXX..XXXXXXX 100644
159
--- a/target/arm/helper.c
160
+++ b/target/arm/helper.c
161
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes)
162
/* Linux crc32c converts the output to one's complement. */
163
return crc32c(acc, buf, bytes) ^ 0xffffffff;
164
}
165
+
166
+/* Return the exception level to which FP-disabled exceptions should
167
+ * be taken, or 0 if FP is enabled.
63
+ */
168
+ */
64
+
169
+static inline int fp_exception_el(CPUARMState *env)
65
+#include "qemu/osdep.h"
66
+#include "hw/hw.h"
67
+#include "hw/i2c/i2c.h"
68
+#include "qapi/error.h"
69
+#include "qapi/visitor.h"
70
+
71
+/* Manufacturer / Device ID's */
72
+#define TMP421_MANUFACTURER_ID 0x55
73
+#define TMP421_DEVICE_ID 0x21
74
+#define TMP422_DEVICE_ID 0x22
75
+#define TMP423_DEVICE_ID 0x23
76
+
77
+typedef struct DeviceInfo {
78
+ int model;
79
+ const char *name;
80
+} DeviceInfo;
81
+
82
+static const DeviceInfo devices[] = {
83
+ { TMP421_DEVICE_ID, "tmp421" },
84
+ { TMP422_DEVICE_ID, "tmp422" },
85
+ { TMP423_DEVICE_ID, "tmp423" },
86
+};
87
+
88
+typedef struct TMP421State {
89
+ /*< private >*/
90
+ I2CSlave i2c;
91
+ /*< public >*/
92
+
93
+ int16_t temperature[4];
94
+
95
+ uint8_t status;
96
+ uint8_t config[2];
97
+ uint8_t rate;
98
+
99
+ uint8_t len;
100
+ uint8_t buf[2];
101
+ uint8_t pointer;
102
+
103
+} TMP421State;
104
+
105
+typedef struct TMP421Class {
106
+ I2CSlaveClass parent_class;
107
+ DeviceInfo *dev;
108
+} TMP421Class;
109
+
110
+#define TYPE_TMP421 "tmp421-generic"
111
+#define TMP421(obj) OBJECT_CHECK(TMP421State, (obj), TYPE_TMP421)
112
+
113
+#define TMP421_CLASS(klass) \
114
+ OBJECT_CLASS_CHECK(TMP421Class, (klass), TYPE_TMP421)
115
+#define TMP421_GET_CLASS(obj) \
116
+ OBJECT_GET_CLASS(TMP421Class, (obj), TYPE_TMP421)
117
+
118
+/* the TMP421 registers */
119
+#define TMP421_STATUS_REG 0x08
120
+#define TMP421_STATUS_BUSY (1 << 7)
121
+#define TMP421_CONFIG_REG_1 0x09
122
+#define TMP421_CONFIG_RANGE (1 << 2)
123
+#define TMP421_CONFIG_SHUTDOWN (1 << 6)
124
+#define TMP421_CONFIG_REG_2 0x0A
125
+#define TMP421_CONFIG_RC (1 << 2)
126
+#define TMP421_CONFIG_LEN (1 << 3)
127
+#define TMP421_CONFIG_REN (1 << 4)
128
+#define TMP421_CONFIG_REN2 (1 << 5)
129
+#define TMP421_CONFIG_REN3 (1 << 6)
130
+
131
+#define TMP421_CONVERSION_RATE_REG 0x0B
132
+#define TMP421_ONE_SHOT 0x0F
133
+
134
+#define TMP421_RESET 0xFC
135
+#define TMP421_MANUFACTURER_ID_REG 0xFE
136
+#define TMP421_DEVICE_ID_REG 0xFF
137
+
138
+#define TMP421_TEMP_MSB0 0x00
139
+#define TMP421_TEMP_MSB1 0x01
140
+#define TMP421_TEMP_MSB2 0x02
141
+#define TMP421_TEMP_MSB3 0x03
142
+#define TMP421_TEMP_LSB0 0x10
143
+#define TMP421_TEMP_LSB1 0x11
144
+#define TMP421_TEMP_LSB2 0x12
145
+#define TMP421_TEMP_LSB3 0x13
146
+
147
+static const int32_t mins[2] = { -40000, -55000 };
148
+static const int32_t maxs[2] = { 127000, 150000 };
149
+
150
+static void tmp421_get_temperature(Object *obj, Visitor *v, const char *name,
151
+ void *opaque, Error **errp)
152
+{
170
+{
153
+ TMP421State *s = TMP421(obj);
171
+ int fpen;
154
+ bool ext_range = (s->config[0] & TMP421_CONFIG_RANGE);
172
+ int cur_el = arm_current_el(env);
155
+ int offset = ext_range * 64 * 256;
173
+
156
+ int64_t value;
174
+ /* CPACR and the CPTR registers don't exist before v6, so FP is
157
+ int tempid;
175
+ * always accessible
158
+
176
+ */
159
+ if (sscanf(name, "temperature%d", &tempid) != 1) {
177
+ if (!arm_feature(env, ARM_FEATURE_V6)) {
160
+ error_setg(errp, "error reading %s: %m", name);
178
+ return 0;
161
+ return;
179
+ }
162
+ }
180
+
163
+
181
+ /* The CPACR controls traps to EL1, or PL1 if we're 32 bit:
164
+ if (tempid >= 4 || tempid < 0) {
182
+ * 0, 2 : trap EL0 and EL1/PL1 accesses
165
+ error_setg(errp, "error reading %s", name);
183
+ * 1 : trap only EL0 accesses
166
+ return;
184
+ * 3 : trap no accesses
167
+ }
185
+ */
168
+
186
+ fpen = extract32(env->cp15.cpacr_el1, 20, 2);
169
+ value = ((s->temperature[tempid] - offset) * 1000 + 128) / 256;
187
+ switch (fpen) {
170
+
188
+ case 0:
171
+ visit_type_int(v, name, &value, errp);
189
+ case 2:
172
+}
190
+ if (cur_el == 0 || cur_el == 1) {
173
+
191
+ /* Trap to PL1, which might be EL1 or EL3 */
174
+/* Units are 0.001 centigrades relative to 0 C. s->temperature is 8.8
192
+ if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
175
+ * fixed point, so units are 1/256 centigrades. A simple ratio will do.
193
+ return 3;
176
+ */
194
+ }
177
+static void tmp421_set_temperature(Object *obj, Visitor *v, const char *name,
195
+ return 1;
178
+ void *opaque, Error **errp)
196
+ }
179
+{
197
+ if (cur_el == 3 && !is_a64(env)) {
180
+ TMP421State *s = TMP421(obj);
198
+ /* Secure PL1 running at EL3 */
181
+ Error *local_err = NULL;
199
+ return 3;
182
+ int64_t temp;
200
+ }
183
+ bool ext_range = (s->config[0] & TMP421_CONFIG_RANGE);
184
+ int offset = ext_range * 64 * 256;
185
+ int tempid;
186
+
187
+ visit_type_int(v, name, &temp, &local_err);
188
+ if (local_err) {
189
+ error_propagate(errp, local_err);
190
+ return;
191
+ }
192
+
193
+ if (temp >= maxs[ext_range] || temp < mins[ext_range]) {
194
+ error_setg(errp, "value %" PRId64 ".%03" PRIu64 " °C is out of range",
195
+ temp / 1000, temp % 1000);
196
+ return;
197
+ }
198
+
199
+ if (sscanf(name, "temperature%d", &tempid) != 1) {
200
+ error_setg(errp, "error reading %s: %m", name);
201
+ return;
202
+ }
203
+
204
+ if (tempid >= 4 || tempid < 0) {
205
+ error_setg(errp, "error reading %s", name);
206
+ return;
207
+ }
208
+
209
+ s->temperature[tempid] = (int16_t) ((temp * 256 - 128) / 1000) + offset;
210
+}
211
+
212
+static void tmp421_read(TMP421State *s)
213
+{
214
+ TMP421Class *sc = TMP421_GET_CLASS(s);
215
+
216
+ s->len = 0;
217
+
218
+ switch (s->pointer) {
219
+ case TMP421_MANUFACTURER_ID_REG:
220
+ s->buf[s->len++] = TMP421_MANUFACTURER_ID;
221
+ break;
201
+ break;
222
+ case TMP421_DEVICE_ID_REG:
202
+ case 1:
223
+ s->buf[s->len++] = sc->dev->model;
203
+ if (cur_el == 0) {
204
+ return 1;
205
+ }
224
+ break;
206
+ break;
225
+ case TMP421_CONFIG_REG_1:
207
+ case 3:
226
+ s->buf[s->len++] = s->config[0];
227
+ break;
208
+ break;
228
+ case TMP421_CONFIG_REG_2:
209
+ }
229
+ s->buf[s->len++] = s->config[1];
210
+
230
+ break;
211
+ /* For the CPTR registers we don't need to guard with an ARM_FEATURE
231
+ case TMP421_CONVERSION_RATE_REG:
212
+ * check because zero bits in the registers mean "don't trap".
232
+ s->buf[s->len++] = s->rate;
213
+ */
233
+ break;
214
+
234
+ case TMP421_STATUS_REG:
215
+ /* CPTR_EL2 : present in v7VE or v8 */
235
+ s->buf[s->len++] = s->status;
216
+ if (cur_el <= 2 && extract32(env->cp15.cptr_el[2], 10, 1)
236
+ break;
217
+ && !arm_is_secure_below_el3(env)) {
237
+
218
+ /* Trap FP ops at EL2, NS-EL1 or NS-EL0 to EL2 */
238
+ /* FIXME: check for channel enablement in config registers */
219
+ return 2;
239
+ case TMP421_TEMP_MSB0:
220
+ }
240
+ s->buf[s->len++] = (((uint16_t) s->temperature[0]) >> 8);
221
+
241
+ s->buf[s->len++] = (((uint16_t) s->temperature[0]) >> 0) & 0xf0;
222
+ /* CPTR_EL3 : present in v8 */
242
+ break;
223
+ if (extract32(env->cp15.cptr_el[3], 10, 1)) {
243
+ case TMP421_TEMP_MSB1:
224
+ /* Trap all FP ops to EL3 */
244
+ s->buf[s->len++] = (((uint16_t) s->temperature[1]) >> 8);
225
+ return 3;
245
+ s->buf[s->len++] = (((uint16_t) s->temperature[1]) >> 0) & 0xf0;
246
+ break;
247
+ case TMP421_TEMP_MSB2:
248
+ s->buf[s->len++] = (((uint16_t) s->temperature[2]) >> 8);
249
+ s->buf[s->len++] = (((uint16_t) s->temperature[2]) >> 0) & 0xf0;
250
+ break;
251
+ case TMP421_TEMP_MSB3:
252
+ s->buf[s->len++] = (((uint16_t) s->temperature[3]) >> 8);
253
+ s->buf[s->len++] = (((uint16_t) s->temperature[3]) >> 0) & 0xf0;
254
+ break;
255
+ case TMP421_TEMP_LSB0:
256
+ s->buf[s->len++] = (((uint16_t) s->temperature[0]) >> 0) & 0xf0;
257
+ break;
258
+ case TMP421_TEMP_LSB1:
259
+ s->buf[s->len++] = (((uint16_t) s->temperature[1]) >> 0) & 0xf0;
260
+ break;
261
+ case TMP421_TEMP_LSB2:
262
+ s->buf[s->len++] = (((uint16_t) s->temperature[2]) >> 0) & 0xf0;
263
+ break;
264
+ case TMP421_TEMP_LSB3:
265
+ s->buf[s->len++] = (((uint16_t) s->temperature[3]) >> 0) & 0xf0;
266
+ break;
267
+ }
268
+}
269
+
270
+static void tmp421_reset(I2CSlave *i2c);
271
+
272
+static void tmp421_write(TMP421State *s)
273
+{
274
+ switch (s->pointer) {
275
+ case TMP421_CONVERSION_RATE_REG:
276
+ s->rate = s->buf[0];
277
+ break;
278
+ case TMP421_CONFIG_REG_1:
279
+ s->config[0] = s->buf[0];
280
+ break;
281
+ case TMP421_CONFIG_REG_2:
282
+ s->config[1] = s->buf[0];
283
+ break;
284
+ case TMP421_RESET:
285
+ tmp421_reset(I2C_SLAVE(s));
286
+ break;
287
+ }
288
+}
289
+
290
+static int tmp421_rx(I2CSlave *i2c)
291
+{
292
+ TMP421State *s = TMP421(i2c);
293
+
294
+ if (s->len < 2) {
295
+ return s->buf[s->len++];
296
+ } else {
297
+ return 0xff;
298
+ }
299
+}
300
+
301
+static int tmp421_tx(I2CSlave *i2c, uint8_t data)
302
+{
303
+ TMP421State *s = TMP421(i2c);
304
+
305
+ if (s->len == 0) {
306
+ /* first byte is the register pointer for a read or write
307
+ * operation */
308
+ s->pointer = data;
309
+ s->len++;
310
+ } else if (s->len == 1) {
311
+ /* second byte is the data to write. The device only supports
312
+ * one byte writes */
313
+ s->buf[0] = data;
314
+ tmp421_write(s);
315
+ }
226
+ }
316
+
227
+
317
+ return 0;
228
+ return 0;
318
+}
229
+}
319
+
230
+
320
+static int tmp421_event(I2CSlave *i2c, enum i2c_event event)
231
+void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
232
+ target_ulong *cs_base, uint32_t *flags)
321
+{
233
+{
322
+ TMP421State *s = TMP421(i2c);
234
+ ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
323
+
235
+ if (is_a64(env)) {
324
+ if (event == I2C_START_RECV) {
236
+ *pc = env->pc;
325
+ tmp421_read(s);
237
+ *flags = ARM_TBFLAG_AARCH64_STATE_MASK;
326
+ }
238
+ /* Get control bits for tagged addresses */
327
+
239
+ *flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT);
328
+ s->len = 0;
240
+ *flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
329
+ return 0;
241
+ } else {
242
+ *pc = env->regs[15];
243
+ *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
244
+ | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
245
+ | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
246
+ | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
247
+ | (arm_sctlr_b(env) << ARM_TBFLAG_SCTLR_B_SHIFT);
248
+ if (!(access_secure_reg(env))) {
249
+ *flags |= ARM_TBFLAG_NS_MASK;
250
+ }
251
+ if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
252
+ || arm_el_is_aa64(env, 1)) {
253
+ *flags |= ARM_TBFLAG_VFPEN_MASK;
254
+ }
255
+ *flags |= (extract32(env->cp15.c15_cpar, 0, 2)
256
+ << ARM_TBFLAG_XSCALE_CPAR_SHIFT);
257
+ }
258
+
259
+ *flags |= (arm_to_core_mmu_idx(mmu_idx) << ARM_TBFLAG_MMUIDX_SHIFT);
260
+
261
+ /* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
262
+ * states defined in the ARM ARM for software singlestep:
263
+ * SS_ACTIVE PSTATE.SS State
264
+ * 0 x Inactive (the TB flag for SS is always 0)
265
+ * 1 0 Active-pending
266
+ * 1 1 Active-not-pending
267
+ */
268
+ if (arm_singlestep_active(env)) {
269
+ *flags |= ARM_TBFLAG_SS_ACTIVE_MASK;
270
+ if (is_a64(env)) {
271
+ if (env->pstate & PSTATE_SS) {
272
+ *flags |= ARM_TBFLAG_PSTATE_SS_MASK;
273
+ }
274
+ } else {
275
+ if (env->uncached_cpsr & PSTATE_SS) {
276
+ *flags |= ARM_TBFLAG_PSTATE_SS_MASK;
277
+ }
278
+ }
279
+ }
280
+ if (arm_cpu_data_is_big_endian(env)) {
281
+ *flags |= ARM_TBFLAG_BE_DATA_MASK;
282
+ }
283
+ *flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
284
+
285
+ if (arm_v7m_is_handler_mode(env)) {
286
+ *flags |= ARM_TBFLAG_HANDLER_MASK;
287
+ }
288
+
289
+ *cs_base = 0;
330
+}
290
+}
331
+
332
+static const VMStateDescription vmstate_tmp421 = {
333
+ .name = "TMP421",
334
+ .version_id = 0,
335
+ .minimum_version_id = 0,
336
+ .fields = (VMStateField[]) {
337
+ VMSTATE_UINT8(len, TMP421State),
338
+ VMSTATE_UINT8_ARRAY(buf, TMP421State, 2),
339
+ VMSTATE_UINT8(pointer, TMP421State),
340
+ VMSTATE_UINT8_ARRAY(config, TMP421State, 2),
341
+ VMSTATE_UINT8(status, TMP421State),
342
+ VMSTATE_UINT8(rate, TMP421State),
343
+ VMSTATE_INT16_ARRAY(temperature, TMP421State, 4),
344
+ VMSTATE_I2C_SLAVE(i2c, TMP421State),
345
+ VMSTATE_END_OF_LIST()
346
+ }
347
+};
348
+
349
+static void tmp421_reset(I2CSlave *i2c)
350
+{
351
+ TMP421State *s = TMP421(i2c);
352
+ TMP421Class *sc = TMP421_GET_CLASS(s);
353
+
354
+ memset(s->temperature, 0, sizeof(s->temperature));
355
+ s->pointer = 0;
356
+
357
+ s->config[0] = 0; /* TMP421_CONFIG_RANGE */
358
+
359
+ /* resistance correction and channel enablement */
360
+ switch (sc->dev->model) {
361
+ case TMP421_DEVICE_ID:
362
+ s->config[1] = 0x1c;
363
+ break;
364
+ case TMP422_DEVICE_ID:
365
+ s->config[1] = 0x3c;
366
+ break;
367
+ case TMP423_DEVICE_ID:
368
+ s->config[1] = 0x7c;
369
+ break;
370
+ }
371
+
372
+ s->rate = 0x7; /* 8Hz */
373
+ s->status = 0;
374
+}
375
+
376
+static int tmp421_init(I2CSlave *i2c)
377
+{
378
+ TMP421State *s = TMP421(i2c);
379
+
380
+ tmp421_reset(&s->i2c);
381
+
382
+ return 0;
383
+}
384
+
385
+static void tmp421_initfn(Object *obj)
386
+{
387
+ object_property_add(obj, "temperature0", "int",
388
+ tmp421_get_temperature,
389
+ tmp421_set_temperature, NULL, NULL, NULL);
390
+ object_property_add(obj, "temperature1", "int",
391
+ tmp421_get_temperature,
392
+ tmp421_set_temperature, NULL, NULL, NULL);
393
+ object_property_add(obj, "temperature2", "int",
394
+ tmp421_get_temperature,
395
+ tmp421_set_temperature, NULL, NULL, NULL);
396
+ object_property_add(obj, "temperature3", "int",
397
+ tmp421_get_temperature,
398
+ tmp421_set_temperature, NULL, NULL, NULL);
399
+}
400
+
401
+static void tmp421_class_init(ObjectClass *klass, void *data)
402
+{
403
+ DeviceClass *dc = DEVICE_CLASS(klass);
404
+ I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
405
+ TMP421Class *sc = TMP421_CLASS(klass);
406
+
407
+ k->init = tmp421_init;
408
+ k->event = tmp421_event;
409
+ k->recv = tmp421_rx;
410
+ k->send = tmp421_tx;
411
+ dc->vmsd = &vmstate_tmp421;
412
+ sc->dev = (DeviceInfo *) data;
413
+}
414
+
415
+static const TypeInfo tmp421_info = {
416
+ .name = TYPE_TMP421,
417
+ .parent = TYPE_I2C_SLAVE,
418
+ .instance_size = sizeof(TMP421State),
419
+ .class_size = sizeof(TMP421Class),
420
+ .instance_init = tmp421_initfn,
421
+ .abstract = true,
422
+};
423
+
424
+static void tmp421_register_types(void)
425
+{
426
+ int i;
427
+
428
+ type_register_static(&tmp421_info);
429
+ for (i = 0; i < ARRAY_SIZE(devices); ++i) {
430
+ TypeInfo ti = {
431
+ .name = devices[i].name,
432
+ .parent = TYPE_TMP421,
433
+ .class_init = tmp421_class_init,
434
+ .class_data = (void *) &devices[i],
435
+ };
436
+ type_register(&ti);
437
+ }
438
+}
439
+
440
+type_init(tmp421_register_types)
441
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
442
index XXXXXXX..XXXXXXX 100644
443
--- a/default-configs/arm-softmmu.mak
444
+++ b/default-configs/arm-softmmu.mak
445
@@ -XXX,XX +XXX,XX @@ CONFIG_TWL92230=y
446
CONFIG_TSC2005=y
447
CONFIG_LM832X=y
448
CONFIG_TMP105=y
449
+CONFIG_TMP421=y
450
CONFIG_STELLARIS=y
451
CONFIG_STELLARIS_INPUT=y
452
CONFIG_STELLARIS_ENET=y
453
--
291
--
454
2.7.4
292
2.7.4
455
293
456
294
diff view generated by jsdifflib
1
From: Krzysztof Kozlowski <krzk@kernel.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Before QOM-ifying the Exynos4 SoC model, move the DRAM initialization
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
from exynos4210.c to exynos4_boards.c because DRAM is board specific,
4
Message-id: 20180119045438.28582-15-richard.henderson@linaro.org
5
not SoC.
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
8
---
11
include/hw/arm/exynos4210.h | 5 +----
9
target/arm/helper.c | 35 +++++++++++++++++++----------------
12
hw/arm/exynos4210.c | 20 +-----------------
10
1 file changed, 19 insertions(+), 16 deletions(-)
13
hw/arm/exynos4_boards.c | 50 ++++++++++++++++++++++++++++++++++++++-------
14
3 files changed, 45 insertions(+), 30 deletions(-)
15
11
16
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/exynos4210.h
14
--- a/target/arm/helper.c
19
+++ b/include/hw/arm/exynos4210.h
15
+++ b/target/arm/helper.c
20
@@ -XXX,XX +XXX,XX @@ typedef struct Exynos4210State {
16
@@ -XXX,XX +XXX,XX @@ static inline int fp_exception_el(CPUARMState *env)
21
MemoryRegion iram_mem;
22
MemoryRegion irom_mem;
23
MemoryRegion irom_alias_mem;
24
- MemoryRegion dram0_mem;
25
- MemoryRegion dram1_mem;
26
MemoryRegion boot_secondary;
27
MemoryRegion bootreg_mem;
28
I2CBus *i2c_if[EXYNOS4210_I2C_NUMBER];
29
@@ -XXX,XX +XXX,XX @@ typedef struct Exynos4210State {
30
void exynos4210_write_secondary(ARMCPU *cpu,
31
const struct arm_boot_info *info);
32
33
-Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
34
- unsigned long ram_size);
35
+Exynos4210State *exynos4210_init(MemoryRegion *system_mem);
36
37
/* Initialize exynos4210 IRQ subsystem stub */
38
qemu_irq *exynos4210_init_irq(Exynos4210Irq *env);
39
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/arm/exynos4210.c
42
+++ b/hw/arm/exynos4210.c
43
@@ -XXX,XX +XXX,XX @@ static uint64_t exynos4210_calc_affinity(int cpu)
44
return mp_affinity;
45
}
17
}
46
18
47
-Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
19
void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
48
- unsigned long ram_size)
20
- target_ulong *cs_base, uint32_t *flags)
49
+Exynos4210State *exynos4210_init(MemoryRegion *system_mem)
21
+ target_ulong *cs_base, uint32_t *pflags)
50
{
22
{
51
int i, n;
23
ARMMMUIdx mmu_idx = core_to_arm_mmu_idx(env, cpu_mmu_index(env, false));
52
Exynos4210State *s = g_new(Exynos4210State, 1);
24
+ uint32_t flags;
53
qemu_irq gate_irq[EXYNOS4210_NCPUS][EXYNOS4210_IRQ_GATE_NINPUTS];
54
- unsigned long mem_size;
55
DeviceState *dev;
56
SysBusDevice *busdev;
57
ObjectClass *cpu_oc;
58
@@ -XXX,XX +XXX,XX @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem,
59
memory_region_add_subregion(system_mem, EXYNOS4210_IRAM_BASE_ADDR,
60
&s->iram_mem);
61
62
- /* DRAM */
63
- mem_size = ram_size;
64
- if (mem_size > EXYNOS4210_DRAM_MAX_SIZE) {
65
- memory_region_init_ram(&s->dram1_mem, NULL, "exynos4210.dram1",
66
- mem_size - EXYNOS4210_DRAM_MAX_SIZE, &error_fatal);
67
- vmstate_register_ram_global(&s->dram1_mem);
68
- memory_region_add_subregion(system_mem, EXYNOS4210_DRAM1_BASE_ADDR,
69
- &s->dram1_mem);
70
- mem_size = EXYNOS4210_DRAM_MAX_SIZE;
71
- }
72
- memory_region_init_ram(&s->dram0_mem, NULL, "exynos4210.dram0", mem_size,
73
- &error_fatal);
74
- vmstate_register_ram_global(&s->dram0_mem);
75
- memory_region_add_subregion(system_mem, EXYNOS4210_DRAM0_BASE_ADDR,
76
- &s->dram0_mem);
77
-
78
/* PMU.
79
* The only reason of existence at the moment is that secondary CPU boot
80
* loader uses PMU INFORM5 register as a holding pen.
81
diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c
82
index XXXXXXX..XXXXXXX 100644
83
--- a/hw/arm/exynos4_boards.c
84
+++ b/hw/arm/exynos4_boards.c
85
@@ -XXX,XX +XXX,XX @@
86
*/
87
88
#include "qemu/osdep.h"
89
+#include "qapi/error.h"
90
#include "qemu/error-report.h"
91
#include "qemu-common.h"
92
#include "cpu.h"
93
@@ -XXX,XX +XXX,XX @@ typedef enum Exynos4BoardType {
94
EXYNOS4_NUM_OF_BOARDS
95
} Exynos4BoardType;
96
97
+typedef struct Exynos4BoardState {
98
+ Exynos4210State *soc;
99
+ MemoryRegion dram0_mem;
100
+ MemoryRegion dram1_mem;
101
+} Exynos4BoardState;
102
+
25
+
103
static int exynos4_board_id[EXYNOS4_NUM_OF_BOARDS] = {
26
if (is_a64(env)) {
104
[EXYNOS4_BOARD_NURI] = 0xD33,
27
*pc = env->pc;
105
[EXYNOS4_BOARD_SMDKC210] = 0xB16,
28
- *flags = ARM_TBFLAG_AARCH64_STATE_MASK;
106
@@ -XXX,XX +XXX,XX @@ static void lan9215_init(uint32_t base, qemu_irq irq)
29
+ flags = ARM_TBFLAG_AARCH64_STATE_MASK;
30
/* Get control bits for tagged addresses */
31
- *flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT);
32
- *flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
33
+ flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT);
34
+ flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
35
} else {
36
*pc = env->regs[15];
37
- *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
38
+ flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
39
| (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT)
40
| (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT)
41
| (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT)
42
| (arm_sctlr_b(env) << ARM_TBFLAG_SCTLR_B_SHIFT);
43
if (!(access_secure_reg(env))) {
44
- *flags |= ARM_TBFLAG_NS_MASK;
45
+ flags |= ARM_TBFLAG_NS_MASK;
46
}
47
if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
48
|| arm_el_is_aa64(env, 1)) {
49
- *flags |= ARM_TBFLAG_VFPEN_MASK;
50
+ flags |= ARM_TBFLAG_VFPEN_MASK;
51
}
52
- *flags |= (extract32(env->cp15.c15_cpar, 0, 2)
53
- << ARM_TBFLAG_XSCALE_CPAR_SHIFT);
54
+ flags |= (extract32(env->cp15.c15_cpar, 0, 2)
55
+ << ARM_TBFLAG_XSCALE_CPAR_SHIFT);
107
}
56
}
57
58
- *flags |= (arm_to_core_mmu_idx(mmu_idx) << ARM_TBFLAG_MMUIDX_SHIFT);
59
+ flags |= (arm_to_core_mmu_idx(mmu_idx) << ARM_TBFLAG_MMUIDX_SHIFT);
60
61
/* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
62
* states defined in the ARM ARM for software singlestep:
63
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
64
* 1 1 Active-not-pending
65
*/
66
if (arm_singlestep_active(env)) {
67
- *flags |= ARM_TBFLAG_SS_ACTIVE_MASK;
68
+ flags |= ARM_TBFLAG_SS_ACTIVE_MASK;
69
if (is_a64(env)) {
70
if (env->pstate & PSTATE_SS) {
71
- *flags |= ARM_TBFLAG_PSTATE_SS_MASK;
72
+ flags |= ARM_TBFLAG_PSTATE_SS_MASK;
73
}
74
} else {
75
if (env->uncached_cpsr & PSTATE_SS) {
76
- *flags |= ARM_TBFLAG_PSTATE_SS_MASK;
77
+ flags |= ARM_TBFLAG_PSTATE_SS_MASK;
78
}
79
}
80
}
81
if (arm_cpu_data_is_big_endian(env)) {
82
- *flags |= ARM_TBFLAG_BE_DATA_MASK;
83
+ flags |= ARM_TBFLAG_BE_DATA_MASK;
84
}
85
- *flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
86
+ flags |= fp_exception_el(env) << ARM_TBFLAG_FPEXC_EL_SHIFT;
87
88
if (arm_v7m_is_handler_mode(env)) {
89
- *flags |= ARM_TBFLAG_HANDLER_MASK;
90
+ flags |= ARM_TBFLAG_HANDLER_MASK;
91
}
92
93
+ *pflags = flags;
94
*cs_base = 0;
108
}
95
}
109
110
-static Exynos4210State *exynos4_boards_init_common(MachineState *machine,
111
- Exynos4BoardType board_type)
112
+static void exynos4_boards_init_ram(Exynos4BoardState *s,
113
+ MemoryRegion *system_mem,
114
+ unsigned long ram_size)
115
+{
116
+ unsigned long mem_size = ram_size;
117
+
118
+ if (mem_size > EXYNOS4210_DRAM_MAX_SIZE) {
119
+ memory_region_init_ram(&s->dram1_mem, NULL, "exynos4210.dram1",
120
+ mem_size - EXYNOS4210_DRAM_MAX_SIZE,
121
+ &error_fatal);
122
+ vmstate_register_ram_global(&s->dram1_mem);
123
+ memory_region_add_subregion(system_mem, EXYNOS4210_DRAM1_BASE_ADDR,
124
+ &s->dram1_mem);
125
+ mem_size = EXYNOS4210_DRAM_MAX_SIZE;
126
+ }
127
+
128
+ memory_region_init_ram(&s->dram0_mem, NULL, "exynos4210.dram0", mem_size,
129
+ &error_fatal);
130
+ vmstate_register_ram_global(&s->dram0_mem);
131
+ memory_region_add_subregion(system_mem, EXYNOS4210_DRAM0_BASE_ADDR,
132
+ &s->dram0_mem);
133
+}
134
+
135
+static Exynos4BoardState *
136
+exynos4_boards_init_common(MachineState *machine,
137
+ Exynos4BoardType board_type)
138
{
139
+ Exynos4BoardState *s = g_new(Exynos4BoardState, 1);
140
MachineClass *mc = MACHINE_GET_CLASS(machine);
141
142
if (smp_cpus != EXYNOS4210_NCPUS && !qtest_enabled()) {
143
@@ -XXX,XX +XXX,XX @@ static Exynos4210State *exynos4_boards_init_common(MachineState *machine,
144
machine->kernel_cmdline,
145
machine->initrd_filename);
146
147
- return exynos4210_init(get_system_memory(),
148
- exynos4_board_ram_size[board_type]);
149
+ exynos4_boards_init_ram(s, get_system_memory(),
150
+ exynos4_board_ram_size[board_type]);
151
+
152
+ s->soc = exynos4210_init(get_system_memory());
153
+
154
+ return s;
155
}
156
157
static void nuri_init(MachineState *machine)
158
@@ -XXX,XX +XXX,XX @@ static void nuri_init(MachineState *machine)
159
160
static void smdkc210_init(MachineState *machine)
161
{
162
- Exynos4210State *s = exynos4_boards_init_common(machine,
163
- EXYNOS4_BOARD_SMDKC210);
164
+ Exynos4BoardState *s = exynos4_boards_init_common(machine,
165
+ EXYNOS4_BOARD_SMDKC210);
166
167
lan9215_init(SMDK_LAN9118_BASE_ADDR,
168
- qemu_irq_invert(s->irq_table[exynos4210_get_irq(37, 1)]));
169
+ qemu_irq_invert(s->soc->irq_table[exynos4210_get_irq(37, 1)]));
170
arm_load_kernel(ARM_CPU(first_cpu), &exynos4_board_binfo);
171
}
172
173
--
96
--
174
2.7.4
97
2.7.4
175
98
176
99
diff view generated by jsdifflib
1
From: Krzysztof Kozlowski <krzk@kernel.org>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Statements under 'case' were in some places wrongly indented bringing
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
confusion and making the code less readable. Remove also few unneeded
4
Message-id: 20180119045438.28582-16-richard.henderson@linaro.org
5
blank lines. No functional changes.
6
7
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
8
---
12
hw/timer/exynos4210_mct.c | 45 ++++++++++++++++++++-------------------------
9
target/arm/helper.c | 3 ++-
13
1 file changed, 20 insertions(+), 25 deletions(-)
10
1 file changed, 2 insertions(+), 1 deletion(-)
14
11
15
diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/timer/exynos4210_mct.c
14
--- a/target/arm/helper.c
18
+++ b/hw/timer/exynos4210_mct.c
15
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ static uint64_t exynos4210_mct_read(void *opaque, hwaddr offset,
16
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes)
20
17
*/
21
case G_COMP_L(0): case G_COMP_L(1): case G_COMP_L(2): case G_COMP_L(3):
18
static inline int fp_exception_el(CPUARMState *env)
22
case G_COMP_U(0): case G_COMP_U(1): case G_COMP_U(2): case G_COMP_U(3):
19
{
23
- index = GET_G_COMP_IDX(offset);
20
+#ifndef CONFIG_USER_ONLY
24
- shift = 8 * (offset & 0x4);
21
int fpen;
25
- value = UINT32_MAX & (s->g_timer.reg.comp[index] >> shift);
22
int cur_el = arm_current_el(env);
26
+ index = GET_G_COMP_IDX(offset);
23
27
+ shift = 8 * (offset & 0x4);
24
@@ -XXX,XX +XXX,XX @@ static inline int fp_exception_el(CPUARMState *env)
28
+ value = UINT32_MAX & (s->g_timer.reg.comp[index] >> shift);
25
/* Trap all FP ops to EL3 */
29
break;
26
return 3;
30
27
}
31
case G_TCON:
32
@@ -XXX,XX +XXX,XX @@ static uint64_t exynos4210_mct_read(void *opaque, hwaddr offset,
33
lt_i = GET_L_TIMER_IDX(offset);
34
35
value = exynos4210_lfrc_get_count(&s->l_timer[lt_i]);
36
-
28
-
37
break;
29
+#endif
38
30
return 0;
39
case L0_TCON: case L1_TCON:
31
}
40
@@ -XXX,XX +XXX,XX @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
41
42
case G_COMP_L(0): case G_COMP_L(1): case G_COMP_L(2): case G_COMP_L(3):
43
case G_COMP_U(0): case G_COMP_U(1): case G_COMP_U(2): case G_COMP_U(3):
44
- index = GET_G_COMP_IDX(offset);
45
- shift = 8 * (offset & 0x4);
46
- s->g_timer.reg.comp[index] =
47
- (s->g_timer.reg.comp[index] &
48
- (((uint64_t)UINT32_MAX << 32) >> shift)) +
49
- (value << shift);
50
+ index = GET_G_COMP_IDX(offset);
51
+ shift = 8 * (offset & 0x4);
52
+ s->g_timer.reg.comp[index] =
53
+ (s->g_timer.reg.comp[index] &
54
+ (((uint64_t)UINT32_MAX << 32) >> shift)) +
55
+ (value << shift);
56
57
- DPRINTF("comparator %d write 0x%llx val << %d\n", index, value, shift);
58
+ DPRINTF("comparator %d write 0x%llx val << %d\n", index, value, shift);
59
60
- if (offset & 0x4) {
61
- s->g_timer.reg.wstat |= G_WSTAT_COMP_U(index);
62
- } else {
63
- s->g_timer.reg.wstat |= G_WSTAT_COMP_L(index);
64
- }
65
+ if (offset & 0x4) {
66
+ s->g_timer.reg.wstat |= G_WSTAT_COMP_U(index);
67
+ } else {
68
+ s->g_timer.reg.wstat |= G_WSTAT_COMP_L(index);
69
+ }
70
71
- exynos4210_gfrc_restart(s);
72
- break;
73
+ exynos4210_gfrc_restart(s);
74
+ break;
75
76
case G_TCON:
77
old_val = s->g_timer.reg.tcon;
78
@@ -XXX,XX +XXX,XX @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
79
break;
80
81
case G_INT_ENB:
82
-
83
/* Raise IRQ if transition from disabled to enabled and CSTAT pending */
84
for (i = 0; i < MCT_GT_CMP_NUM; i++) {
85
if ((value & G_INT_ENABLE(i)) > (s->g_timer.reg.tcon &
86
@@ -XXX,XX +XXX,XX @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
87
break;
88
89
case L0_TCNTB: case L1_TCNTB:
90
-
91
lt_i = GET_L_TIMER_IDX(offset);
92
index = GET_L_TIMER_CNT_REG_IDX(offset, lt_i);
93
94
@@ -XXX,XX +XXX,XX @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
95
break;
96
97
case L0_ICNTB: case L1_ICNTB:
98
-
99
lt_i = GET_L_TIMER_IDX(offset);
100
index = GET_L_TIMER_CNT_REG_IDX(offset, lt_i);
101
102
@@ -XXX,XX +XXX,XX @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
103
if (icntb_max[lt_i] < value) {
104
icntb_max[lt_i] = value;
105
}
106
-DPRINTF("local timer[%d] ICNTB write %llx; max=%x, min=%x\n\n",
107
- lt_i, value, icntb_max[lt_i], icntb_min[lt_i]);
108
+ DPRINTF("local timer[%d] ICNTB write %llx; max=%x, min=%x\n\n",
109
+ lt_i, value, icntb_max[lt_i], icntb_min[lt_i]);
110
#endif
111
-break;
112
+ break;
113
114
case L0_FRCNTB: case L1_FRCNTB:
115
-
116
lt_i = GET_L_TIMER_IDX(offset);
117
index = GET_L_TIMER_CNT_REG_IDX(offset, lt_i);
118
32
119
--
33
--
120
2.7.4
34
2.7.4
121
35
122
36
diff view generated by jsdifflib
1
From: Krzysztof Kozlowski <krzk@kernel.org>
1
From: Luc MICHEL <luc.michel@git.antfield.fr>
2
2
3
Remove defines not used anywhere.
3
In the GIC, when an IRQ is acknowledged, its state goes from "pending"
4
to:
5
- "active" if the corresponding IRQ pin has been de-asserted
6
- "active and pending" otherwise.
7
The GICv2 manual states that when a IRQ becomes active (or active and
8
pending), the GIC should either signal another (higher priority) IRQ to
9
the CPU if there is one, or de-assert the CPU IRQ pin.
4
10
5
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
11
The current implementation of the GIC in QEMU does not check if the
12
IRQ is already active when looking for pending interrupts with
13
sufficient priority in gic_update(). This can lead to signaling an
14
interrupt that is already active.
15
16
This usually happens when splitting priority drop and interrupt
17
deactivation. On priority drop, the IRQ stays active until deactivation.
18
If it becomes pending again, chances are that it will be incorrectly
19
selected as best_irq in gic_update().
20
21
This commit fixes this by checking if the IRQ is not already active when
22
looking for best_irq in gic_update().
23
24
Note that regarding the ARM11MPCore GIC version, the corresponding
25
manual is not clear on that point, but it has has no priority
26
drop/interrupt deactivation separation, so this case should not happen.
27
28
Signed-off-by: Luc MICHEL <luc.michel@git.antfield.fr>
29
Message-id: 20180119145756.7629-3-luc.michel@greensocs.com
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
30
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
31
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
32
---
9
hw/timer/exynos4210_mct.c | 3 ---
33
hw/intc/arm_gic.c | 1 +
10
1 file changed, 3 deletions(-)
34
1 file changed, 1 insertion(+)
11
35
12
diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c
36
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
13
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/timer/exynos4210_mct.c
38
--- a/hw/intc/arm_gic.c
15
+++ b/hw/timer/exynos4210_mct.c
39
+++ b/hw/intc/arm_gic.c
16
@@ -XXX,XX +XXX,XX @@ enum LocalTimerRegCntIndexes {
40
@@ -XXX,XX +XXX,XX @@ void gic_update(GICState *s)
17
L_REG_CNT_AMOUNT
41
best_irq = 1023;
18
};
42
for (irq = 0; irq < s->num_irq; irq++) {
19
43
if (GIC_TEST_ENABLED(irq, cm) && gic_test_pending(s, irq, cm) &&
20
-#define MCT_NIRQ 6
44
+ (!GIC_TEST_ACTIVE(irq, cm)) &&
21
#define MCT_SFR_SIZE 0x444
45
(irq < GIC_INTERNAL || GIC_TARGET(irq) & cm)) {
22
46
if (GIC_GET_PRIORITY(irq, cpu) < best_prio) {
23
#define MCT_GT_CMP_NUM 4
47
best_prio = GIC_GET_PRIORITY(irq, cpu);
24
25
-#define MCT_GT_MAX_VAL UINT64_MAX
26
-
27
#define MCT_GT_COUNTER_STEP 0x100000000ULL
28
#define MCT_LT_COUNTER_STEP 0x100000000ULL
29
#define MCT_LT_CNT_LOW_LIMIT 0x100
30
--
48
--
31
2.7.4
49
2.7.4
32
50
33
51
diff view generated by jsdifflib
1
From: Krzysztof Kozlowski <krzk@kernel.org>
1
From: Luc MICHEL <luc.michel@git.antfield.fr>
2
2
3
Fix checkpatch errors:
3
When there is no active interrupts in the GIC, a read to the C_RPR
4
1. ERROR: spaces required around that '+' (ctx:VxV)
4
register should return the value of the "Idle priority", which is either
5
2. ERROR: spaces required around that '&' (ctx:VxV)
5
the maximum value an IRQ priority field can be set to, or 0xff.
6
6
7
No functional changes.
7
Since the QEMU GIC model implements all the 8 priority bits, the Idle
8
priority is 0xff.
8
9
9
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
10
Internally, when there is no active interrupt, the running priority
11
value is 0x100. The gic_get_running_priority function returns an uint8_t
12
and thus, truncate this value to 0x00 when returning it. This is wrong since
13
a value of 0x00 correspond to the maximum possible priority.
14
15
This commit fixes the returned value when the internal value is 0x100.
16
17
Note that it is correct for the Non-Secure view to return 0xff even
18
though from the NS world point of view, only 7 priority bits are
19
implemented. The specification states that the Idle priority can be 0xff
20
even when not all the 8 priority bits are implemented. This has been
21
verified against a real GICv2 hardware on a Xilinx ZynqMP based board.
22
23
Regarding the ARM11MPCore version of the GIC, the specification is not
24
clear on that point, so this commit does not alter its behavior.
25
26
Signed-off-by: Luc MICHEL <luc.michel@git.antfield.fr>
27
Message-id: 20180119145756.7629-4-luc.michel@greensocs.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
28
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
30
---
14
hw/timer/exynos4210_mct.c | 4 ++--
31
hw/intc/arm_gic.c | 5 +++++
15
1 file changed, 2 insertions(+), 2 deletions(-)
32
1 file changed, 5 insertions(+)
16
33
17
diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c
34
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
18
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/timer/exynos4210_mct.c
36
--- a/hw/intc/arm_gic.c
20
+++ b/hw/timer/exynos4210_mct.c
37
+++ b/hw/intc/arm_gic.c
21
@@ -XXX,XX +XXX,XX @@ static void exynos4210_mct_update_freq(Exynos4210MCTState *s)
38
@@ -XXX,XX +XXX,XX @@ static void gic_set_cpu_control(GICState *s, int cpu, uint32_t value,
39
40
static uint8_t gic_get_running_priority(GICState *s, int cpu, MemTxAttrs attrs)
22
{
41
{
23
uint32_t freq = s->freq;
42
+ if ((s->revision != REV_11MPCORE) && (s->running_priority[cpu] > 0xff)) {
24
s->freq = 24000000 /
43
+ /* Idle priority */
25
- ((MCT_CFG_GET_PRESCALER(s->reg_mct_cfg)+1) *
44
+ return 0xff;
26
+ ((MCT_CFG_GET_PRESCALER(s->reg_mct_cfg) + 1) *
45
+ }
27
MCT_CFG_GET_DIVIDER(s->reg_mct_cfg));
46
+
28
47
if (s->security_extn && !attrs.secure) {
29
if (freq != s->freq) {
48
if (s->running_priority[cpu] & 0x80) {
30
@@ -XXX,XX +XXX,XX @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
49
/* Running priority in upper half of range: return the Non-secure
31
32
DPRINTF("comparator %d write 0x%llx val << %d\n", index, value, shift);
33
34
- if (offset&0x4) {
35
+ if (offset & 0x4) {
36
s->g_timer.reg.wstat |= G_WSTAT_COMP_U(index);
37
} else {
38
s->g_timer.reg.wstat |= G_WSTAT_COMP_L(index);
39
--
50
--
40
2.7.4
51
2.7.4
41
52
42
53
diff view generated by jsdifflib
1
From: Krzysztof Kozlowski <krzk@kernel.org>
1
From: Luc MICHEL <luc.michel@git.antfield.fr>
2
2
3
Use a define for a9mpcore_priv device type name instead of hard-coded
3
When determining the group priority of a group 1 IRQ, if C_CTRL.CBPR is
4
string.
4
0, the non-secure BPR value is used. However, this value must be
5
incremented by one so that it matches the secure world number of
6
implemented priority bits (NS world has one less priority bit compared
7
to the Secure world).
5
8
6
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
9
Signed-off-by: Luc MICHEL <luc.michel@git.antfield.fr>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20180119145756.7629-5-luc.michel@greensocs.com
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
[PMM: add assert, as the gicv3 code has]
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
14
---
10
hw/arm/exynos4210.c | 3 ++-
15
hw/intc/arm_gic.c | 3 ++-
11
1 file changed, 2 insertions(+), 1 deletion(-)
16
1 file changed, 2 insertions(+), 1 deletion(-)
12
17
13
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
18
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
14
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/exynos4210.c
20
--- a/hw/intc/arm_gic.c
16
+++ b/hw/arm/exynos4210.c
21
+++ b/hw/intc/arm_gic.c
17
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ static int gic_get_group_priority(GICState *s, int cpu, int irq)
18
#include "qemu-common.h"
23
if (gic_has_groups(s) &&
19
#include "qemu/log.h"
24
!(s->cpu_ctlr[cpu] & GICC_CTLR_CBPR) &&
20
#include "cpu.h"
25
GIC_TEST_GROUP(irq, (1 << cpu))) {
21
+#include "hw/cpu/a9mpcore.h"
26
- bpr = s->abpr[cpu];
22
#include "hw/boards.h"
27
+ bpr = s->abpr[cpu] - 1;
23
#include "sysemu/sysemu.h"
28
+ assert(bpr >= 0);
24
#include "hw/sysbus.h"
29
} else {
25
@@ -XXX,XX +XXX,XX @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem)
30
bpr = s->bpr[cpu];
26
}
31
}
27
28
/* Private memory region and Internal GIC */
29
- dev = qdev_create(NULL, "a9mpcore_priv");
30
+ dev = qdev_create(NULL, TYPE_A9MPCORE_PRIV);
31
qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
32
qdev_init_nofail(dev);
33
busdev = SYS_BUS_DEVICE(dev);
34
--
32
--
35
2.7.4
33
2.7.4
36
34
37
35
diff view generated by jsdifflib
1
From: Krzysztof Kozlowski <krzk@kernel.org>
1
From: Luc MICHEL <luc.michel@git.antfield.fr>
2
2
3
There are to SysBusDevice variables in exynos4210_gic_realize()
3
When C_CTRL.CBPR is 1, the Non-Secure view of C_BPR is altered:
4
function: one for the device itself and second for arm_gic device. Add
4
- A Non-Secure read of C_BPR should return the BPR value plus 1,
5
a prefix "gic" to the second one so it will be easier to understand the
5
saturated to 7,
6
code.
6
- A Non-Secure write should be ignored.
7
7
8
While at it, put local uninitialized 'i' variable at the end, next to
8
Signed-off-by: Luc MICHEL <luc.michel@git.antfield.fr>
9
other uninitialized ones.
9
Message-id: 20180119145756.7629-6-luc.michel@greensocs.com
10
11
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
[PMM: fixed comment typo]
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
13
---
16
hw/intc/exynos4210_gic.c | 12 ++++++------
14
hw/intc/arm_gic.c | 16 +++++++++++++---
17
1 file changed, 6 insertions(+), 6 deletions(-)
15
1 file changed, 13 insertions(+), 3 deletions(-)
18
16
19
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
17
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
20
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/intc/exynos4210_gic.c
19
--- a/hw/intc/arm_gic.c
22
+++ b/hw/intc/exynos4210_gic.c
20
+++ b/hw/intc/arm_gic.c
23
@@ -XXX,XX +XXX,XX @@ static void exynos4210_gic_init(Object *obj)
21
@@ -XXX,XX +XXX,XX @@ static MemTxResult gic_cpu_read(GICState *s, int cpu, int offset,
24
DeviceState *dev = DEVICE(obj);
22
break;
25
Exynos4210GicState *s = EXYNOS4210_GIC(obj);
23
case 0x08: /* Binary Point */
26
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
24
if (s->security_extn && !attrs.secure) {
27
- uint32_t i;
25
- /* BPR is banked. Non-secure copy stored in ABPR. */
28
const char cpu_prefix[] = "exynos4210-gic-alias_cpu";
26
- *data = s->abpr[cpu];
29
const char dist_prefix[] = "exynos4210-gic-alias_dist";
27
+ if (s->cpu_ctlr[cpu] & GICC_CTLR_CBPR) {
30
char cpu_alias_name[sizeof(cpu_prefix) + 3];
28
+ /* NS view of BPR when CBPR is 1 */
31
char dist_alias_name[sizeof(cpu_prefix) + 3];
29
+ *data = MIN(s->bpr[cpu] + 1, 7);
32
- SysBusDevice *busdev;
30
+ } else {
33
+ SysBusDevice *gicbusdev;
31
+ /* BPR is banked. Non-secure copy stored in ABPR. */
34
+ uint32_t i;
32
+ *data = s->abpr[cpu];
35
33
+ }
36
s->gic = qdev_create(NULL, "arm_gic");
34
} else {
37
qdev_prop_set_uint32(s->gic, "num-cpu", s->num_cpu);
35
*data = s->bpr[cpu];
38
qdev_prop_set_uint32(s->gic, "num-irq", EXYNOS4210_GIC_NIRQ);
36
}
39
qdev_init_nofail(s->gic);
37
@@ -XXX,XX +XXX,XX @@ static MemTxResult gic_cpu_write(GICState *s, int cpu, int offset,
40
- busdev = SYS_BUS_DEVICE(s->gic);
38
break;
41
+ gicbusdev = SYS_BUS_DEVICE(s->gic);
39
case 0x08: /* Binary Point */
42
40
if (s->security_extn && !attrs.secure) {
43
/* Pass through outbound IRQ lines from the GIC */
41
- s->abpr[cpu] = MAX(value & 0x7, GIC_MIN_ABPR);
44
- sysbus_pass_irq(sbd, busdev);
42
+ if (s->cpu_ctlr[cpu] & GICC_CTLR_CBPR) {
45
+ sysbus_pass_irq(sbd, gicbusdev);
43
+ /* WI when CBPR is 1 */
46
44
+ return MEMTX_OK;
47
/* Pass through inbound GPIO lines to the GIC */
45
+ } else {
48
qdev_init_gpio_in(dev, exynos4210_gic_set_irq,
46
+ s->abpr[cpu] = MAX(value & 0x7, GIC_MIN_ABPR);
49
@@ -XXX,XX +XXX,XX @@ static void exynos4210_gic_init(Object *obj)
47
+ }
50
sprintf(cpu_alias_name, "%s%x", cpu_prefix, i);
48
} else {
51
memory_region_init_alias(&s->cpu_alias[i], obj,
49
s->bpr[cpu] = MAX(value & 0x7, GIC_MIN_BPR);
52
cpu_alias_name,
50
}
53
- sysbus_mmio_get_region(busdev, 1),
54
+ sysbus_mmio_get_region(gicbusdev, 1),
55
0,
56
EXYNOS4210_GIC_CPU_REGION_SIZE);
57
memory_region_add_subregion(&s->cpu_container,
58
@@ -XXX,XX +XXX,XX @@ static void exynos4210_gic_init(Object *obj)
59
sprintf(dist_alias_name, "%s%x", dist_prefix, i);
60
memory_region_init_alias(&s->dist_alias[i], obj,
61
dist_alias_name,
62
- sysbus_mmio_get_region(busdev, 0),
63
+ sysbus_mmio_get_region(gicbusdev, 0),
64
0,
65
EXYNOS4210_GIC_DIST_REGION_SIZE);
66
memory_region_add_subregion(&s->dist_container,
67
--
51
--
68
2.7.4
52
2.7.4
69
53
70
54
diff view generated by jsdifflib
1
From: Krzysztof Kozlowski <krzk@kernel.org>
1
We were passing a NULL error pointer to the object_property_set_bool()
2
call that realizes the CPU object. This meant that we wouldn't detect
3
failure, and would plough blindly on to crash later trying to use a
4
NULL CPU object pointer. Detect errors and fail instead.
2
5
3
The static array of interrupt combiner mappings is not modified so it
6
In particular, this will be necessary to detect the user error
4
can be made const for code safeness.
7
of using "-cpu host" without "-enable-kvm" once we make the host
8
CPU type be registered unconditionally rather than only in
9
kvm_arch_init().
5
10
6
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
12
---
10
hw/intc/exynos4210_gic.c | 2 +-
13
hw/arm/virt.c | 2 +-
11
1 file changed, 1 insertion(+), 1 deletion(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
12
15
13
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
16
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
14
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/intc/exynos4210_gic.c
18
--- a/hw/arm/virt.c
16
+++ b/hw/intc/exynos4210_gic.c
19
+++ b/hw/arm/virt.c
17
@@ -XXX,XX +XXX,XX @@ enum ExtInt {
20
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
18
* which is INTG16 in Internal Interrupt Combiner.
21
"secure-memory", &error_abort);
19
*/
22
}
20
23
21
-static uint32_t
24
- object_property_set_bool(cpuobj, true, "realized", NULL);
22
+static const uint32_t
25
+ object_property_set_bool(cpuobj, true, "realized", &error_fatal);
23
combiner_grp_to_gic_id[64-EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
26
object_unref(cpuobj);
24
/* int combiner groups 16-19 */
27
}
25
{ }, { }, { }, { },
28
fdt_add_timer_nodes(vms);
26
--
29
--
27
2.7.4
30
2.7.4
28
31
29
32
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
In some circumstances, we don't want to abort if the
3
missed in 60765b6ceeb4.
4
kvm_device_access fails. This will be the case during ITS
5
migration, in case the ITS table save/restore fails because
6
the guest did not program the vITS correctly. So let's pass an
7
error object to the function and return the ioctl value. New
8
callers will be able to make a decision upon this returned
9
value.
10
4
11
Existing callers pass &error_abort which will cause the
5
Thread 1 "qemu-system-aarch64" received signal SIGSEGV, Segmentation fault.
12
function to abort on failure.
6
address_space_init (as=0x0, root=0x55555726e410, name=name@entry=0x555555e3f0a7 "sdhci-dma") at memory.c:3050
7
3050     as->root = root;
8
(gdb) bt
9
#0 address_space_init (as=0x0, root=0x55555726e410, name=name@entry=0x555555e3f0a7 "sdhci-dma") at memory.c:3050
10
#1 0x0000555555af62c3 in sdhci_sysbus_realize (dev=<optimized out>, errp=0x7fff7f931150) at hw/sd/sdhci.c:1564
11
#2 0x00005555558b25e5 in zynqmp_sdhci_realize (dev=0x555557051520, errp=0x7fff7f931150) at hw/sd/zynqmp-sdhci.c:151
12
#3 0x0000555555a2e7f3 in device_set_realized (obj=0x555557051520, value=<optimized out>, errp=0x7fff7f931270) at hw/core/qdev.c:966
13
#4 0x0000555555ba3f74 in property_set_bool (obj=0x555557051520, v=<optimized out>, name=<optimized out>, opaque=0x555556e04a20,
14
errp=0x7fff7f931270) at qom/object.c:1906
15
#5 0x0000555555ba51f4 in object_property_set (obj=obj@entry=0x555557051520, v=v@entry=0x5555576dbd60,
16
name=name@entry=0x555555dd6306 "realized", errp=errp@entry=0x7fff7f931270) at qom/object.c:1102
13
17
14
Signed-off-by: Eric Auger <eric.auger@redhat.com>
18
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Juan Quintela <quintela@redhat.com>
19
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Reviewed-by: Peter Xu <peterx@redhat.com>
20
Message-id: 20180123132051.24448-1-f4bug@amsat.org
17
Message-id: 1497023553-18411-2-git-send-email-eric.auger@redhat.com
21
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
[PMM: wrapped long line]
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
23
---
21
include/sysemu/kvm.h | 11 +++++++----
24
include/hw/sd/sdhci.h | 1 +
22
hw/intc/arm_gic_kvm.c | 9 +++++----
25
hw/sd/sdhci.c | 1 +
23
hw/intc/arm_gicv3_its_kvm.c | 2 +-
26
2 files changed, 2 insertions(+)
24
hw/intc/arm_gicv3_kvm.c | 14 +++++++-------
25
kvm-all.c | 14 ++++++++------
26
5 files changed, 28 insertions(+), 22 deletions(-)
27
27
28
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
28
diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
29
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
30
--- a/include/sysemu/kvm.h
30
--- a/include/hw/sd/sdhci.h
31
+++ b/include/sysemu/kvm.h
31
+++ b/include/hw/sd/sdhci.h
32
@@ -XXX,XX +XXX,XX @@ int kvm_device_check_attr(int fd, uint32_t group, uint64_t attr);
32
@@ -XXX,XX +XXX,XX @@ typedef struct SDHCIState {
33
* @attr: the attribute of that group to set or get
33
/*< public >*/
34
* @val: pointer to a storage area for the value
34
SDBus sdbus;
35
* @write: true for set and false for get operation
35
MemoryRegion iomem;
36
+ * @errp: error object handle
36
+ AddressSpace sysbus_dma_as;
37
*
37
AddressSpace *dma_as;
38
- * This function is not allowed to fail. Use kvm_device_check_attr()
38
MemoryRegion *dma_mr;
39
- * in order to check for the availability of optional attributes.
39
40
+ * Returns: 0 on success
40
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
41
+ * < 0 on error
42
+ * Use kvm_device_check_attr() in order to check for the availability
43
+ * of optional attributes.
44
*/
45
-void kvm_device_access(int fd, int group, uint64_t attr,
46
- void *val, bool write);
47
+int kvm_device_access(int fd, int group, uint64_t attr,
48
+ void *val, bool write, Error **errp);
49
50
/**
51
* kvm_create_device - create a KVM device for the device control API
52
diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
53
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
54
--- a/hw/intc/arm_gic_kvm.c
42
--- a/hw/sd/sdhci.c
55
+++ b/hw/intc/arm_gic_kvm.c
43
+++ b/hw/sd/sdhci.c
56
@@ -XXX,XX +XXX,XX @@ static void kvm_gicd_access(GICState *s, int offset, int cpu,
44
@@ -XXX,XX +XXX,XX @@ static void sdhci_sysbus_realize(DeviceState *dev, Error ** errp)
57
uint32_t *val, bool write)
58
{
59
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
60
- KVM_VGIC_ATTR(offset, cpu), val, write);
61
+ KVM_VGIC_ATTR(offset, cpu), val, write, &error_abort);
62
}
63
64
static void kvm_gicc_access(GICState *s, int offset, int cpu,
65
uint32_t *val, bool write)
66
{
67
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CPU_REGS,
68
- KVM_VGIC_ATTR(offset, cpu), val, write);
69
+ KVM_VGIC_ATTR(offset, cpu), val, write, &error_abort);
70
}
71
72
#define for_each_irq_reg(_ctr, _max_irq, _field_width) \
73
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
74
if (kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0)) {
75
uint32_t numirqs = s->num_irq;
76
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0,
77
- &numirqs, true);
78
+ &numirqs, true, &error_abort);
79
}
80
/* Tell the kernel to complete VGIC initialization now */
81
if (kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
82
KVM_DEV_ARM_VGIC_CTRL_INIT)) {
83
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
84
- KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true);
85
+ KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true,
86
+ &error_abort);
87
}
88
} else if (ret != -ENODEV && ret != -ENOTSUP) {
89
error_setg_errno(errp, -ret, "error creating in-kernel VGIC");
90
diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c
91
index XXXXXXX..XXXXXXX 100644
92
--- a/hw/intc/arm_gicv3_its_kvm.c
93
+++ b/hw/intc/arm_gicv3_its_kvm.c
94
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_its_realize(DeviceState *dev, Error **errp)
95
96
/* explicit init of the ITS */
97
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
98
- KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true);
99
+ KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true, &error_abort);
100
101
/* register the base address */
102
kvm_arm_register_device(&s->iomem_its_cntrl, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
103
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
104
index XXXXXXX..XXXXXXX 100644
105
--- a/hw/intc/arm_gicv3_kvm.c
106
+++ b/hw/intc/arm_gicv3_kvm.c
107
@@ -XXX,XX +XXX,XX @@ static inline void kvm_gicd_access(GICv3State *s, int offset,
108
{
109
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
110
KVM_VGIC_ATTR(offset, 0),
111
- val, write);
112
+ val, write, &error_abort);
113
}
114
115
static inline void kvm_gicr_access(GICv3State *s, int offset, int cpu,
116
@@ -XXX,XX +XXX,XX @@ static inline void kvm_gicr_access(GICv3State *s, int offset, int cpu,
117
{
118
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_REDIST_REGS,
119
KVM_VGIC_ATTR(offset, s->cpu[cpu].gicr_typer),
120
- val, write);
121
+ val, write, &error_abort);
122
}
123
124
static inline void kvm_gicc_access(GICv3State *s, uint64_t reg, int cpu,
125
@@ -XXX,XX +XXX,XX @@ static inline void kvm_gicc_access(GICv3State *s, uint64_t reg, int cpu,
126
{
127
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
128
KVM_VGIC_ATTR(reg, s->cpu[cpu].gicr_typer),
129
- val, write);
130
+ val, write, &error_abort);
131
}
132
133
static inline void kvm_gic_line_level_access(GICv3State *s, int irq, int cpu,
134
@@ -XXX,XX +XXX,XX @@ static inline void kvm_gic_line_level_access(GICv3State *s, int irq, int cpu,
135
KVM_VGIC_ATTR(irq, s->cpu[cpu].gicr_typer) |
136
(VGIC_LEVEL_INFO_LINE_LEVEL <<
137
KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT),
138
- val, write);
139
+ val, write, &error_abort);
140
}
141
142
/* Loop through each distributor IRQ related register; since bits
143
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_icc_reset(CPUARMState *env, const ARMCPRegInfo *ri)
144
/* Initialize to actual HW supported configuration */
145
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS,
146
KVM_VGIC_ATTR(ICC_CTLR_EL1, cpu->mp_affinity),
147
- &c->icc_ctlr_el1[GICV3_NS], false);
148
+ &c->icc_ctlr_el1[GICV3_NS], false, &error_abort);
149
150
c->icc_ctlr_el1[GICV3_S] = c->icc_ctlr_el1[GICV3_NS];
151
}
152
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
153
}
45
}
154
46
155
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS,
47
if (s->dma_mr) {
156
- 0, &s->num_irq, true);
48
+ s->dma_as = &s->sysbus_dma_as;
157
+ 0, &s->num_irq, true, &error_abort);
49
address_space_init(s->dma_as, s->dma_mr, "sdhci-dma");
158
50
} else {
159
/* Tell the kernel to complete VGIC initialization now */
51
/* use system_memory() if property "dma" not set */
160
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
161
- KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true);
162
+ KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true, &error_abort);
163
164
kvm_arm_register_device(&s->iomem_dist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
165
KVM_VGIC_V3_ADDR_TYPE_DIST, s->dev_fd);
166
diff --git a/kvm-all.c b/kvm-all.c
167
index XXXXXXX..XXXXXXX 100644
168
--- a/kvm-all.c
169
+++ b/kvm-all.c
170
@@ -XXX,XX +XXX,XX @@
171
#include "qemu/option.h"
172
#include "qemu/config-file.h"
173
#include "qemu/error-report.h"
174
+#include "qapi/error.h"
175
#include "hw/hw.h"
176
#include "hw/pci/msi.h"
177
#include "hw/pci/msix.h"
178
@@ -XXX,XX +XXX,XX @@ int kvm_device_check_attr(int dev_fd, uint32_t group, uint64_t attr)
179
return kvm_device_ioctl(dev_fd, KVM_HAS_DEVICE_ATTR, &attribute) ? 0 : 1;
180
}
181
182
-void kvm_device_access(int fd, int group, uint64_t attr,
183
- void *val, bool write)
184
+int kvm_device_access(int fd, int group, uint64_t attr,
185
+ void *val, bool write, Error **errp)
186
{
187
struct kvm_device_attr kvmattr;
188
int err;
189
@@ -XXX,XX +XXX,XX @@ void kvm_device_access(int fd, int group, uint64_t attr,
190
write ? KVM_SET_DEVICE_ATTR : KVM_GET_DEVICE_ATTR,
191
&kvmattr);
192
if (err < 0) {
193
- error_report("KVM_%s_DEVICE_ATTR failed: %s",
194
- write ? "SET" : "GET", strerror(-err));
195
- error_printf("Group %d attr 0x%016" PRIx64 "\n", group, attr);
196
- abort();
197
+ error_setg_errno(errp, -err,
198
+ "KVM_%s_DEVICE_ATTR failed: Group %d "
199
+ "attr 0x%016" PRIx64,
200
+ write ? "SET" : "GET", group, attr);
201
}
202
+ return err;
203
}
204
205
/* Return 1 on success, 0 on failure */
206
--
52
--
207
2.7.4
53
2.7.4
208
54
209
55
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Francisco Iglesias <frasse.iglesias@gmail.com>
2
2
3
This patch adds the flush of the LPI pending bits into the
3
Coverity found that the variable tx_rx in the function
4
redistributor pending tables. This happens on VM stop.
4
xilinx_spips_flush_txfifo was being used uninitialized (CID 1383841). This
5
patch corrects this by always initializing tx_rx to zeros.
5
6
6
There is no explicit restore as the tables are implicitly sync'ed
7
Signed-off-by: Francisco Iglesias <frasse.iglesias@gmail.com>
7
on ITS table restore and on LPI enable at redistributor level.
8
Message-id: 20180124215708.30400-1-frasse.iglesias@gmail.com
8
9
Signed-off-by: Eric Auger <eric.auger@redhat.com>
10
Message-id: 1497023553-18411-4-git-send-email-eric.auger@redhat.com
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
11
---
14
hw/intc/arm_gicv3_kvm.c | 34 ++++++++++++++++++++++++++++++++++
12
hw/ssi/xilinx_spips.c | 18 +++++++++++++++++-
15
1 file changed, 34 insertions(+)
13
1 file changed, 17 insertions(+), 1 deletion(-)
16
14
17
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
15
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/intc/arm_gicv3_kvm.c
17
--- a/hw/ssi/xilinx_spips.c
20
+++ b/hw/intc/arm_gicv3_kvm.c
18
+++ b/hw/ssi/xilinx_spips.c
21
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
22
#include "hw/sysbus.h"
20
#define SNOOP_NONE 0xEE
23
#include "qemu/error-report.h"
21
#define SNOOP_STRIPING 0
24
#include "sysemu/kvm.h"
22
25
+#include "sysemu/sysemu.h"
23
+#define MIN_NUM_BUSSES 1
26
#include "kvm_arm.h"
24
+#define MAX_NUM_BUSSES 2
27
#include "gicv3_internal.h"
28
#include "vgic_common.h"
29
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
30
REGINFO_SENTINEL
31
};
32
33
+/**
34
+ * vm_change_state_handler - VM change state callback aiming at flushing
35
+ * RDIST pending tables into guest RAM
36
+ *
37
+ * The tables get flushed to guest RAM whenever the VM gets stopped.
38
+ */
39
+static void vm_change_state_handler(void *opaque, int running,
40
+ RunState state)
41
+{
42
+ GICv3State *s = (GICv3State *)opaque;
43
+ Error *err = NULL;
44
+ int ret;
45
+
25
+
46
+ if (running) {
26
static inline int num_effective_busses(XilinxSPIPS *s)
27
{
28
return (s->regs[R_LQSPI_CFG] & LQSPI_CFG_SEP_BUS &&
29
@@ -XXX,XX +XXX,XX @@ static void xilinx_spips_flush_txfifo(XilinxSPIPS *s)
30
for (;;) {
31
int i;
32
uint8_t tx = 0;
33
- uint8_t tx_rx[num_effective_busses(s)];
34
+ uint8_t tx_rx[MAX_NUM_BUSSES] = { 0 };
35
uint8_t dummy_cycles = 0;
36
uint8_t addr_length;
37
38
@@ -XXX,XX +XXX,XX @@ static void xilinx_spips_realize(DeviceState *dev, Error **errp)
39
40
DB_PRINT_L(0, "realized spips\n");
41
42
+ if (s->num_busses > MAX_NUM_BUSSES) {
43
+ error_setg(errp,
44
+ "requested number of SPI busses %u exceeds maximum %d",
45
+ s->num_busses, MAX_NUM_BUSSES);
46
+ return;
47
+ }
48
+ if (s->num_busses < MIN_NUM_BUSSES) {
49
+ error_setg(errp,
50
+ "requested number of SPI busses %u is below minimum %d",
51
+ s->num_busses, MIN_NUM_BUSSES);
47
+ return;
52
+ return;
48
+ }
53
+ }
49
+
54
+
50
+ ret = kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
55
s->spi = g_new(SSIBus *, s->num_busses);
51
+ KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES,
56
for (i = 0; i < s->num_busses; ++i) {
52
+ NULL, true, &err);
57
char bus_name[16];
53
+ if (err) {
54
+ error_report_err(err);
55
+ }
56
+ if (ret < 0 && ret != -EFAULT) {
57
+ abort();
58
+ }
59
+}
60
+
61
+
62
static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
63
{
64
GICv3State *s = KVM_ARM_GICV3(dev);
65
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
66
return;
67
}
68
}
69
+ if (kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
70
+ KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES)) {
71
+ qemu_add_vm_change_state_handler(vm_change_state_handler, s);
72
+ }
73
}
74
75
static void kvm_arm_gicv3_class_init(ObjectClass *klass, void *data)
76
--
58
--
77
2.7.4
59
2.7.4
78
60
79
61
diff view generated by jsdifflib
1
From: Cédric Le Goater <clg@kaod.org>
1
From: Linus Walleij <linus.walleij@linaro.org>
2
2
3
When a timer is enabled before a reload value is set, the controller
3
This implements rudimentary support for interrupt generation on the
4
waits for a reload value to be set before starting decrementing. This
4
PL110. I am working on a new DRI/KMS driver for Linux and since that
5
fix tries to cover that case by changing the timer expiry only when
5
uses the blanking interrupt, we need something to fire here. Without
6
a reload value is valid.
6
any interrupt support Linux waits for a while and then gives ugly
7
messages about the vblank not working in the console (it does not
8
hang perpetually or anything though, DRI is pretty forgiving).
7
9
8
Signed-off-by: Cédric Le Goater <clg@kaod.org>
10
I solved it for now by setting up a timer to fire at 60Hz and pull
9
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
11
the interrupts for "vertical compare" and "next memory base"
10
Message-id: 1496739312-32304-1-git-send-email-clg@kaod.org
12
at this interval. This works fine and fires roughly the same number
13
of IRQs on QEMU as on the hardware and leaves the console clean
14
and nice.
15
16
People who want to create more accurate emulation can probably work
17
on top of this if need be. It is certainly closer to the hardware
18
behaviour than what we have today anyway.
19
20
Cc: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
22
Message-id: 20180123225654.5764-1-linus.walleij@linaro.org
23
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
24
[PMM: folded long lines]
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
26
---
13
hw/timer/aspeed_timer.c | 37 +++++++++++++++++++++++++++++--------
27
hw/display/pl110.c | 30 +++++++++++++++++++++++++++++-
14
1 file changed, 29 insertions(+), 8 deletions(-)
28
1 file changed, 29 insertions(+), 1 deletion(-)
15
29
16
diff --git a/hw/timer/aspeed_timer.c b/hw/timer/aspeed_timer.c
30
diff --git a/hw/display/pl110.c b/hw/display/pl110.c
17
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/timer/aspeed_timer.c
32
--- a/hw/display/pl110.c
19
+++ b/hw/timer/aspeed_timer.c
33
+++ b/hw/display/pl110.c
20
@@ -XXX,XX +XXX,XX @@ static uint64_t calculate_next(struct AspeedTimer *t)
34
@@ -XXX,XX +XXX,XX @@
21
next = seq[1];
35
#include "ui/console.h"
22
} else if (now < seq[2]) {
36
#include "framebuffer.h"
23
next = seq[2];
37
#include "ui/pixel_ops.h"
24
- } else {
38
+#include "qemu/timer.h"
25
+ } else if (t->reload) {
39
#include "qemu/log.h"
26
reload_ns = muldiv64(t->reload, NANOSECONDS_PER_SECOND, rate);
40
27
t->start = now - ((now - t->start) % reload_ns);
41
#define PL110_CR_EN 0x001
28
+ } else {
42
@@ -XXX,XX +XXX,XX @@
29
+ /* no reload value, return 0 */
43
#define PL110_CR_BEBO 0x200
30
+ break;
44
#define PL110_CR_BEPO 0x400
31
}
45
#define PL110_CR_PWR 0x800
32
}
46
+#define PL110_IE_NB 0x004
33
47
+#define PL110_IE_VC 0x008
34
return next;
48
35
}
49
enum pl110_bppmode
36
50
{
37
+static void aspeed_timer_mod(AspeedTimer *t)
51
@@ -XXX,XX +XXX,XX @@ typedef struct PL110State {
38
+{
52
MemoryRegion iomem;
39
+ uint64_t next = calculate_next(t);
53
MemoryRegionSection fbsection;
40
+ if (next) {
54
QemuConsole *con;
41
+ timer_mod(&t->timer, next);
55
+ QEMUTimer *vblank_timer;
56
57
int version;
58
uint32_t timing[4];
59
@@ -XXX,XX +XXX,XX @@ static void pl110_resize(PL110State *s, int width, int height)
60
/* Update interrupts. */
61
static void pl110_update(PL110State *s)
62
{
63
- /* TODO: Implement interrupts. */
64
+ /* Raise IRQ if enabled and any status bit is 1 */
65
+ if (s->int_status & s->int_mask) {
66
+ qemu_irq_raise(s->irq);
67
+ } else {
68
+ qemu_irq_lower(s->irq);
42
+ }
69
+ }
43
+}
70
+}
44
+
71
+
45
static void aspeed_timer_expire(void *opaque)
72
+static void pl110_vblank_interrupt(void *opaque)
46
{
73
+{
47
AspeedTimer *t = opaque;
74
+ PL110State *s = opaque;
48
@@ -XXX,XX +XXX,XX @@ static void aspeed_timer_expire(void *opaque)
75
+
49
qemu_set_irq(t->irq, t->level);
76
+ /* Fire the vertical compare and next base IRQs and re-arm */
50
}
77
+ s->int_status |= (PL110_IE_NB | PL110_IE_VC);
51
78
+ timer_mod(s->vblank_timer,
52
- timer_mod(&t->timer, calculate_next(t));
79
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
53
+ aspeed_timer_mod(t);
80
+ NANOSECONDS_PER_SECOND / 60);
81
+ pl110_update(s);
54
}
82
}
55
83
56
static uint64_t aspeed_timer_get_value(AspeedTimer *t, int reg)
84
static uint64_t pl110_read(void *opaque, hwaddr offset,
57
@@ -XXX,XX +XXX,XX @@ static void aspeed_timer_set_value(AspeedTimerCtrlState *s, int timer, int reg,
85
@@ -XXX,XX +XXX,XX @@ static void pl110_write(void *opaque, hwaddr offset,
58
uint32_t value)
86
s->bpp = (val >> 1) & 7;
59
{
87
if (pl110_enabled(s)) {
60
AspeedTimer *t;
88
qemu_console_resize(s->con, s->cols, s->rows);
61
+ uint32_t old_reload;
89
+ timer_mod(s->vblank_timer,
62
90
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
63
trace_aspeed_timer_set_value(timer, reg, value);
91
+ NANOSECONDS_PER_SECOND / 60);
64
t = &s->timers[timer];
92
+ } else {
65
switch (reg) {
93
+ timer_del(s->vblank_timer);
66
+ case TIMER_REG_RELOAD:
67
+ old_reload = t->reload;
68
+ t->reload = value;
69
+
70
+ /* If the reload value was not previously set, or zero, and
71
+ * the current value is valid, try to start the timer if it is
72
+ * enabled.
73
+ */
74
+ if (old_reload || !t->reload) {
75
+ break;
76
+ }
77
+
78
case TIMER_REG_STATUS:
79
if (timer_enabled(t)) {
80
uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
81
@@ -XXX,XX +XXX,XX @@ static void aspeed_timer_set_value(AspeedTimerCtrlState *s, int timer, int reg,
82
uint32_t rate = calculate_rate(t);
83
84
t->start += muldiv64(delta, NANOSECONDS_PER_SECOND, rate);
85
- timer_mod(&t->timer, calculate_next(t));
86
+ aspeed_timer_mod(t);
87
}
94
}
88
break;
95
break;
89
- case TIMER_REG_RELOAD:
96
case 10: /* LCDICR */
90
- t->reload = value;
97
@@ -XXX,XX +XXX,XX @@ static void pl110_realize(DeviceState *dev, Error **errp)
91
- break;
98
memory_region_init_io(&s->iomem, OBJECT(s), &pl110_ops, s, "pl110", 0x1000);
92
case TIMER_REG_MATCH_FIRST:
99
sysbus_init_mmio(sbd, &s->iomem);
93
case TIMER_REG_MATCH_SECOND:
100
sysbus_init_irq(sbd, &s->irq);
94
t->match[reg - 2] = value;
101
+ s->vblank_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
95
if (timer_enabled(t)) {
102
+ pl110_vblank_interrupt, s);
96
- timer_mod(&t->timer, calculate_next(t));
103
qdev_init_gpio_in(dev, pl110_mux_ctrl_set, 1);
97
+ aspeed_timer_mod(t);
104
s->con = graphic_console_init(dev, 0, &pl110_gfx_ops, s);
98
}
105
}
99
break;
100
default:
101
@@ -XXX,XX +XXX,XX @@ static void aspeed_timer_ctrl_enable(AspeedTimer *t, bool enable)
102
trace_aspeed_timer_ctrl_enable(t->id, enable);
103
if (enable) {
104
t->start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
105
- timer_mod(&t->timer, calculate_next(t));
106
+ aspeed_timer_mod(t);
107
} else {
108
timer_del(&t->timer);
109
}
110
--
106
--
111
2.7.4
107
2.7.4
112
108
113
109
diff view generated by jsdifflib