1
target-arm queue for rc2. This has 3 Arm related bug fixes,
1
Handful of bugfixes for rc2. None of these are particularly critical
2
and a couple of non-arm patches which don't have an obviously
2
or exciting.
3
better route into the tree.
4
3
5
thanks
6
-- PMM
4
-- PMM
7
5
8
The following changes since commit b9e02bb3f98174209dbd5c96858e65a31723221b:
6
The following changes since commit 45a150aa2b3492acf6691c7bdbeb25a8545d8345:
9
7
10
Merge remote-tracking branch 'remotes/ericb/tags/pull-nbd-2019-07-19' into staging (2019-07-22 10:11:28 +0100)
8
Merge remote-tracking branch 'remotes/ericb/tags/pull-bitmaps-2020-08-03' into staging (2020-08-03 15:13:49 +0100)
11
9
12
are available in the Git repository at:
10
are available in the Git repository at:
13
11
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20190722
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200803
15
13
16
for you to fetch changes up to ddb45afbfbc639365d6c934e4e29f6de5e5e2a0e:
14
for you to fetch changes up to 13557fd392890cbd985bceba7f717e01efd674b8:
17
15
18
contrib/elf2dmp: Build download.o with CURL_CFLAGS (2019-07-22 14:07:39 +0100)
16
hw/timer/imx_epit: Avoid assertion when CR.SWR is written (2020-08-03 17:56:11 +0100)
19
17
20
----------------------------------------------------------------
18
----------------------------------------------------------------
21
target-arm queue:
19
target-arm queue:
22
* target/arm: Add missing break statement for Hypervisor Trap Exception
20
* hw/timer/imx_epit: Avoid assertion when CR.SWR is written
23
(fixes handling of SMC insn taken to AArch32 Hyp mode via HCR.TSC)
21
* netduino2, netduinoplus2, microbit: set system_clock_scale so that
24
* hw/arm/fsl-imx6ul.c: Remove dead SMP-related code
22
SysTick running on the CPU clock works
25
* target/arm: Limit ID register assertions to TCG
23
* target/arm: Avoid maybe-uninitialized warning with gcc 4.9
26
* configure: Clarify URL to source downloads
24
* target/arm: Fix AddPAC error indication
27
* contrib/elf2dmp: Build download.o with CURL_CFLAGS
25
* Make AIRCR.SYSRESETREQ actually reset the system for the
26
microbit, mps2-*, musca-*, netduino* boards
28
27
29
----------------------------------------------------------------
28
----------------------------------------------------------------
30
Peter Maydell (4):
29
Kaige Li (1):
31
hw/arm/fsl-imx6ul.c: Remove dead SMP-related code
30
target/arm: Avoid maybe-uninitialized warning with gcc 4.9
32
target/arm: Limit ID register assertions to TCG
33
configure: Clarify URL to source downloads
34
contrib/elf2dmp: Build download.o with CURL_CFLAGS
35
31
36
Philippe Mathieu-Daudé (1):
32
Peter Maydell (6):
37
target/arm: Add missing break statement for Hypervisor Trap Exception
33
hw/arm/netduino2, netduinoplus2: Set system_clock_scale
34
include/hw/irq.h: New function qemu_irq_is_connected()
35
hw/intc/armv7m_nvic: Provide default "reset the system" behaviour for SYSRESETREQ
36
msf2-soc, stellaris: Don't wire up SYSRESETREQ
37
hw/arm/nrf51_soc: Set system_clock_scale
38
hw/timer/imx_epit: Avoid assertion when CR.SWR is written
38
39
39
configure | 2 +-
40
Richard Henderson (1):
40
Makefile | 1 -
41
target/arm: Fix AddPAC error indication
41
contrib/elf2dmp/Makefile.objs | 3 +++
42
include/hw/arm/fsl-imx6ul.h | 2 +-
43
hw/arm/fsl-imx6ul.c | 62 +++++++++++++------------------------------
44
hw/arm/mcimx6ul-evk.c | 2 +-
45
target/arm/cpu.c | 7 +++--
46
target/arm/helper.c | 1 +
47
8 files changed, 30 insertions(+), 50 deletions(-)
48
42
43
include/hw/arm/armv7m.h | 4 +++-
44
include/hw/irq.h | 18 ++++++++++++++++++
45
hw/arm/msf2-soc.c | 11 -----------
46
hw/arm/netduino2.c | 10 ++++++++++
47
hw/arm/netduinoplus2.c | 10 ++++++++++
48
hw/arm/nrf51_soc.c | 5 +++++
49
hw/arm/stellaris.c | 12 ------------
50
hw/intc/armv7m_nvic.c | 17 ++++++++++++++++-
51
hw/timer/imx_epit.c | 13 ++++++++++---
52
target/arm/pauth_helper.c | 6 +++++-
53
target/arm/translate-a64.c | 2 +-
54
tests/tcg/aarch64/pauth-5.c | 33 +++++++++++++++++++++++++++++++++
55
tests/tcg/aarch64/Makefile.target | 2 +-
56
13 files changed, 112 insertions(+), 31 deletions(-)
57
create mode 100644 tests/tcg/aarch64/pauth-5.c
58
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
The netduino2 and netduinoplus2 boards forgot to set the system_clock_scale
2
global, which meant that if guest code used the systick timer in "use
3
the processor clock" mode it would hang because time never advances.
2
4
3
Reported by GCC9 when building with -Wimplicit-fallthrough=2:
5
Set the global to match the documented CPU clock speed of these boards.
6
Judging by the data sheet this is slightly simplistic because the
7
SoC allows configuration of the SYSCLK source and frequency via the
8
RCC (reset and clock control) module, but we don't model that.
4
9
5
target/arm/helper.c: In function ‘arm_cpu_do_interrupt_aarch32_hyp’:
10
Fixes: https://bugs.launchpad.net/qemu/+bug/1876187
6
target/arm/helper.c:7958:14: error: this statement may fall through [-Werror=implicit-fallthrough=]
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
7958 | addr = 0x14;
12
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
| ~~~~~^~~~~~
13
Message-id: 20200727162617.26227-1-peter.maydell@linaro.org
9
target/arm/helper.c:7959:5: note: here
14
---
10
7959 | default:
15
hw/arm/netduino2.c | 10 ++++++++++
11
| ^~~~~~~
16
hw/arm/netduinoplus2.c | 10 ++++++++++
12
cc1: all warnings being treated as errors
17
2 files changed, 20 insertions(+)
13
18
14
Fixes: b9bc21ff9f9
19
diff --git a/hw/arm/netduino2.c b/hw/arm/netduino2.c
15
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
16
Reported-by: Stefan Weil <sw@weilnetz.de>
17
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
18
Message-id: 20190719111451.12406-1-philmd@redhat.com
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
21
target/arm/helper.c | 1 +
22
1 file changed, 1 insertion(+)
23
24
diff --git a/target/arm/helper.c b/target/arm/helper.c
25
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/helper.c
21
--- a/hw/arm/netduino2.c
27
+++ b/target/arm/helper.c
22
+++ b/hw/arm/netduino2.c
28
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch32_hyp(CPUState *cs)
23
@@ -XXX,XX +XXX,XX @@
29
break;
24
#include "hw/arm/stm32f205_soc.h"
30
case EXCP_HYP_TRAP:
25
#include "hw/arm/boot.h"
31
addr = 0x14;
26
32
+ break;
27
+/* Main SYSCLK frequency in Hz (120MHz) */
33
default:
28
+#define SYSCLK_FRQ 120000000ULL
34
cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
29
+
35
}
30
static void netduino2_init(MachineState *machine)
31
{
32
DeviceState *dev;
33
34
+ /*
35
+ * TODO: ideally we would model the SoC RCC and let it handle
36
+ * system_clock_scale, including its ability to define different
37
+ * possible SYSCLK sources.
38
+ */
39
+ system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
40
+
41
dev = qdev_new(TYPE_STM32F205_SOC);
42
qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m3"));
43
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
44
diff --git a/hw/arm/netduinoplus2.c b/hw/arm/netduinoplus2.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/hw/arm/netduinoplus2.c
47
+++ b/hw/arm/netduinoplus2.c
48
@@ -XXX,XX +XXX,XX @@
49
#include "hw/arm/stm32f405_soc.h"
50
#include "hw/arm/boot.h"
51
52
+/* Main SYSCLK frequency in Hz (168MHz) */
53
+#define SYSCLK_FRQ 168000000ULL
54
+
55
static void netduinoplus2_init(MachineState *machine)
56
{
57
DeviceState *dev;
58
59
+ /*
60
+ * TODO: ideally we would model the SoC RCC and let it handle
61
+ * system_clock_scale, including its ability to define different
62
+ * possible SYSCLK sources.
63
+ */
64
+ system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
65
+
66
dev = qdev_new(TYPE_STM32F405_SOC);
67
qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4"));
68
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
36
--
69
--
37
2.20.1
70
2.20.1
38
71
39
72
diff view generated by jsdifflib
New patch
1
Mostly devices don't need to care whether one of their output
2
qemu_irq lines is connected, because functions like qemu_set_irq()
3
silently do nothing if there is nothing on the other end. However
4
sometimes a device might want to implement default behaviour for the
5
case where the machine hasn't wired the line up to anywhere.
1
6
7
Provide a function qemu_irq_is_connected() that devices can use for
8
this purpose. (The test is trivial but encapsulating it in a
9
function makes it easier to see where we're doing it in case we need
10
to change the implementation later.)
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
15
Message-id: 20200728103744.6909-2-peter.maydell@linaro.org
16
---
17
include/hw/irq.h | 18 ++++++++++++++++++
18
1 file changed, 18 insertions(+)
19
20
diff --git a/include/hw/irq.h b/include/hw/irq.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/irq.h
23
+++ b/include/hw/irq.h
24
@@ -XXX,XX +XXX,XX @@ qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2);
25
on an existing vector of qemu_irq. */
26
void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n);
27
28
+/**
29
+ * qemu_irq_is_connected: Return true if IRQ line is wired up
30
+ *
31
+ * If a qemu_irq has a device on the other (receiving) end of it,
32
+ * return true; otherwise return false.
33
+ *
34
+ * Usually device models don't need to care whether the machine model
35
+ * has wired up their outbound qemu_irq lines, because functions like
36
+ * qemu_set_irq() silently do nothing if there is nothing on the other
37
+ * end of the line. However occasionally a device model will want to
38
+ * provide default behaviour if its output is left floating, and
39
+ * it can use this function to identify when that is the case.
40
+ */
41
+static inline bool qemu_irq_is_connected(qemu_irq irq)
42
+{
43
+ return irq != NULL;
44
+}
45
+
46
#endif
47
--
48
2.20.1
49
50
diff view generated by jsdifflib
New patch
1
The NVIC provides an outbound qemu_irq "SYSRESETREQ" which it signals
2
when the guest sets the SYSRESETREQ bit in the AIRCR register. This
3
matches the hardware design (where the CPU has a signal of this name
4
and it is up to the SoC to connect that up to an actual reset
5
mechanism), but in QEMU it mostly results in duplicated code in SoC
6
objects and bugs where SoC model implementors forget to wire up the
7
SYSRESETREQ line.
1
8
9
Provide a default behaviour for the case where SYSRESETREQ is not
10
actually connected to anything: use qemu_system_reset_request() to
11
perform a system reset. This will allow us to remove the
12
implementations of SYSRESETREQ handling from the boards where that's
13
exactly what it does, and also fixes the bugs in the board models
14
which forgot to wire up the signal:
15
16
* microbit
17
* mps2-an385
18
* mps2-an505
19
* mps2-an511
20
* mps2-an521
21
* musca-a
22
* musca-b1
23
* netduino
24
* netduinoplus2
25
26
We still allow the board to wire up the signal if it needs to, in case
27
we need to model more complicated reset controller logic or to model
28
buggy SoC hardware which forgot to wire up the line itself. But
29
defaulting to "reset the system" is more often going to be correct
30
than defaulting to "do nothing".
31
32
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
33
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
34
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
35
Message-id: 20200728103744.6909-3-peter.maydell@linaro.org
36
---
37
include/hw/arm/armv7m.h | 4 +++-
38
hw/intc/armv7m_nvic.c | 17 ++++++++++++++++-
39
2 files changed, 19 insertions(+), 2 deletions(-)
40
41
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
42
index XXXXXXX..XXXXXXX 100644
43
--- a/include/hw/arm/armv7m.h
44
+++ b/include/hw/arm/armv7m.h
45
@@ -XXX,XX +XXX,XX @@ typedef struct {
46
47
/* ARMv7M container object.
48
* + Unnamed GPIO input lines: external IRQ lines for the NVIC
49
- * + Named GPIO output SYSRESETREQ: signalled for guest AIRCR.SYSRESETREQ
50
+ * + Named GPIO output SYSRESETREQ: signalled for guest AIRCR.SYSRESETREQ.
51
+ * If this GPIO is not wired up then the NVIC will default to performing
52
+ * a qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET).
53
* + Property "cpu-type": CPU type to instantiate
54
* + Property "num-irq": number of external IRQ lines
55
* + Property "memory": MemoryRegion defining the physical address space
56
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/hw/intc/armv7m_nvic.c
59
+++ b/hw/intc/armv7m_nvic.c
60
@@ -XXX,XX +XXX,XX @@
61
#include "hw/intc/armv7m_nvic.h"
62
#include "hw/irq.h"
63
#include "hw/qdev-properties.h"
64
+#include "sysemu/runstate.h"
65
#include "target/arm/cpu.h"
66
#include "exec/exec-all.h"
67
#include "exec/memop.h"
68
@@ -XXX,XX +XXX,XX @@ static const uint8_t nvic_id[] = {
69
0x00, 0xb0, 0x1b, 0x00, 0x0d, 0xe0, 0x05, 0xb1
70
};
71
72
+static void signal_sysresetreq(NVICState *s)
73
+{
74
+ if (qemu_irq_is_connected(s->sysresetreq)) {
75
+ qemu_irq_pulse(s->sysresetreq);
76
+ } else {
77
+ /*
78
+ * Default behaviour if the SoC doesn't need to wire up
79
+ * SYSRESETREQ (eg to a system reset controller of some kind):
80
+ * perform a system reset via the usual QEMU API.
81
+ */
82
+ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
83
+ }
84
+}
85
+
86
static int nvic_pending_prio(NVICState *s)
87
{
88
/* return the group priority of the current pending interrupt,
89
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
90
if (value & R_V7M_AIRCR_SYSRESETREQ_MASK) {
91
if (attrs.secure ||
92
!(cpu->env.v7m.aircr & R_V7M_AIRCR_SYSRESETREQS_MASK)) {
93
- qemu_irq_pulse(s->sysresetreq);
94
+ signal_sysresetreq(s);
95
}
96
}
97
if (value & R_V7M_AIRCR_VECTCLRACTIVE_MASK) {
98
--
99
2.20.1
100
101
diff view generated by jsdifflib
1
contrib/elf2dmp has a source file which uses curl/curl.h;
1
The MSF2 SoC model and the Stellaris board code both wire
2
although we link the final executable with CURL_LIBS, we
2
SYSRESETREQ up to a function that just invokes
3
forgot to build this source file with CURL_CFLAGS, so if
3
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
4
the curl header is in a place that's not already on the
4
This is now the default action that the NVIC does if the line is
5
system include path then it will fail to build.
5
not connected, so we can delete the handling code.
6
7
Add a line specifying the cflags needed for download.o;
8
while we are here, bring the specification of the libs
9
into line with this, since using a per-object variable
10
setting is preferred over adding them to the final
11
executable link line.
12
6
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Message-id: 20190719100955.17180-1-peter.maydell@linaro.org
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Message-id: 20200728103744.6909-4-peter.maydell@linaro.org
16
---
11
---
17
Makefile | 1 -
12
hw/arm/msf2-soc.c | 11 -----------
18
contrib/elf2dmp/Makefile.objs | 3 +++
13
hw/arm/stellaris.c | 12 ------------
19
2 files changed, 3 insertions(+), 1 deletion(-)
14
2 files changed, 23 deletions(-)
20
15
21
diff --git a/Makefile b/Makefile
16
diff --git a/hw/arm/msf2-soc.c b/hw/arm/msf2-soc.c
22
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
23
--- a/Makefile
18
--- a/hw/arm/msf2-soc.c
24
+++ b/Makefile
19
+++ b/hw/arm/msf2-soc.c
25
@@ -XXX,XX +XXX,XX @@ ifneq ($(EXESUF),)
20
@@ -XXX,XX +XXX,XX @@
26
qemu-ga: qemu-ga$(EXESUF) $(QGA_VSS_PROVIDER) $(QEMU_GA_MSI)
21
#include "hw/irq.h"
27
endif
22
#include "hw/arm/msf2-soc.h"
28
23
#include "hw/misc/unimp.h"
29
-elf2dmp$(EXESUF): LIBS += $(CURL_LIBS)
24
-#include "sysemu/runstate.h"
30
elf2dmp$(EXESUF): $(elf2dmp-obj-y)
25
#include "sysemu/sysemu.h"
31
    $(call LINK, $^)
26
32
27
#define MSF2_TIMER_BASE 0x40004000
33
diff --git a/contrib/elf2dmp/Makefile.objs b/contrib/elf2dmp/Makefile.objs
28
@@ -XXX,XX +XXX,XX @@ static const int spi_irq[MSF2_NUM_SPIS] = { 2, 3 };
29
static const int uart_irq[MSF2_NUM_UARTS] = { 10, 11 };
30
static const int timer_irq[MSF2_NUM_TIMERS] = { 14, 15 };
31
32
-static void do_sys_reset(void *opaque, int n, int level)
33
-{
34
- if (level) {
35
- qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
36
- }
37
-}
38
-
39
static void m2sxxx_soc_initfn(Object *obj)
40
{
41
MSF2State *s = MSF2_SOC(obj);
42
@@ -XXX,XX +XXX,XX @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp)
43
return;
44
}
45
46
- qdev_connect_gpio_out_named(DEVICE(&s->armv7m.nvic), "SYSRESETREQ", 0,
47
- qemu_allocate_irq(&do_sys_reset, NULL, 0));
48
-
49
system_clock_scale = NANOSECONDS_PER_SECOND / s->m3clk;
50
51
for (i = 0; i < MSF2_NUM_UARTS; i++) {
52
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
34
index XXXXXXX..XXXXXXX 100644
53
index XXXXXXX..XXXXXXX 100644
35
--- a/contrib/elf2dmp/Makefile.objs
54
--- a/hw/arm/stellaris.c
36
+++ b/contrib/elf2dmp/Makefile.objs
55
+++ b/hw/arm/stellaris.c
37
@@ -1 +1,4 @@
56
@@ -XXX,XX +XXX,XX @@
38
elf2dmp-obj-y = main.o addrspace.o download.o pdb.o qemu_elf.o
57
#include "hw/boards.h"
39
+
58
#include "qemu/log.h"
40
+download.o-cflags := $(CURL_CFLAGS)
59
#include "exec/address-spaces.h"
41
+download.o-libs := $(CURL_LIBS)
60
-#include "sysemu/runstate.h"
61
#include "sysemu/sysemu.h"
62
#include "hw/arm/armv7m.h"
63
#include "hw/char/pl011.h"
64
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_init(Object *obj)
65
qdev_init_gpio_in(dev, stellaris_adc_trigger, 1);
66
}
67
68
-static
69
-void do_sys_reset(void *opaque, int n, int level)
70
-{
71
- if (level) {
72
- qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
73
- }
74
-}
75
-
76
/* Board init. */
77
static stellaris_board_info stellaris_boards[] = {
78
{ "LM3S811EVB",
79
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
80
/* This will exit with an error if the user passed us a bad cpu_type */
81
sysbus_realize_and_unref(SYS_BUS_DEVICE(nvic), &error_fatal);
82
83
- qdev_connect_gpio_out_named(nvic, "SYSRESETREQ", 0,
84
- qemu_allocate_irq(&do_sys_reset, NULL, 0));
85
-
86
if (board->dc1 & (1 << 16)) {
87
dev = sysbus_create_varargs(TYPE_STELLARIS_ADC, 0x40038000,
88
qdev_get_gpio_in(nvic, 14),
42
--
89
--
43
2.20.1
90
2.20.1
44
91
45
92
diff view generated by jsdifflib
1
In arm_cpu_realizefn() we make several assertions about the values of
1
From: Richard Henderson <richard.henderson@linaro.org>
2
guest ID registers:
3
* if the CPU provides AArch32 v7VE or better it must advertise the
4
ARM_DIV feature
5
* if the CPU provides AArch32 A-profile v6 or better it must
6
advertise the Jazelle feature
7
2
8
These are essentially consistency checks that our ID register
3
The definition of top_bit used in this function is one higher
9
specifications in cpu.c didn't accidentally miss out a feature,
4
than that used in the Arm ARM psuedo-code, which put the error
10
because increasingly the TCG emulation gates features on the values
5
indication at top_bit - 1 at the wrong place, which meant that
11
in ID registers rather than using old-style checks of ARM_FEATURE_FOO
6
it wasn't visible to Auth.
12
bits.
13
7
14
Unfortunately, these asserts can cause problems if we're running KVM,
8
Fixing the definition of top_bit requires more changes, because
15
because in that case we don't control the values of the ID registers
9
its most common use is for the count of bits in top_bit:bot_bit,
16
-- we read them from the host kernel. In particular, if the host
10
which would then need to be computed as top_bit - bot_bit + 1.
17
kernel is older than 4.15 then it doesn't expose the ID registers via
18
the KVM_GET_ONE_REG ioctl, and we set up dummy values for some
19
registers and leave the rest at zero. (See the comment in
20
target/arm/kvm64.c kvm_arm_get_host_cpu_features().) This set of
21
dummy values is not sufficient to pass our assertions, and so on
22
those kernels running an AArch32 guest on AArch64 will assert.
23
11
24
We could provide a more sophisticated set of dummy ID registers in
12
For now, prefer the minimal fix to the error indication alone.
25
this case, but that still leaves the possibility of a host CPU which
26
reports bogus ID register values that would cause us to assert. It's
27
more robust to only do these ID register checks if we're using TCG,
28
as that is the only case where this is truly a QEMU code bug.
29
13
30
Reported-by: Laszlo Ersek <lersek@redhat.com>
14
Fixes: 63ff0ca94cb
31
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Reported-by: Derrick McKee <derrick.mckee@gmail.com>
32
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
16
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
33
Tested-by: Laszlo Ersek <lersek@redhat.com>
17
Message-id: 20200728195706.11087-1-richard.henderson@linaro.org
34
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
35
Message-id: 20190718125928.20147-1-peter.maydell@linaro.org
19
[PMM: added comment about the divergence from the pseudocode]
36
Fixes: https://bugs.launchpad.net/qemu/+bug/1830864
37
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
38
---
21
---
39
target/arm/cpu.c | 7 +++++--
22
target/arm/pauth_helper.c | 6 +++++-
40
1 file changed, 5 insertions(+), 2 deletions(-)
23
tests/tcg/aarch64/pauth-5.c | 33 +++++++++++++++++++++++++++++++
24
tests/tcg/aarch64/Makefile.target | 2 +-
25
3 files changed, 39 insertions(+), 2 deletions(-)
26
create mode 100644 tests/tcg/aarch64/pauth-5.c
41
27
42
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
28
diff --git a/target/arm/pauth_helper.c b/target/arm/pauth_helper.c
43
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/cpu.c
30
--- a/target/arm/pauth_helper.c
45
+++ b/target/arm/cpu.c
31
+++ b/target/arm/pauth_helper.c
46
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
32
@@ -XXX,XX +XXX,XX @@ static uint64_t pauth_addpac(CPUARMState *env, uint64_t ptr, uint64_t modifier,
47
* There exist AArch64 cpus without AArch32 support. When KVM
48
* queries ID_ISAR0_EL1 on such a host, the value is UNKNOWN.
49
* Similarly, we cannot check ID_AA64PFR0 without AArch64 support.
50
+ * As a general principle, we also do not make ID register
51
+ * consistency checks anywhere unless using TCG, because only
52
+ * for TCG would a consistency-check failure be a QEMU bug.
53
*/
33
*/
54
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
34
test = sextract64(ptr, bot_bit, top_bit - bot_bit);
55
no_aa32 = !cpu_isar_feature(aa64_aa32, cpu);
35
if (test != 0 && test != -1) {
56
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
36
- pac ^= MAKE_64BIT_MASK(top_bit - 1, 1);
57
* Presence of EL2 itself is ARM_FEATURE_EL2, and of the
37
+ /*
58
* Security Extensions is ARM_FEATURE_EL3.
38
+ * Note that our top_bit is one greater than the pseudocode's
59
*/
39
+ * version, hence "- 2" here.
60
- assert(no_aa32 || cpu_isar_feature(arm_div, cpu));
40
+ */
61
+ assert(!tcg_enabled() || no_aa32 || cpu_isar_feature(arm_div, cpu));
41
+ pac ^= MAKE_64BIT_MASK(top_bit - 2, 1);
62
set_feature(env, ARM_FEATURE_LPAE);
63
set_feature(env, ARM_FEATURE_V7);
64
}
42
}
65
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
43
66
if (arm_feature(env, ARM_FEATURE_V6)) {
44
/*
67
set_feature(env, ARM_FEATURE_V5);
45
diff --git a/tests/tcg/aarch64/pauth-5.c b/tests/tcg/aarch64/pauth-5.c
68
if (!arm_feature(env, ARM_FEATURE_M)) {
46
new file mode 100644
69
- assert(no_aa32 || cpu_isar_feature(jazelle, cpu));
47
index XXXXXXX..XXXXXXX
70
+ assert(!tcg_enabled() || no_aa32 || cpu_isar_feature(jazelle, cpu));
48
--- /dev/null
71
set_feature(env, ARM_FEATURE_AUXCR);
49
+++ b/tests/tcg/aarch64/pauth-5.c
72
}
50
@@ -XXX,XX +XXX,XX @@
73
}
51
+#include <assert.h>
52
+
53
+static int x;
54
+
55
+int main()
56
+{
57
+ int *p0 = &x, *p1, *p2, *p3;
58
+ unsigned long salt = 0;
59
+
60
+ /*
61
+ * With TBI enabled and a 48-bit VA, there are 7 bits of auth, and so
62
+ * a 1/128 chance of auth = pac(ptr,key,salt) producing zero.
63
+ * Find a salt that creates auth != 0.
64
+ */
65
+ do {
66
+ salt++;
67
+ asm("pacda %0, %1" : "=r"(p1) : "r"(salt), "0"(p0));
68
+ } while (p0 == p1);
69
+
70
+ /*
71
+ * This pac must fail, because the input pointer bears an encryption,
72
+ * and so is not properly extended within bits [55:47]. This will
73
+ * toggle bit 54 in the output...
74
+ */
75
+ asm("pacda %0, %1" : "=r"(p2) : "r"(salt), "0"(p1));
76
+
77
+ /* ... so that the aut must fail, setting bit 53 in the output ... */
78
+ asm("autda %0, %1" : "=r"(p3) : "r"(salt), "0"(p2));
79
+
80
+ /* ... which means this equality must not hold. */
81
+ assert(p3 != p0);
82
+ return 0;
83
+}
84
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
85
index XXXXXXX..XXXXXXX 100644
86
--- a/tests/tcg/aarch64/Makefile.target
87
+++ b/tests/tcg/aarch64/Makefile.target
88
@@ -XXX,XX +XXX,XX @@ run-fcvt: fcvt
89
90
# Pauth Tests
91
ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_ARMV8_3),)
92
-AARCH64_TESTS += pauth-1 pauth-2 pauth-4
93
+AARCH64_TESTS += pauth-1 pauth-2 pauth-4 pauth-5
94
pauth-%: CFLAGS += -march=armv8.3-a
95
run-pauth-%: QEMU_OPTS += -cpu max
96
run-plugin-pauth-%: QEMU_OPTS += -cpu max
74
--
97
--
75
2.20.1
98
2.20.1
76
99
77
100
diff view generated by jsdifflib
1
If configure detects that it's being run on a source tree which
1
From: Kaige Li <likaige@loongson.cn>
2
is missing git modules, it prints an error messages suggesting
3
that the user downloads a correct source archive from the project
4
website. However https://www.qemu.org/download/ is a link to a
5
page with multiple tabs, with the default being the one telling
6
users how to get binaries from their distro. Clarify the URL
7
we print to include the #source anchor, so that the browser will
8
go directly to the source-tarball instructions.
9
2
10
Reported-by: Philippe Mathieu-Daudé <philmd@redhat.com>
3
GCC version 4.9.4 isn't clever enough to figure out that all
11
Reviewed-by: Thomas Huth <thuth@redhat.com>
4
execution paths in disas_ldst() that use 'fn' will have initialized
12
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
it first, and so it warns:
13
Reviewed-by: Stefan Weil <sw@weilnetz.de>
6
14
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
/home/LiKaige/qemu/target/arm/translate-a64.c: In function ‘disas_ldst’:
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
/home/LiKaige/qemu/target/arm/translate-a64.c:3392:5: error: ‘fn’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
16
Message-id: 20190718131659.20783-1-peter.maydell@linaro.org
9
fn(cpu_reg(s, rt), clean_addr, tcg_rs, get_mem_index(s),
17
Suggested-by: Stefan Weil <sw@weilnetz.de>
10
^
11
/home/LiKaige/qemu/target/arm/translate-a64.c:3318:22: note: ‘fn’ was declared here
12
AtomicThreeOpFn *fn;
13
^
14
15
Make it happy by initializing the variable to NULL.
16
17
Signed-off-by: Kaige Li <likaige@loongson.cn>
18
Message-id: 1596110248-7366-2-git-send-email-likaige@loongson.cn
19
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
20
[PMM: Clean up commit message and note which gcc version this was]
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
22
---
20
configure | 2 +-
23
target/arm/translate-a64.c | 2 +-
21
1 file changed, 1 insertion(+), 1 deletion(-)
24
1 file changed, 1 insertion(+), 1 deletion(-)
22
25
23
diff --git a/configure b/configure
26
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
24
index XXXXXXX..XXXXXXX 100755
27
index XXXXXXX..XXXXXXX 100644
25
--- a/configure
28
--- a/target/arm/translate-a64.c
26
+++ b/configure
29
+++ b/target/arm/translate-a64.c
27
@@ -XXX,XX +XXX,XX @@ else
30
@@ -XXX,XX +XXX,XX @@ static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
28
echo "to acquire QEMU source archives. Non-GIT builds are only"
31
bool r = extract32(insn, 22, 1);
29
echo "supported with source archives linked from:"
32
bool a = extract32(insn, 23, 1);
30
echo
33
TCGv_i64 tcg_rs, clean_addr;
31
- echo " https://www.qemu.org/download/"
34
- AtomicThreeOpFn *fn;
32
+ echo " https://www.qemu.org/download/#source"
35
+ AtomicThreeOpFn *fn = NULL;
33
echo
36
34
echo "Developers working with GIT can use scripts/archive-source.sh"
37
if (is_vector || !dc_isar_feature(aa64_atomics, s)) {
35
echo "if they need to create valid source archives."
38
unallocated_encoding(s);
36
--
39
--
37
2.20.1
40
2.20.1
38
41
39
42
diff view generated by jsdifflib
1
The i.MX6UL always has a single Cortex-A7 CPU (we set FSL_IMX6UL_NUM_CPUS
1
The nrf51 SoC model wasn't setting the system_clock_scale
2
to 1 in line with this). This means that all the code in fsl-imx6ul.c to
2
global.which meant that if guest code used the systick timer in "use
3
handle multiple CPUs is dead code, and Coverity is now complaining that
3
the processor clock" mode it would hang because time never advances.
4
it is unreachable (CID 1403008, 1403011).
5
4
6
Remove the unreachable code and the only-executes-once loops,
5
Set the global to match the documented CPU clock speed for this SoC.
7
and replace the single-entry cpu[] array in the FSLIMX6ULState
6
8
with a simple cpu member.
7
This SoC in fact doesn't have a SysTick timer (which is the only thing
8
currently that cares about the system_clock_scale), because it's
9
a configurable option in the Cortex-M0. However our Cortex-M0 and
10
thus our nrf51 and our micro:bit board do provide a SysTick, so
11
we ought to provide a functional one rather than a broken one.
9
12
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
14
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
15
Message-id: 20200727193458.31250-1-peter.maydell@linaro.org
13
Message-id: 20190712115030.26895-1-peter.maydell@linaro.org
14
---
16
---
15
include/hw/arm/fsl-imx6ul.h | 2 +-
17
hw/arm/nrf51_soc.c | 5 +++++
16
hw/arm/fsl-imx6ul.c | 62 +++++++++++--------------------------
18
1 file changed, 5 insertions(+)
17
hw/arm/mcimx6ul-evk.c | 2 +-
18
3 files changed, 20 insertions(+), 46 deletions(-)
19
19
20
diff --git a/include/hw/arm/fsl-imx6ul.h b/include/hw/arm/fsl-imx6ul.h
20
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
21
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/arm/fsl-imx6ul.h
22
--- a/hw/arm/nrf51_soc.c
23
+++ b/include/hw/arm/fsl-imx6ul.h
23
+++ b/hw/arm/nrf51_soc.c
24
@@ -XXX,XX +XXX,XX @@ typedef struct FslIMX6ULState {
25
DeviceState parent_obj;
26
27
/*< public >*/
28
- ARMCPU cpu[FSL_IMX6UL_NUM_CPUS];
29
+ ARMCPU cpu;
30
A15MPPrivState a7mpcore;
31
IMXGPTState gpt[FSL_IMX6UL_NUM_GPTS];
32
IMXEPITState epit[FSL_IMX6UL_NUM_EPITS];
33
diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/arm/fsl-imx6ul.c
36
+++ b/hw/arm/fsl-imx6ul.c
37
@@ -XXX,XX +XXX,XX @@
24
@@ -XXX,XX +XXX,XX @@
38
25
39
static void fsl_imx6ul_init(Object *obj)
26
#define BASE_TO_IRQ(base) ((base >> 12) & 0x1F)
27
28
+/* HCLK (the main CPU clock) on this SoC is always 16MHz */
29
+#define HCLK_FRQ 16000000
30
+
31
static uint64_t clock_read(void *opaque, hwaddr addr, unsigned int size)
40
{
32
{
41
- MachineState *ms = MACHINE(qdev_get_machine());
33
qemu_log_mask(LOG_UNIMP, "%s: 0x%" HWADDR_PRIx " [%u]\n",
42
FslIMX6ULState *s = FSL_IMX6UL(obj);
34
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
43
char name[NAME_SIZE];
44
int i;
45
46
- for (i = 0; i < MIN(ms->smp.cpus, FSL_IMX6UL_NUM_CPUS); i++) {
47
- snprintf(name, NAME_SIZE, "cpu%d", i);
48
- object_initialize_child(obj, name, &s->cpu[i], sizeof(s->cpu[i]),
49
- "cortex-a7-" TYPE_ARM_CPU, &error_abort, NULL);
50
- }
51
+ object_initialize_child(obj, "cpu0", &s->cpu, sizeof(s->cpu),
52
+ "cortex-a7-" TYPE_ARM_CPU, &error_abort, NULL);
53
54
/*
55
* A7MPCORE
56
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
57
MachineState *ms = MACHINE(qdev_get_machine());
58
FslIMX6ULState *s = FSL_IMX6UL(dev);
59
int i;
60
- qemu_irq irq;
61
char name[NAME_SIZE];
62
- unsigned int smp_cpus = ms->smp.cpus;
63
+ SysBusDevice *sbd;
64
+ DeviceState *d;
65
66
- if (smp_cpus > FSL_IMX6UL_NUM_CPUS) {
67
- error_setg(errp, "%s: Only %d CPUs are supported (%d requested)",
68
- TYPE_FSL_IMX6UL, FSL_IMX6UL_NUM_CPUS, smp_cpus);
69
+ if (ms->smp.cpus > 1) {
70
+ error_setg(errp, "%s: Only a single CPU is supported (%d requested)",
71
+ TYPE_FSL_IMX6UL, ms->smp.cpus);
72
return;
35
return;
73
}
36
}
74
37
75
- for (i = 0; i < smp_cpus; i++) {
38
+ system_clock_scale = NANOSECONDS_PER_SECOND / HCLK_FRQ;
76
- Object *o = OBJECT(&s->cpu[i]);
39
+
77
-
40
object_property_set_link(OBJECT(&s->cpu), "memory", OBJECT(&s->container),
78
- object_property_set_int(o, QEMU_PSCI_CONDUIT_SMC,
79
- "psci-conduit", &error_abort);
80
-
81
- /* On uniprocessor, the CBAR is set to 0 */
82
- if (smp_cpus > 1) {
83
- object_property_set_int(o, FSL_IMX6UL_A7MPCORE_ADDR,
84
- "reset-cbar", &error_abort);
85
- }
86
-
87
- if (i) {
88
- /* Secondary CPUs start in PSCI powered-down state */
89
- object_property_set_bool(o, true,
90
- "start-powered-off", &error_abort);
91
- }
92
-
93
- object_property_set_bool(o, true, "realized", &error_abort);
94
- }
95
+ object_property_set_int(OBJECT(&s->cpu), QEMU_PSCI_CONDUIT_SMC,
96
+ "psci-conduit", &error_abort);
97
+ object_property_set_bool(OBJECT(&s->cpu), true,
98
+ "realized", &error_abort);
99
100
/*
101
* A7MPCORE
102
*/
103
- object_property_set_int(OBJECT(&s->a7mpcore), smp_cpus, "num-cpu",
104
- &error_abort);
105
+ object_property_set_int(OBJECT(&s->a7mpcore), 1, "num-cpu", &error_abort);
106
object_property_set_int(OBJECT(&s->a7mpcore),
107
FSL_IMX6UL_MAX_IRQ + GIC_INTERNAL,
108
"num-irq", &error_abort);
109
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
110
&error_abort);
41
&error_abort);
111
sysbus_mmio_map(SYS_BUS_DEVICE(&s->a7mpcore), 0, FSL_IMX6UL_A7MPCORE_ADDR);
42
if (!sysbus_realize(SYS_BUS_DEVICE(&s->cpu), errp)) {
112
113
- for (i = 0; i < smp_cpus; i++) {
114
- SysBusDevice *sbd = SYS_BUS_DEVICE(&s->a7mpcore);
115
- DeviceState *d = DEVICE(qemu_get_cpu(i));
116
+ sbd = SYS_BUS_DEVICE(&s->a7mpcore);
117
+ d = DEVICE(&s->cpu);
118
119
- irq = qdev_get_gpio_in(d, ARM_CPU_IRQ);
120
- sysbus_connect_irq(sbd, i, irq);
121
- sysbus_connect_irq(sbd, i + smp_cpus, qdev_get_gpio_in(d, ARM_CPU_FIQ));
122
- sysbus_connect_irq(sbd, i + 2 * smp_cpus,
123
- qdev_get_gpio_in(d, ARM_CPU_VIRQ));
124
- sysbus_connect_irq(sbd, i + 3 * smp_cpus,
125
- qdev_get_gpio_in(d, ARM_CPU_VFIQ));
126
- }
127
+ sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(d, ARM_CPU_IRQ));
128
+ sysbus_connect_irq(sbd, 1, qdev_get_gpio_in(d, ARM_CPU_FIQ));
129
+ sysbus_connect_irq(sbd, 2, qdev_get_gpio_in(d, ARM_CPU_VIRQ));
130
+ sysbus_connect_irq(sbd, 3, qdev_get_gpio_in(d, ARM_CPU_VFIQ));
131
132
/*
133
* A7MPCORE DAP
134
diff --git a/hw/arm/mcimx6ul-evk.c b/hw/arm/mcimx6ul-evk.c
135
index XXXXXXX..XXXXXXX 100644
136
--- a/hw/arm/mcimx6ul-evk.c
137
+++ b/hw/arm/mcimx6ul-evk.c
138
@@ -XXX,XX +XXX,XX @@ static void mcimx6ul_evk_init(MachineState *machine)
139
}
140
141
if (!qtest_enabled()) {
142
- arm_load_kernel(&s->soc.cpu[0], &boot_info);
143
+ arm_load_kernel(&s->soc.cpu, &boot_info);
144
}
145
}
146
147
--
43
--
148
2.20.1
44
2.20.1
149
45
150
46
diff view generated by jsdifflib
New patch
1
The imx_epit device has a software-controllable reset triggered by
2
setting the SWR bit in the CR register. An error in commit cc2722ec83ad9
3
means that we will end up assert()ing if the guest does this, because
4
the code in imx_epit_write() starts ptimer transactions, and then
5
imx_epit_reset() also starts ptimer transactions, triggering
6
"ptimer_transaction_begin: Assertion `!s->in_transaction' failed".
1
7
8
The cleanest way to avoid this double-transaction is to move the
9
start-transaction for the CR write handling down below the check of
10
the SWR bit.
11
12
Fixes: https://bugs.launchpad.net/qemu/+bug/1880424
13
Fixes: cc2722ec83ad944505fe
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Message-id: 20200727154550.3409-1-peter.maydell@linaro.org
17
---
18
hw/timer/imx_epit.c | 13 ++++++++++---
19
1 file changed, 10 insertions(+), 3 deletions(-)
20
21
diff --git a/hw/timer/imx_epit.c b/hw/timer/imx_epit.c
22
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/timer/imx_epit.c
24
+++ b/hw/timer/imx_epit.c
25
@@ -XXX,XX +XXX,XX @@ static void imx_epit_write(void *opaque, hwaddr offset, uint64_t value,
26
27
switch (offset >> 2) {
28
case 0: /* CR */
29
- ptimer_transaction_begin(s->timer_cmp);
30
- ptimer_transaction_begin(s->timer_reload);
31
32
oldcr = s->cr;
33
s->cr = value & 0x03ffffff;
34
if (s->cr & CR_SWR) {
35
/* handle the reset */
36
imx_epit_reset(DEVICE(s));
37
- } else {
38
+ /*
39
+ * TODO: could we 'break' here? following operations appear
40
+ * to duplicate the work imx_epit_reset() already did.
41
+ */
42
+ }
43
+
44
+ ptimer_transaction_begin(s->timer_cmp);
45
+ ptimer_transaction_begin(s->timer_reload);
46
+
47
+ if (!(s->cr & CR_SWR)) {
48
imx_epit_set_freq(s);
49
}
50
51
--
52
2.20.1
53
54
diff view generated by jsdifflib