1
The following changes since commit 41fb4c14ee500125dc0ce6fb573cf84b8db29ed0:
1
Arm queue. I still have a lot of stuff in my to-review queue, so
2
won't be long til the next one.
2
3
3
Merge tag 'linux-user-for-7.0-pull-request' of https://gitlab.com/laurent_vivier/qemu into staging (2022-01-06 11:22:42 -0800)
4
I've thrown in a couple of minor non-arm patches (a xen code
5
cleanup and a vl.c codestyle issue).
6
7
thanks
8
-- PMM
9
10
The following changes since commit de44c044420d1139480fa50c2d5be19223391218:
11
12
Merge remote-tracking branch 'remotes/stsquad/tags/pull-tcg-testing-revivial-210618-2' into staging (2018-06-22 10:57:47 +0100)
4
13
5
are available in the Git repository at:
14
are available in the Git repository at:
6
15
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220107
16
git://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20180622
8
17
9
for you to fetch changes up to b8905cc2dde95ca6be5e56d77053b1ca0b8fc182:
18
for you to fetch changes up to 6dad8260e82b69bd278685ee25209f5824360455:
10
19
11
hw/arm: kudo add lm75s on bus 13 (2022-01-07 17:08:01 +0000)
20
xen: Don't use memory_region_init_ram_nomigrate() in pci_assign_dev_load_option_rom() (2018-06-22 13:28:42 +0100)
12
21
13
----------------------------------------------------------------
22
----------------------------------------------------------------
14
target-arm queue:
23
target-arm queue:
15
* Add dummy Aspeed AST2600 Display Port MCU (DPMCU)
24
* hw/intc/arm_gicv3: fix wrong values when reading IPRIORITYR
16
* Add missing FEAT_TLBIOS instructions
25
* target/arm: fix read of freed memory in kvm_arm_machine_init_done()
17
* arm_gicv3_its: Various bug fixes and cleanups
26
* virt: support up to 512 CPUs
18
* kudo-bmc: Add more devices
27
* virt: support 256MB ECAM PCI region (for more PCI devices)
28
* xlnx-zynqmp: Use Cortex-R5F, not Cortex-R5
29
* mps2-tz: Implement and use the TrustZone Memory Protection Controller
30
* target/arm: enforce alignment checking for v6M cores
31
* xen: Don't use memory_region_init_ram_nomigrate() in pci_assign_dev_load_option_rom()
32
* vl.c: Don't zero-initialize statics for serial_hds
19
33
20
----------------------------------------------------------------
34
----------------------------------------------------------------
21
Chris Rauer (1):
35
Amol Surati (1):
22
hw/arm: Add kudo i2c eeproms.
36
hw/intc/arm_gicv3: fix an extra left-shift when reading IPRIORITYR
23
37
24
Idan Horowitz (1):
38
Edgar E. Iglesias (2):
25
target/arm: Add missing FEAT_TLBIOS instructions
39
target-arm: Add the Cortex-R5F
40
xlnx-zynqmp: Swap Cortex-R5 for Cortex-R5F
26
41
27
Patrick Venture (2):
42
Eric Auger (11):
28
hw/arm: add i2c muxes to kudo-bmc
43
linux-headers: Update to kernel mainline commit b357bf602
29
hw/arm: kudo add lm75s on bus 13
44
target/arm: Allow KVM device address overwriting
45
hw/intc/arm_gicv3: Introduce redist-region-count array property
46
hw/intc/arm_gicv3_kvm: Get prepared to handle multiple redist regions
47
hw/arm/virt: GICv3 DT node with one or two redistributor regions
48
hw/arm/virt-acpi-build: Advertise one or two GICR structures
49
hw/arm/virt: Register two redistributor regions when necessary
50
hw/arm/virt: Add a new 256MB ECAM region
51
hw/arm/virt: Add virt-3.0 machine type
52
hw/arm/virt: Use 256MB ECAM region by default
53
hw/arm/virt: Increase max_cpus to 512
30
54
31
Peter Maydell (13):
55
Julia Suvorova (3):
32
hw/intc/arm_gicv3_its: Correct off-by-one bounds check on rdbase
56
target/arm: Minor cleanup for ARMv6-M 32-bit instructions
33
hw/intc/arm_gicv3_its: Remove redundant ITS_CTLR_ENABLED define
57
target/arm: Introduce ARM_FEATURE_M_MAIN
34
hw/intc/arm_gicv3_its: Remove maxids union from TableDesc
58
target/arm: Strict alignment for ARMv6-M and ARMv8-M Baseline
35
hw/intc/arm_gicv3_its: Don't return early in extract_table_params() loop
36
hw/intc/arm_gicv3_its: Reduce code duplication in extract_table_params()
37
hw/intc/arm_gicv3_its: Correct setting of TableDesc entry_sz
38
hw/intc/arm_gicv3_its: Don't misuse GITS_TYPE_PHYSICAL define
39
hw/intc/arm_gicv3_its: Correct handling of MAPI
40
hw/intc/arm_gicv3_its: Use FIELD macros for DTEs
41
hw/intc/arm_gicv3_its: Correct comment about CTE RDBase field size
42
hw/intc/arm_gicv3_its: Use FIELD macros for CTEs
43
hw/intc/arm_gicv3_its: Fix various off-by-one errors
44
hw/intc/arm_gicv3_its: Rename max_l2_entries to num_l2_entries
45
59
46
Shengtan Mao (1):
60
Peter Maydell (10):
47
hw/arm: attach MMC to kudo-bmc
61
hw/misc/tz-mpc.c: Implement the Arm TrustZone Memory Protection Controller
62
hw/misc/tz-mpc.c: Implement registers
63
hw/misc/tz-mpc.c: Implement correct blocked-access behaviour
64
hw/misc/tz_mpc.c: Honour the BLK_LUT settings in translate
65
hw/misc/iotkit-secctl.c: Implement SECMPCINTSTATUS
66
hw/arm/iotkit: Instantiate MPC
67
hw/arm/iotkit: Wire up MPC interrupt lines
68
hw/arm/mps2-tz.c: Instantiate MPCs
69
vl.c: Don't zero-initialize statics for serial_hds
70
xen: Don't use memory_region_init_ram_nomigrate() in pci_assign_dev_load_option_rom()
48
71
49
Troy Lee (1):
72
Zheng Xiang (1):
50
Add dummy Aspeed AST2600 Display Port MCU (DPMCU)
73
target-arm: fix a segmentation fault due to illegal memory access
51
74
52
hw/intc/gicv3_internal.h | 40 +++---
75
hw/misc/Makefile.objs | 1 +
53
include/hw/arm/aspeed_soc.h | 2 +
76
hw/xen/xen_pt.h | 2 +-
54
include/hw/intc/arm_gicv3_its_common.h | 9 +-
77
include/hw/arm/iotkit.h | 8 +
55
hw/arm/aspeed_ast2600.c | 8 ++
78
include/hw/arm/virt.h | 19 +
56
hw/arm/npcm7xx_boards.c | 27 ++++
79
include/hw/intc/arm_gicv3_common.h | 8 +-
57
hw/intc/arm_gicv3_its.c | 234 +++++++++++++++------------------
80
include/hw/misc/iotkit-secctl.h | 8 +
58
target/arm/helper.c | 32 +++++
81
include/hw/misc/tz-mpc.h | 80 +++
59
7 files changed, 197 insertions(+), 155 deletions(-)
82
include/standard-headers/linux/pci_regs.h | 8 +
83
include/standard-headers/linux/virtio_gpu.h | 1 +
84
include/standard-headers/linux/virtio_net.h | 3 +
85
linux-headers/asm-arm/kvm.h | 1 +
86
linux-headers/asm-arm/unistd-common.h | 1 +
87
linux-headers/asm-arm64/kvm.h | 1 +
88
linux-headers/asm-generic/unistd.h | 4 +-
89
linux-headers/asm-powerpc/unistd.h | 1 +
90
linux-headers/asm-x86/unistd_32.h | 2 +
91
linux-headers/asm-x86/unistd_64.h | 2 +
92
linux-headers/asm-x86/unistd_x32.h | 2 +
93
linux-headers/linux/kvm.h | 5 +-
94
linux-headers/linux/psp-sev.h | 12 +
95
target/arm/cpu.h | 1 +
96
target/arm/kvm_arm.h | 3 +-
97
hw/arm/iotkit.c | 112 +++-
98
hw/arm/mps2-tz.c | 71 ++-
99
hw/arm/virt-acpi-build.c | 30 +-
100
hw/arm/virt.c | 100 +++-
101
hw/arm/xlnx-zcu102.c | 2 +-
102
hw/arm/xlnx-zynqmp.c | 2 +-
103
hw/intc/arm_gic_kvm.c | 4 +-
104
hw/intc/arm_gicv3.c | 12 +-
105
hw/intc/arm_gicv3_common.c | 38 +-
106
hw/intc/arm_gicv3_dist.c | 3 +-
107
hw/intc/arm_gicv3_its_kvm.c | 2 +-
108
hw/intc/arm_gicv3_kvm.c | 44 +-
109
hw/intc/arm_gicv3_redist.c | 3 +-
110
hw/misc/iotkit-secctl.c | 38 +-
111
hw/misc/tz-mpc.c | 628 +++++++++++++++++++++
112
hw/xen/xen_pt_graphics.c | 2 +-
113
hw/xen/xen_pt_load_rom.c | 6 +-
114
target/arm/cpu.c | 12 +
115
target/arm/kvm.c | 11 +-
116
target/arm/translate.c | 45 +-
117
vl.c | 4 +-
118
MAINTAINERS | 2 +
119
default-configs/arm-softmmu.mak | 1 +
120
hw/misc/trace-events | 8 +
121
.../LICENSES/exceptions/Linux-syscall-note | 2 +-
122
linux-headers/LICENSES/preferred/GPL-2.0 | 6 +
123
48 files changed, 1250 insertions(+), 111 deletions(-)
124
create mode 100644 include/hw/misc/tz-mpc.h
125
create mode 100644 hw/misc/tz-mpc.c
60
126
diff view generated by jsdifflib
New patch
1
From: Amol Surati <suratiamol@gmail.com>
1
2
3
When either GICD_IPRIORITYR or GICR_IPRIORITYR is read as a 32-bit
4
register, the post left-shift operator in the for loop causes an
5
extra shift after the least significant byte has been placed.
6
7
The 32-bit value actually returned is therefore the expected value
8
shifted left by 8 bits.
9
10
Signed-off-by: Amol Surati <suratiamol@gmail.com>
11
Message-id: 20180614054857.26248-1-suratiamol@gmail.com
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
hw/intc/arm_gicv3_dist.c | 3 ++-
16
hw/intc/arm_gicv3_redist.c | 3 ++-
17
2 files changed, 4 insertions(+), 2 deletions(-)
18
19
diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/intc/arm_gicv3_dist.c
22
+++ b/hw/intc/arm_gicv3_dist.c
23
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset,
24
int i, irq = offset - GICD_IPRIORITYR;
25
uint32_t value = 0;
26
27
- for (i = irq + 3; i >= irq; i--, value <<= 8) {
28
+ for (i = irq + 3; i >= irq; i--) {
29
+ value <<= 8;
30
value |= gicd_read_ipriorityr(s, attrs, i);
31
}
32
*data = value;
33
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/intc/arm_gicv3_redist.c
36
+++ b/hw/intc/arm_gicv3_redist.c
37
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicr_readl(GICv3CPUState *cs, hwaddr offset,
38
int i, irq = offset - GICR_IPRIORITYR;
39
uint32_t value = 0;
40
41
- for (i = irq + 3; i >= irq; i--, value <<= 8) {
42
+ for (i = irq + 3; i >= irq; i--) {
43
+ value <<= 8;
44
value |= gicr_read_ipriorityr(cs, attrs, i);
45
}
46
*data = value;
47
--
48
2.17.1
49
50
diff view generated by jsdifflib
New patch
1
From: Julia Suvorova <jusual@mail.ru>
1
2
3
The arrays were made static, "if" was simplified because V7M and V8M
4
define V6 feature.
5
6
Signed-off-by: Julia Suvorova <jusual@mail.ru>
7
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
8
Message-id: 20180618214604.6777-1-jusual@mail.ru
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/translate.c | 27 +++++++++++++--------------
13
1 file changed, 13 insertions(+), 14 deletions(-)
14
15
diff --git a/target/arm/translate.c b/target/arm/translate.c
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate.c
18
+++ b/target/arm/translate.c
19
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
20
!arm_dc_feature(s, ARM_FEATURE_V7)) {
21
int i;
22
bool found = false;
23
- const uint32_t armv6m_insn[] = {0xf3808000 /* msr */,
24
- 0xf3b08040 /* dsb */,
25
- 0xf3b08050 /* dmb */,
26
- 0xf3b08060 /* isb */,
27
- 0xf3e08000 /* mrs */,
28
- 0xf000d000 /* bl */};
29
- const uint32_t armv6m_mask[] = {0xffe0d000,
30
- 0xfff0d0f0,
31
- 0xfff0d0f0,
32
- 0xfff0d0f0,
33
- 0xffe0d000,
34
- 0xf800d000};
35
+ static const uint32_t armv6m_insn[] = {0xf3808000 /* msr */,
36
+ 0xf3b08040 /* dsb */,
37
+ 0xf3b08050 /* dmb */,
38
+ 0xf3b08060 /* isb */,
39
+ 0xf3e08000 /* mrs */,
40
+ 0xf000d000 /* bl */};
41
+ static const uint32_t armv6m_mask[] = {0xffe0d000,
42
+ 0xfff0d0f0,
43
+ 0xfff0d0f0,
44
+ 0xfff0d0f0,
45
+ 0xffe0d000,
46
+ 0xf800d000};
47
48
for (i = 0; i < ARRAY_SIZE(armv6m_insn); i++) {
49
if ((insn & armv6m_mask[i]) == armv6m_insn[i]) {
50
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
51
break;
52
case 3: /* Special control operations. */
53
if (!arm_dc_feature(s, ARM_FEATURE_V7) &&
54
- !(arm_dc_feature(s, ARM_FEATURE_V6) &&
55
- arm_dc_feature(s, ARM_FEATURE_M))) {
56
+ !arm_dc_feature(s, ARM_FEATURE_M)) {
57
goto illegal_op;
58
}
59
op = (insn >> 4) & 0xf;
60
--
61
2.17.1
62
63
diff view generated by jsdifflib
New patch
1
From: Zheng Xiang <xiang.zheng@linaro.org>
1
2
3
The elements of kvm_devices_head list are freed in kvm_arm_machine_init_done(),
4
but we still access these illegal memory in kvm_arm_devlistener_del().
5
6
This will cause segment fault when booting guest with MALLOC_PERTURB_=1.
7
8
Signed-off-by: Zheng Xiang <xiang.zheng@linaro.org>
9
Message-id: 20180619075821.9884-1-zhengxiang9@huawei.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
target/arm/kvm.c | 1 +
14
1 file changed, 1 insertion(+)
15
16
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/kvm.c
19
+++ b/target/arm/kvm.c
20
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_machine_init_done(Notifier *notifier, void *data)
21
kvm_arm_set_device_addr(kd);
22
}
23
memory_region_unref(kd->mr);
24
+ QSLIST_REMOVE_HEAD(&kvm_devices_head, entries);
25
g_free(kd);
26
}
27
memory_listener_unregister(&devlistener);
28
--
29
2.17.1
30
31
diff view generated by jsdifflib
New patch
1
1
From: Eric Auger <eric.auger@redhat.com>
2
3
Update our kernel headers to mainline commit
4
b357bf6023a948cf6a9472f07a1b0caac0e4f8e8
5
("Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm")
6
7
Signed-off-by: Eric Auger <eric.auger@redhat.com>
8
Message-id: 1529072910-16156-2-git-send-email-eric.auger@redhat.com
9
[PMM: clarified commit message]
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/standard-headers/linux/pci_regs.h | 8 ++++++++
13
include/standard-headers/linux/virtio_gpu.h | 1 +
14
include/standard-headers/linux/virtio_net.h | 3 +++
15
linux-headers/asm-arm/kvm.h | 1 +
16
linux-headers/asm-arm/unistd-common.h | 1 +
17
linux-headers/asm-arm64/kvm.h | 1 +
18
linux-headers/asm-generic/unistd.h | 4 +++-
19
linux-headers/asm-powerpc/unistd.h | 1 +
20
linux-headers/asm-x86/unistd_32.h | 2 ++
21
linux-headers/asm-x86/unistd_64.h | 2 ++
22
linux-headers/asm-x86/unistd_x32.h | 2 ++
23
linux-headers/linux/kvm.h | 5 +++--
24
linux-headers/linux/psp-sev.h | 12 ++++++++++++
25
linux-headers/LICENSES/exceptions/Linux-syscall-note | 2 +-
26
linux-headers/LICENSES/preferred/GPL-2.0 | 6 ++++++
27
15 files changed, 47 insertions(+), 4 deletions(-)
28
29
diff --git a/include/standard-headers/linux/pci_regs.h b/include/standard-headers/linux/pci_regs.h
30
index XXXXXXX..XXXXXXX 100644
31
--- a/include/standard-headers/linux/pci_regs.h
32
+++ b/include/standard-headers/linux/pci_regs.h
33
@@ -XXX,XX +XXX,XX @@
34
#define PCI_EXP_DEVCTL_READRQ_256B 0x1000 /* 256 Bytes */
35
#define PCI_EXP_DEVCTL_READRQ_512B 0x2000 /* 512 Bytes */
36
#define PCI_EXP_DEVCTL_READRQ_1024B 0x3000 /* 1024 Bytes */
37
+#define PCI_EXP_DEVCTL_READRQ_2048B 0x4000 /* 2048 Bytes */
38
+#define PCI_EXP_DEVCTL_READRQ_4096B 0x5000 /* 4096 Bytes */
39
#define PCI_EXP_DEVCTL_BCR_FLR 0x8000 /* Bridge Configuration Retry / FLR */
40
#define PCI_EXP_DEVSTA        10    /* Device Status */
41
#define PCI_EXP_DEVSTA_CED    0x0001    /* Correctable Error Detected */
42
@@ -XXX,XX +XXX,XX @@
43
#define PCI_EXP_LNKCAP2_SLS_16_0GB    0x00000010 /* Supported Speed 16GT/s */
44
#define PCI_EXP_LNKCAP2_CROSSLINK    0x00000100 /* Crosslink supported */
45
#define PCI_EXP_LNKCTL2        48    /* Link Control 2 */
46
+#define PCI_EXP_LNKCTL2_TLS        0x000f
47
+#define PCI_EXP_LNKCTL2_TLS_2_5GT    0x0001 /* Supported Speed 2.5GT/s */
48
+#define PCI_EXP_LNKCTL2_TLS_5_0GT    0x0002 /* Supported Speed 5GT/s */
49
+#define PCI_EXP_LNKCTL2_TLS_8_0GT    0x0003 /* Supported Speed 8GT/s */
50
+#define PCI_EXP_LNKCTL2_TLS_16_0GT    0x0004 /* Supported Speed 16GT/s */
51
#define PCI_EXP_LNKSTA2        50    /* Link Status 2 */
52
#define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2    52    /* v2 endpoints with link end here */
53
#define PCI_EXP_SLTCAP2        52    /* Slot Capabilities 2 */
54
@@ -XXX,XX +XXX,XX @@
55
#define PCI_EXP_DPC_CAP_DL_ACTIVE    0x1000    /* ERR_COR signal on DL_Active supported */
56
57
#define PCI_EXP_DPC_CTL            6    /* DPC control */
58
+#define PCI_EXP_DPC_CTL_EN_FATAL     0x0001    /* Enable trigger on ERR_FATAL message */
59
#define PCI_EXP_DPC_CTL_EN_NONFATAL     0x0002    /* Enable trigger on ERR_NONFATAL message */
60
#define PCI_EXP_DPC_CTL_INT_EN     0x0008    /* DPC Interrupt Enable */
61
62
diff --git a/include/standard-headers/linux/virtio_gpu.h b/include/standard-headers/linux/virtio_gpu.h
63
index XXXXXXX..XXXXXXX 100644
64
--- a/include/standard-headers/linux/virtio_gpu.h
65
+++ b/include/standard-headers/linux/virtio_gpu.h
66
@@ -XXX,XX +XXX,XX @@ struct virtio_gpu_cmd_submit {
67
};
68
69
#define VIRTIO_GPU_CAPSET_VIRGL 1
70
+#define VIRTIO_GPU_CAPSET_VIRGL2 2
71
72
/* VIRTIO_GPU_CMD_GET_CAPSET_INFO */
73
struct virtio_gpu_get_capset_info {
74
diff --git a/include/standard-headers/linux/virtio_net.h b/include/standard-headers/linux/virtio_net.h
75
index XXXXXXX..XXXXXXX 100644
76
--- a/include/standard-headers/linux/virtio_net.h
77
+++ b/include/standard-headers/linux/virtio_net.h
78
@@ -XXX,XX +XXX,XX @@
79
                     * Steering */
80
#define VIRTIO_NET_F_CTRL_MAC_ADDR 23    /* Set MAC address */
81
82
+#define VIRTIO_NET_F_STANDBY     62    /* Act as standby for another device
83
+                     * with the same MAC.
84
+                     */
85
#define VIRTIO_NET_F_SPEED_DUPLEX 63    /* Device set linkspeed and duplex */
86
87
#ifndef VIRTIO_NET_NO_LEGACY
88
diff --git a/linux-headers/asm-arm/kvm.h b/linux-headers/asm-arm/kvm.h
89
index XXXXXXX..XXXXXXX 100644
90
--- a/linux-headers/asm-arm/kvm.h
91
+++ b/linux-headers/asm-arm/kvm.h
92
@@ -XXX,XX +XXX,XX @@ struct kvm_regs {
93
#define KVM_VGIC_V3_ADDR_TYPE_DIST    2
94
#define KVM_VGIC_V3_ADDR_TYPE_REDIST    3
95
#define KVM_VGIC_ITS_ADDR_TYPE        4
96
+#define KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION    5
97
98
#define KVM_VGIC_V3_DIST_SIZE        SZ_64K
99
#define KVM_VGIC_V3_REDIST_SIZE        (2 * SZ_64K)
100
diff --git a/linux-headers/asm-arm/unistd-common.h b/linux-headers/asm-arm/unistd-common.h
101
index XXXXXXX..XXXXXXX 100644
102
--- a/linux-headers/asm-arm/unistd-common.h
103
+++ b/linux-headers/asm-arm/unistd-common.h
104
@@ -XXX,XX +XXX,XX @@
105
#define __NR_pkey_alloc (__NR_SYSCALL_BASE + 395)
106
#define __NR_pkey_free (__NR_SYSCALL_BASE + 396)
107
#define __NR_statx (__NR_SYSCALL_BASE + 397)
108
+#define __NR_rseq (__NR_SYSCALL_BASE + 398)
109
110
#endif /* _ASM_ARM_UNISTD_COMMON_H */
111
diff --git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h
112
index XXXXXXX..XXXXXXX 100644
113
--- a/linux-headers/asm-arm64/kvm.h
114
+++ b/linux-headers/asm-arm64/kvm.h
115
@@ -XXX,XX +XXX,XX @@ struct kvm_regs {
116
#define KVM_VGIC_V3_ADDR_TYPE_DIST    2
117
#define KVM_VGIC_V3_ADDR_TYPE_REDIST    3
118
#define KVM_VGIC_ITS_ADDR_TYPE        4
119
+#define KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION    5
120
121
#define KVM_VGIC_V3_DIST_SIZE        SZ_64K
122
#define KVM_VGIC_V3_REDIST_SIZE        (2 * SZ_64K)
123
diff --git a/linux-headers/asm-generic/unistd.h b/linux-headers/asm-generic/unistd.h
124
index XXXXXXX..XXXXXXX 100644
125
--- a/linux-headers/asm-generic/unistd.h
126
+++ b/linux-headers/asm-generic/unistd.h
127
@@ -XXX,XX +XXX,XX @@ __SYSCALL(__NR_pkey_alloc, sys_pkey_alloc)
128
__SYSCALL(__NR_pkey_free, sys_pkey_free)
129
#define __NR_statx 291
130
__SYSCALL(__NR_statx, sys_statx)
131
+#define __NR_io_pgetevents 292
132
+__SC_COMP(__NR_io_pgetevents, sys_io_pgetevents, compat_sys_io_pgetevents)
133
134
#undef __NR_syscalls
135
-#define __NR_syscalls 292
136
+#define __NR_syscalls 293
137
138
/*
139
* 32 bit systems traditionally used different
140
diff --git a/linux-headers/asm-powerpc/unistd.h b/linux-headers/asm-powerpc/unistd.h
141
index XXXXXXX..XXXXXXX 100644
142
--- a/linux-headers/asm-powerpc/unistd.h
143
+++ b/linux-headers/asm-powerpc/unistd.h
144
@@ -XXX,XX +XXX,XX @@
145
#define __NR_pkey_alloc        384
146
#define __NR_pkey_free        385
147
#define __NR_pkey_mprotect    386
148
+#define __NR_rseq        387
149
150
#endif /* _ASM_POWERPC_UNISTD_H_ */
151
diff --git a/linux-headers/asm-x86/unistd_32.h b/linux-headers/asm-x86/unistd_32.h
152
index XXXXXXX..XXXXXXX 100644
153
--- a/linux-headers/asm-x86/unistd_32.h
154
+++ b/linux-headers/asm-x86/unistd_32.h
155
@@ -XXX,XX +XXX,XX @@
156
#define __NR_pkey_free 382
157
#define __NR_statx 383
158
#define __NR_arch_prctl 384
159
+#define __NR_io_pgetevents 385
160
+#define __NR_rseq 386
161
162
#endif /* _ASM_X86_UNISTD_32_H */
163
diff --git a/linux-headers/asm-x86/unistd_64.h b/linux-headers/asm-x86/unistd_64.h
164
index XXXXXXX..XXXXXXX 100644
165
--- a/linux-headers/asm-x86/unistd_64.h
166
+++ b/linux-headers/asm-x86/unistd_64.h
167
@@ -XXX,XX +XXX,XX @@
168
#define __NR_pkey_alloc 330
169
#define __NR_pkey_free 331
170
#define __NR_statx 332
171
+#define __NR_io_pgetevents 333
172
+#define __NR_rseq 334
173
174
#endif /* _ASM_X86_UNISTD_64_H */
175
diff --git a/linux-headers/asm-x86/unistd_x32.h b/linux-headers/asm-x86/unistd_x32.h
176
index XXXXXXX..XXXXXXX 100644
177
--- a/linux-headers/asm-x86/unistd_x32.h
178
+++ b/linux-headers/asm-x86/unistd_x32.h
179
@@ -XXX,XX +XXX,XX @@
180
#define __NR_pkey_alloc (__X32_SYSCALL_BIT + 330)
181
#define __NR_pkey_free (__X32_SYSCALL_BIT + 331)
182
#define __NR_statx (__X32_SYSCALL_BIT + 332)
183
+#define __NR_io_pgetevents (__X32_SYSCALL_BIT + 333)
184
+#define __NR_rseq (__X32_SYSCALL_BIT + 334)
185
#define __NR_rt_sigaction (__X32_SYSCALL_BIT + 512)
186
#define __NR_rt_sigreturn (__X32_SYSCALL_BIT + 513)
187
#define __NR_ioctl (__X32_SYSCALL_BIT + 514)
188
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
189
index XXXXXXX..XXXXXXX 100644
190
--- a/linux-headers/linux/kvm.h
191
+++ b/linux-headers/linux/kvm.h
192
@@ -XXX,XX +XXX,XX @@ struct kvm_ioeventfd {
193
};
194
195
#define KVM_X86_DISABLE_EXITS_MWAIT (1 << 0)
196
-#define KVM_X86_DISABLE_EXITS_HTL (1 << 1)
197
+#define KVM_X86_DISABLE_EXITS_HLT (1 << 1)
198
#define KVM_X86_DISABLE_EXITS_PAUSE (1 << 2)
199
#define KVM_X86_DISABLE_VALID_EXITS (KVM_X86_DISABLE_EXITS_MWAIT | \
200
- KVM_X86_DISABLE_EXITS_HTL | \
201
+ KVM_X86_DISABLE_EXITS_HLT | \
202
KVM_X86_DISABLE_EXITS_PAUSE)
203
204
/* for KVM_ENABLE_CAP */
205
@@ -XXX,XX +XXX,XX @@ struct kvm_ppc_resize_hpt {
206
#define KVM_CAP_S390_BPB 152
207
#define KVM_CAP_GET_MSR_FEATURES 153
208
#define KVM_CAP_HYPERV_EVENTFD 154
209
+#define KVM_CAP_HYPERV_TLBFLUSH 155
210
211
#ifdef KVM_CAP_IRQ_ROUTING
212
213
diff --git a/linux-headers/linux/psp-sev.h b/linux-headers/linux/psp-sev.h
214
index XXXXXXX..XXXXXXX 100644
215
--- a/linux-headers/linux/psp-sev.h
216
+++ b/linux-headers/linux/psp-sev.h
217
@@ -XXX,XX +XXX,XX @@ enum {
218
    SEV_PDH_GEN,
219
    SEV_PDH_CERT_EXPORT,
220
    SEV_PEK_CERT_IMPORT,
221
+    SEV_GET_ID,
222
223
    SEV_MAX,
224
};
225
@@ -XXX,XX +XXX,XX @@ struct sev_user_data_pdh_cert_export {
226
    __u32 cert_chain_len;            /* In/Out */
227
} __attribute__((packed));
228
229
+/**
230
+ * struct sev_user_data_get_id - GET_ID command parameters
231
+ *
232
+ * @socket1: Buffer to pass unique ID of first socket
233
+ * @socket2: Buffer to pass unique ID of second socket
234
+ */
235
+struct sev_user_data_get_id {
236
+    __u8 socket1[64];            /* Out */
237
+    __u8 socket2[64];            /* Out */
238
+} __attribute__((packed));
239
+
240
/**
241
* struct sev_issue_cmd - SEV ioctl parameters
242
*
243
diff --git a/linux-headers/LICENSES/exceptions/Linux-syscall-note b/linux-headers/LICENSES/exceptions/Linux-syscall-note
244
index XXXXXXX..XXXXXXX 100644
245
--- a/linux-headers/LICENSES/exceptions/Linux-syscall-note
246
+++ b/linux-headers/LICENSES/exceptions/Linux-syscall-note
247
@@ -XXX,XX +XXX,XX @@
248
SPDX-Exception-Identifier: Linux-syscall-note
249
SPDX-URL: https://spdx.org/licenses/Linux-syscall-note.html
250
-SPDX-Licenses: GPL-2.0, GPL-2.0+, GPL-1.0+, LGPL-2.0, LGPL-2.0+, LGPL-2.1, LGPL-2.1+
251
+SPDX-Licenses: GPL-2.0, GPL-2.0+, GPL-1.0+, LGPL-2.0, LGPL-2.0+, LGPL-2.1, LGPL-2.1+, GPL-2.0-only, GPL-2.0-or-later
252
Usage-Guide:
253
This exception is used together with one of the above SPDX-Licenses
254
to mark user space API (uapi) header files so they can be included
255
diff --git a/linux-headers/LICENSES/preferred/GPL-2.0 b/linux-headers/LICENSES/preferred/GPL-2.0
256
index XXXXXXX..XXXXXXX 100644
257
--- a/linux-headers/LICENSES/preferred/GPL-2.0
258
+++ b/linux-headers/LICENSES/preferred/GPL-2.0
259
@@ -XXX,XX +XXX,XX @@
260
Valid-License-Identifier: GPL-2.0
261
+Valid-License-Identifier: GPL-2.0-only
262
Valid-License-Identifier: GPL-2.0+
263
+Valid-License-Identifier: GPL-2.0-or-later
264
SPDX-URL: https://spdx.org/licenses/GPL-2.0.html
265
Usage-Guide:
266
To use this license in source code, put one of the following SPDX
267
@@ -XXX,XX +XXX,XX @@ Usage-Guide:
268
guidelines in the licensing rules documentation.
269
For 'GNU General Public License (GPL) version 2 only' use:
270
SPDX-License-Identifier: GPL-2.0
271
+ or
272
+ SPDX-License-Identifier: GPL-2.0-only
273
For 'GNU General Public License (GPL) version 2 or any later version' use:
274
SPDX-License-Identifier: GPL-2.0+
275
+ or
276
+ SPDX-License-Identifier: GPL-2.0-or-later
277
License-Text:
278
279
         GNU GENERAL PUBLIC LICENSE
280
--
281
2.17.1
282
283
diff view generated by jsdifflib
New patch
1
From: Eric Auger <eric.auger@redhat.com>
1
2
3
for KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION attribute, the attribute
4
data pointed to by kvm_device_attr.addr is a OR of the
5
redistributor region address and other fields such as the index
6
of the redistributor region and the number of redistributors the
7
region can contain.
8
9
The existing machine init done notifier framework sets the address
10
field to the actual address of the device and does not allow to OR
11
this value with other fields.
12
13
This patch extends the KVMDevice struct with a new kda_addr_ormask
14
member. Its value is passed at registration time and OR'ed with the
15
resolved address on kvm_arm_set_device_addr().
16
17
Signed-off-by: Eric Auger <eric.auger@redhat.com>
18
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
Message-id: 1529072910-16156-3-git-send-email-eric.auger@redhat.com
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
---
22
target/arm/kvm_arm.h | 3 ++-
23
hw/intc/arm_gic_kvm.c | 4 ++--
24
hw/intc/arm_gicv3_its_kvm.c | 2 +-
25
hw/intc/arm_gicv3_kvm.c | 4 ++--
26
target/arm/kvm.c | 10 +++++++++-
27
5 files changed, 16 insertions(+), 7 deletions(-)
28
29
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/kvm_arm.h
32
+++ b/target/arm/kvm_arm.h
33
@@ -XXX,XX +XXX,XX @@ int kvm_arm_vcpu_init(CPUState *cs);
34
* @group: device control API group for setting addresses
35
* @attr: device control API address type
36
* @dev_fd: device control device file descriptor (or -1 if not supported)
37
+ * @addr_ormask: value to be OR'ed with resolved address
38
*
39
* Remember the memory region @mr, and when it is mapped by the
40
* machine model, tell the kernel that base address using the
41
@@ -XXX,XX +XXX,XX @@ int kvm_arm_vcpu_init(CPUState *cs);
42
* address at the point where machine init is complete.
43
*/
44
void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group,
45
- uint64_t attr, int dev_fd);
46
+ uint64_t attr, int dev_fd, uint64_t addr_ormask);
47
48
/**
49
* kvm_arm_init_cpreg_list:
50
diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/hw/intc/arm_gic_kvm.c
53
+++ b/hw/intc/arm_gic_kvm.c
54
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
55
| KVM_VGIC_V2_ADDR_TYPE_DIST,
56
KVM_DEV_ARM_VGIC_GRP_ADDR,
57
KVM_VGIC_V2_ADDR_TYPE_DIST,
58
- s->dev_fd);
59
+ s->dev_fd, 0);
60
/* CPU interface for current core. Unlike arm_gic, we don't
61
* provide the "interface for core #N" memory regions, because
62
* cores with a VGIC don't have those.
63
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
64
| KVM_VGIC_V2_ADDR_TYPE_CPU,
65
KVM_DEV_ARM_VGIC_GRP_ADDR,
66
KVM_VGIC_V2_ADDR_TYPE_CPU,
67
- s->dev_fd);
68
+ s->dev_fd, 0);
69
70
if (kvm_has_gsi_routing()) {
71
/* set up irq routing */
72
diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c
73
index XXXXXXX..XXXXXXX 100644
74
--- a/hw/intc/arm_gicv3_its_kvm.c
75
+++ b/hw/intc/arm_gicv3_its_kvm.c
76
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_its_realize(DeviceState *dev, Error **errp)
77
78
/* register the base address */
79
kvm_arm_register_device(&s->iomem_its_cntrl, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
80
- KVM_VGIC_ITS_ADDR_TYPE, s->dev_fd);
81
+ KVM_VGIC_ITS_ADDR_TYPE, s->dev_fd, 0);
82
83
gicv3_its_init_mmio(s, NULL);
84
85
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/hw/intc/arm_gicv3_kvm.c
88
+++ b/hw/intc/arm_gicv3_kvm.c
89
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
90
KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true, &error_abort);
91
92
kvm_arm_register_device(&s->iomem_dist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
93
- KVM_VGIC_V3_ADDR_TYPE_DIST, s->dev_fd);
94
+ KVM_VGIC_V3_ADDR_TYPE_DIST, s->dev_fd, 0);
95
kvm_arm_register_device(&s->iomem_redist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
96
- KVM_VGIC_V3_ADDR_TYPE_REDIST, s->dev_fd);
97
+ KVM_VGIC_V3_ADDR_TYPE_REDIST, s->dev_fd, 0);
98
99
if (kvm_has_gsi_routing()) {
100
/* set up irq routing */
101
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
102
index XXXXXXX..XXXXXXX 100644
103
--- a/target/arm/kvm.c
104
+++ b/target/arm/kvm.c
105
@@ -XXX,XX +XXX,XX @@ unsigned long kvm_arch_vcpu_id(CPUState *cpu)
106
* We use a MemoryListener to track mapping and unmapping of
107
* the regions during board creation, so the board models don't
108
* need to do anything special for the KVM case.
109
+ *
110
+ * Sometimes the address must be OR'ed with some other fields
111
+ * (for example for KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION).
112
+ * @kda_addr_ormask aims at storing the value of those fields.
113
*/
114
typedef struct KVMDevice {
115
struct kvm_arm_device_addr kda;
116
struct kvm_device_attr kdattr;
117
+ uint64_t kda_addr_ormask;
118
MemoryRegion *mr;
119
QSLIST_ENTRY(KVMDevice) entries;
120
int dev_fd;
121
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_set_device_addr(KVMDevice *kd)
122
*/
123
if (kd->dev_fd >= 0) {
124
uint64_t addr = kd->kda.addr;
125
+
126
+ addr |= kd->kda_addr_ormask;
127
attr->addr = (uintptr_t)&addr;
128
ret = kvm_device_ioctl(kd->dev_fd, KVM_SET_DEVICE_ATTR, attr);
129
} else {
130
@@ -XXX,XX +XXX,XX @@ static Notifier notify = {
131
};
132
133
void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group,
134
- uint64_t attr, int dev_fd)
135
+ uint64_t attr, int dev_fd, uint64_t addr_ormask)
136
{
137
KVMDevice *kd;
138
139
@@ -XXX,XX +XXX,XX @@ void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid, uint64_t group,
140
kd->kdattr.group = group;
141
kd->kdattr.attr = attr;
142
kd->dev_fd = dev_fd;
143
+ kd->kda_addr_ormask = addr_ormask;
144
QSLIST_INSERT_HEAD(&kvm_devices_head, kd, entries);
145
memory_region_ref(kd->mr);
146
}
147
--
148
2.17.1
149
150
diff view generated by jsdifflib
New patch
1
1
From: Eric Auger <eric.auger@redhat.com>
2
3
To prepare for multiple redistributor regions, we introduce
4
an array of uint32_t properties that stores the redistributor
5
count of each redistributor region.
6
7
Non accelerated VGICv3 only supports a single redistributor region.
8
The capacity of all redist regions is checked against the number of
9
vcpus.
10
11
Machvirt is updated to set those properties, ie. a single
12
redistributor region with count set to the number of vcpus
13
capped by 123.
14
15
Signed-off-by: Eric Auger <eric.auger@redhat.com>
16
Reviewed-by: Andrew Jones <drjones@redhat.com>
17
Message-id: 1529072910-16156-4-git-send-email-eric.auger@redhat.com
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
20
include/hw/intc/arm_gicv3_common.h | 8 +++++--
21
hw/arm/virt.c | 11 ++++++++-
22
hw/intc/arm_gicv3.c | 12 +++++++++-
23
hw/intc/arm_gicv3_common.c | 38 ++++++++++++++++++++++++++----
24
hw/intc/arm_gicv3_kvm.c | 9 +++++--
25
5 files changed, 67 insertions(+), 11 deletions(-)
26
27
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
28
index XXXXXXX..XXXXXXX 100644
29
--- a/include/hw/intc/arm_gicv3_common.h
30
+++ b/include/hw/intc/arm_gicv3_common.h
31
@@ -XXX,XX +XXX,XX @@
32
#define GICV3_MAXIRQ 1020
33
#define GICV3_MAXSPI (GICV3_MAXIRQ - GIC_INTERNAL)
34
35
+#define GICV3_REDIST_SIZE 0x20000
36
+
37
/* Number of SGI target-list bits */
38
#define GICV3_TARGETLIST_BITS 16
39
40
@@ -XXX,XX +XXX,XX @@ struct GICv3State {
41
/*< public >*/
42
43
MemoryRegion iomem_dist; /* Distributor */
44
- MemoryRegion iomem_redist; /* Redistributors */
45
+ MemoryRegion *iomem_redist; /* Redistributor Regions */
46
+ uint32_t *redist_region_count; /* redistributor count within each region */
47
+ uint32_t nb_redist_regions; /* number of redist regions */
48
49
uint32_t num_cpu;
50
uint32_t num_irq;
51
@@ -XXX,XX +XXX,XX @@ typedef struct ARMGICv3CommonClass {
52
} ARMGICv3CommonClass;
53
54
void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
55
- const MemoryRegionOps *ops);
56
+ const MemoryRegionOps *ops, Error **errp);
57
58
#endif
59
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
60
index XXXXXXX..XXXXXXX 100644
61
--- a/hw/arm/virt.c
62
+++ b/hw/arm/virt.c
63
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
64
if (!kvm_irqchip_in_kernel()) {
65
qdev_prop_set_bit(gicdev, "has-security-extensions", vms->secure);
66
}
67
+
68
+ if (type == 3) {
69
+ uint32_t redist0_capacity =
70
+ vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
71
+ uint32_t redist0_count = MIN(smp_cpus, redist0_capacity);
72
+
73
+ qdev_prop_set_uint32(gicdev, "len-redist-region-count", 1);
74
+ qdev_prop_set_uint32(gicdev, "redist-region-count[0]", redist0_count);
75
+ }
76
qdev_init_nofail(gicdev);
77
gicbusdev = SYS_BUS_DEVICE(gicdev);
78
sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base);
79
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
80
* many redistributors we can fit into the memory map.
81
*/
82
if (vms->gic_version == 3) {
83
- virt_max_cpus = vms->memmap[VIRT_GIC_REDIST].size / 0x20000;
84
+ virt_max_cpus = vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
85
} else {
86
virt_max_cpus = GIC_NCPU;
87
}
88
diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c
89
index XXXXXXX..XXXXXXX 100644
90
--- a/hw/intc/arm_gicv3.c
91
+++ b/hw/intc/arm_gicv3.c
92
@@ -XXX,XX +XXX,XX @@ static void arm_gic_realize(DeviceState *dev, Error **errp)
93
return;
94
}
95
96
- gicv3_init_irqs_and_mmio(s, gicv3_set_irq, gic_ops);
97
+ if (s->nb_redist_regions != 1) {
98
+ error_setg(errp, "VGICv3 redist region number(%d) not equal to 1",
99
+ s->nb_redist_regions);
100
+ return;
101
+ }
102
+
103
+ gicv3_init_irqs_and_mmio(s, gicv3_set_irq, gic_ops, &local_err);
104
+ if (local_err) {
105
+ error_propagate(errp, local_err);
106
+ return;
107
+ }
108
109
gicv3_init_cpuif(s);
110
}
111
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
112
index XXXXXXX..XXXXXXX 100644
113
--- a/hw/intc/arm_gicv3_common.c
114
+++ b/hw/intc/arm_gicv3_common.c
115
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_gicv3 = {
116
};
117
118
void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
119
- const MemoryRegionOps *ops)
120
+ const MemoryRegionOps *ops, Error **errp)
121
{
122
SysBusDevice *sbd = SYS_BUS_DEVICE(s);
123
+ int rdist_capacity = 0;
124
int i;
125
126
+ for (i = 0; i < s->nb_redist_regions; i++) {
127
+ rdist_capacity += s->redist_region_count[i];
128
+ }
129
+ if (rdist_capacity < s->num_cpu) {
130
+ error_setg(errp, "Capacity of the redist regions(%d) "
131
+ "is less than number of vcpus(%d)",
132
+ rdist_capacity, s->num_cpu);
133
+ return;
134
+ }
135
+
136
/* For the GIC, also expose incoming GPIO lines for PPIs for each CPU.
137
* GPIO array layout is thus:
138
* [0..N-1] spi
139
@@ -XXX,XX +XXX,XX @@ void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
140
141
memory_region_init_io(&s->iomem_dist, OBJECT(s), ops, s,
142
"gicv3_dist", 0x10000);
143
- memory_region_init_io(&s->iomem_redist, OBJECT(s), ops ? &ops[1] : NULL, s,
144
- "gicv3_redist", 0x20000 * s->num_cpu);
145
-
146
sysbus_init_mmio(sbd, &s->iomem_dist);
147
- sysbus_init_mmio(sbd, &s->iomem_redist);
148
+
149
+ s->iomem_redist = g_new0(MemoryRegion, s->nb_redist_regions);
150
+ for (i = 0; i < s->nb_redist_regions; i++) {
151
+ char *name = g_strdup_printf("gicv3_redist_region[%d]", i);
152
+
153
+ memory_region_init_io(&s->iomem_redist[i], OBJECT(s),
154
+ ops ? &ops[1] : NULL, s, name,
155
+ s->redist_region_count[i] * GICV3_REDIST_SIZE);
156
+ sysbus_init_mmio(sbd, &s->iomem_redist[i]);
157
+ g_free(name);
158
+ }
159
}
160
161
static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
162
@@ -XXX,XX +XXX,XX @@ static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
163
}
164
}
165
166
+static void arm_gicv3_finalize(Object *obj)
167
+{
168
+ GICv3State *s = ARM_GICV3_COMMON(obj);
169
+
170
+ g_free(s->redist_region_count);
171
+}
172
+
173
static void arm_gicv3_common_reset(DeviceState *dev)
174
{
175
GICv3State *s = ARM_GICV3_COMMON(dev);
176
@@ -XXX,XX +XXX,XX @@ static Property arm_gicv3_common_properties[] = {
177
DEFINE_PROP_UINT32("num-irq", GICv3State, num_irq, 32),
178
DEFINE_PROP_UINT32("revision", GICv3State, revision, 3),
179
DEFINE_PROP_BOOL("has-security-extensions", GICv3State, security_extn, 0),
180
+ DEFINE_PROP_ARRAY("redist-region-count", GICv3State, nb_redist_regions,
181
+ redist_region_count, qdev_prop_uint32, uint32_t),
182
DEFINE_PROP_END_OF_LIST(),
183
};
184
185
@@ -XXX,XX +XXX,XX @@ static const TypeInfo arm_gicv3_common_type = {
186
.instance_size = sizeof(GICv3State),
187
.class_size = sizeof(ARMGICv3CommonClass),
188
.class_init = arm_gicv3_common_class_init,
189
+ .instance_finalize = arm_gicv3_finalize,
190
.abstract = true,
191
.interfaces = (InterfaceInfo []) {
192
{ TYPE_ARM_LINUX_BOOT_IF },
193
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
194
index XXXXXXX..XXXXXXX 100644
195
--- a/hw/intc/arm_gicv3_kvm.c
196
+++ b/hw/intc/arm_gicv3_kvm.c
197
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
198
return;
199
}
200
201
- gicv3_init_irqs_and_mmio(s, kvm_arm_gicv3_set_irq, NULL);
202
+ gicv3_init_irqs_and_mmio(s, kvm_arm_gicv3_set_irq, NULL, &local_err);
203
+ if (local_err) {
204
+ error_propagate(errp, local_err);
205
+ return;
206
+ }
207
208
for (i = 0; i < s->num_cpu; i++) {
209
ARMCPU *cpu = ARM_CPU(qemu_get_cpu(i));
210
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
211
212
kvm_arm_register_device(&s->iomem_dist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
213
KVM_VGIC_V3_ADDR_TYPE_DIST, s->dev_fd, 0);
214
- kvm_arm_register_device(&s->iomem_redist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
215
+ kvm_arm_register_device(&s->iomem_redist[0], -1,
216
+ KVM_DEV_ARM_VGIC_GRP_ADDR,
217
KVM_VGIC_V3_ADDR_TYPE_REDIST, s->dev_fd, 0);
218
219
if (kvm_has_gsi_routing()) {
220
--
221
2.17.1
222
223
diff view generated by jsdifflib
1
We currently define a bitmask for the GITS_CTLR ENABLED bit in
1
From: Eric Auger <eric.auger@redhat.com>
2
two ways: as ITS_CTLR_ENABLED, and via the FIELD() macro as
3
R_GITS_CTLR_ENABLED_MASK. Consistently use the FIELD macro version
4
everywhere and remove the redundant ITS_CTLR_ENABLED define.
5
2
3
Let's check if KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION is supported.
4
If not, we check the number of redist region is equal to 1 and use the
5
legacy KVM_VGIC_V3_ADDR_TYPE_REDIST attribute. Otherwise we use
6
the new attribute and allow to register multiple regions to the
7
KVM device.
8
9
Signed-off-by: Eric Auger <eric.auger@redhat.com>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Andrew Jones <drjones@redhat.com>
12
Message-id: 1529072910-16156-5-git-send-email-eric.auger@redhat.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
---
14
---
11
hw/intc/gicv3_internal.h | 2 --
15
hw/intc/arm_gicv3_kvm.c | 37 ++++++++++++++++++++++++++++++++++---
12
hw/intc/arm_gicv3_its.c | 20 ++++++++++----------
16
1 file changed, 34 insertions(+), 3 deletions(-)
13
2 files changed, 10 insertions(+), 12 deletions(-)
14
17
15
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
18
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/intc/gicv3_internal.h
20
--- a/hw/intc/arm_gicv3_kvm.c
18
+++ b/hw/intc/gicv3_internal.h
21
+++ b/hw/intc/arm_gicv3_kvm.c
19
@@ -XXX,XX +XXX,XX @@ FIELD(GITS_TYPER, CIL, 36, 1)
22
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
20
23
{
21
#define GITS_IDREGS 0xFFD0
24
GICv3State *s = KVM_ARM_GICV3(dev);
22
25
KVMARMGICv3Class *kgc = KVM_ARM_GICV3_GET_CLASS(s);
23
-#define ITS_CTLR_ENABLED (1U) /* ITS Enabled */
26
+ bool multiple_redist_region_allowed;
24
-
27
Error *local_err = NULL;
25
#define GITS_BASER_RO_MASK (R_GITS_BASER_ENTRYSIZE_MASK | \
26
R_GITS_BASER_TYPE_MASK)
27
28
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/hw/intc/arm_gicv3_its.c
31
+++ b/hw/intc/arm_gicv3_its.c
32
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
33
uint8_t cmd;
34
int i;
28
int i;
35
29
36
- if (!(s->ctlr & ITS_CTLR_ENABLED)) {
30
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
37
+ if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
38
return;
31
return;
39
}
32
}
40
33
41
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicv3_its_translation_write(void *opaque, hwaddr offset,
34
+ multiple_redist_region_allowed =
42
35
+ kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
43
switch (offset) {
36
+ KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION);
44
case GITS_TRANSLATER:
37
+
45
- if (s->ctlr & ITS_CTLR_ENABLED) {
38
+ if (!multiple_redist_region_allowed && s->nb_redist_regions > 1) {
46
+ if (s->ctlr & R_GITS_CTLR_ENABLED_MASK) {
39
+ error_setg(errp, "Multiple VGICv3 redistributor regions are not "
47
devid = attrs.requester_id;
40
+ "supported by this host kernel");
48
result = process_its_cmd(s, data, devid, NONE);
41
+ error_append_hint(errp, "A maximum of %d VCPUs can be used",
49
}
42
+ s->redist_region_count[0]);
50
@@ -XXX,XX +XXX,XX @@ static bool its_writel(GICv3ITSState *s, hwaddr offset,
43
+ return;
51
switch (offset) {
44
+ }
52
case GITS_CTLR:
45
+
53
if (value & R_GITS_CTLR_ENABLED_MASK) {
46
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS,
54
- s->ctlr |= ITS_CTLR_ENABLED;
47
0, &s->num_irq, true, &error_abort);
55
+ s->ctlr |= R_GITS_CTLR_ENABLED_MASK;
48
56
extract_table_params(s);
49
@@ -XXX,XX +XXX,XX @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp)
57
extract_cmdq_params(s);
50
58
s->creadr = 0;
51
kvm_arm_register_device(&s->iomem_dist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR,
59
process_cmdq(s);
52
KVM_VGIC_V3_ADDR_TYPE_DIST, s->dev_fd, 0);
60
} else {
53
- kvm_arm_register_device(&s->iomem_redist[0], -1,
61
- s->ctlr &= ~ITS_CTLR_ENABLED;
54
- KVM_DEV_ARM_VGIC_GRP_ADDR,
62
+ s->ctlr &= ~R_GITS_CTLR_ENABLED_MASK;
55
- KVM_VGIC_V3_ADDR_TYPE_REDIST, s->dev_fd, 0);
63
}
56
+
64
break;
57
+ if (!multiple_redist_region_allowed) {
65
case GITS_CBASER:
58
+ kvm_arm_register_device(&s->iomem_redist[0], -1,
66
@@ -XXX,XX +XXX,XX @@ static bool its_writel(GICv3ITSState *s, hwaddr offset,
59
+ KVM_DEV_ARM_VGIC_GRP_ADDR,
67
* IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
60
+ KVM_VGIC_V3_ADDR_TYPE_REDIST, s->dev_fd, 0);
68
* already enabled
61
+ } else {
69
*/
62
+ /* we register regions in reverse order as "devices" are inserted at
70
- if (!(s->ctlr & ITS_CTLR_ENABLED)) {
63
+ * the head of a QSLIST and the list is then popped from the head
71
+ if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
64
+ * onwards by kvm_arm_machine_init_done()
72
s->cbaser = deposit64(s->cbaser, 0, 32, value);
65
+ */
73
s->creadr = 0;
66
+ for (i = s->nb_redist_regions - 1; i >= 0; i--) {
74
s->cwriter = s->creadr;
67
+ /* Address mask made of the rdist region index and count */
75
@@ -XXX,XX +XXX,XX @@ static bool its_writel(GICv3ITSState *s, hwaddr offset,
68
+ uint64_t addr_ormask =
76
* IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
69
+ i | ((uint64_t)s->redist_region_count[i] << 52);
77
* already enabled
70
+
78
*/
71
+ kvm_arm_register_device(&s->iomem_redist[i], -1,
79
- if (!(s->ctlr & ITS_CTLR_ENABLED)) {
72
+ KVM_DEV_ARM_VGIC_GRP_ADDR,
80
+ if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
73
+ KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION,
81
s->cbaser = deposit64(s->cbaser, 32, 32, value);
74
+ s->dev_fd, addr_ormask);
82
s->creadr = 0;
75
+ }
83
s->cwriter = s->creadr;
76
+ }
84
@@ -XXX,XX +XXX,XX @@ static bool its_writel(GICv3ITSState *s, hwaddr offset,
77
85
* IMPDEF choice:- GITS_BASERn register becomes RO if ITS is
78
if (kvm_has_gsi_routing()) {
86
* already enabled
79
/* set up irq routing */
87
*/
88
- if (!(s->ctlr & ITS_CTLR_ENABLED)) {
89
+ if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
90
index = (offset - GITS_BASER) / 8;
91
92
if (offset & 7) {
93
@@ -XXX,XX +XXX,XX @@ static bool its_writell(GICv3ITSState *s, hwaddr offset,
94
* IMPDEF choice:- GITS_BASERn register becomes RO if ITS is
95
* already enabled
96
*/
97
- if (!(s->ctlr & ITS_CTLR_ENABLED)) {
98
+ if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
99
index = (offset - GITS_BASER) / 8;
100
s->baser[index] &= GITS_BASER_RO_MASK;
101
s->baser[index] |= (value & ~GITS_BASER_RO_MASK);
102
@@ -XXX,XX +XXX,XX @@ static bool its_writell(GICv3ITSState *s, hwaddr offset,
103
* IMPDEF choice:- GITS_CBASER register becomes RO if ITS is
104
* already enabled
105
*/
106
- if (!(s->ctlr & ITS_CTLR_ENABLED)) {
107
+ if (!(s->ctlr & R_GITS_CTLR_ENABLED_MASK)) {
108
s->cbaser = value;
109
s->creadr = 0;
110
s->cwriter = s->creadr;
111
@@ -XXX,XX +XXX,XX @@ static void gicv3_its_reset(DeviceState *dev)
112
113
static void gicv3_its_post_load(GICv3ITSState *s)
114
{
115
- if (s->ctlr & ITS_CTLR_ENABLED) {
116
+ if (s->ctlr & R_GITS_CTLR_ENABLED_MASK) {
117
extract_table_params(s);
118
extract_cmdq_params(s);
119
}
120
--
80
--
121
2.25.1
81
2.17.1
122
82
123
83
diff view generated by jsdifflib
New patch
1
From: Eric Auger <eric.auger@redhat.com>
1
2
3
This patch allows the creation of a GICv3 node with 1 or 2
4
redistributor regions depending on the number of smu_cpus.
5
The second redistributor region is located just after the
6
existing RAM region, at 256GB and contains up to up to 512 vcpus.
7
8
Please refer to kernel documentation for further node details:
9
Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt
10
11
Signed-off-by: Eric Auger <eric.auger@redhat.com>
12
Reviewed-by: Andrew Jones <drjones@redhat.com>
13
Message-id: 1529072910-16156-6-git-send-email-eric.auger@redhat.com
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
include/hw/arm/virt.h | 14 ++++++++++++++
17
hw/arm/virt.c | 29 ++++++++++++++++++++++++-----
18
2 files changed, 38 insertions(+), 5 deletions(-)
19
20
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/arm/virt.h
23
+++ b/include/hw/arm/virt.h
24
@@ -XXX,XX +XXX,XX @@
25
#include "qemu/notify.h"
26
#include "hw/boards.h"
27
#include "hw/arm/arm.h"
28
+#include "sysemu/kvm.h"
29
+#include "hw/intc/arm_gicv3_common.h"
30
31
#define NUM_GICV2M_SPIS 64
32
#define NUM_VIRTIO_TRANSPORTS 32
33
@@ -XXX,XX +XXX,XX @@ enum {
34
VIRT_GIC_V2M,
35
VIRT_GIC_ITS,
36
VIRT_GIC_REDIST,
37
+ VIRT_GIC_REDIST2,
38
VIRT_SMMU,
39
VIRT_UART,
40
VIRT_MMIO,
41
@@ -XXX,XX +XXX,XX @@ typedef struct {
42
43
void virt_acpi_setup(VirtMachineState *vms);
44
45
+/* Return the number of used redistributor regions */
46
+static inline int virt_gicv3_redist_region_count(VirtMachineState *vms)
47
+{
48
+ uint32_t redist0_capacity =
49
+ vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
50
+
51
+ assert(vms->gic_version == 3);
52
+
53
+ return vms->smp_cpus > redist0_capacity ? 2 : 1;
54
+}
55
+
56
#endif /* QEMU_ARM_VIRT_H */
57
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/hw/arm/virt.c
60
+++ b/hw/arm/virt.c
61
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry a15memmap[] = {
62
[VIRT_PCIE_PIO] = { 0x3eff0000, 0x00010000 },
63
[VIRT_PCIE_ECAM] = { 0x3f000000, 0x01000000 },
64
[VIRT_MEM] = { 0x40000000, RAMLIMIT_BYTES },
65
+ /* Additional 64 MB redist region (can contain up to 512 redistributors) */
66
+ [VIRT_GIC_REDIST2] = { 0x4000000000ULL, 0x4000000 },
67
/* Second PCIe window, 512GB wide at the 512GB boundary */
68
[VIRT_PCIE_MMIO_HIGH] = { 0x8000000000ULL, 0x8000000000ULL },
69
};
70
@@ -XXX,XX +XXX,XX @@ static void fdt_add_gic_node(VirtMachineState *vms)
71
qemu_fdt_setprop_cell(vms->fdt, "/intc", "#size-cells", 0x2);
72
qemu_fdt_setprop(vms->fdt, "/intc", "ranges", NULL, 0);
73
if (vms->gic_version == 3) {
74
+ int nb_redist_regions = virt_gicv3_redist_region_count(vms);
75
+
76
qemu_fdt_setprop_string(vms->fdt, "/intc", "compatible",
77
"arm,gic-v3");
78
- qemu_fdt_setprop_sized_cells(vms->fdt, "/intc", "reg",
79
- 2, vms->memmap[VIRT_GIC_DIST].base,
80
- 2, vms->memmap[VIRT_GIC_DIST].size,
81
- 2, vms->memmap[VIRT_GIC_REDIST].base,
82
- 2, vms->memmap[VIRT_GIC_REDIST].size);
83
+
84
+ qemu_fdt_setprop_cell(vms->fdt, "/intc",
85
+ "#redistributor-regions", nb_redist_regions);
86
+
87
+ if (nb_redist_regions == 1) {
88
+ qemu_fdt_setprop_sized_cells(vms->fdt, "/intc", "reg",
89
+ 2, vms->memmap[VIRT_GIC_DIST].base,
90
+ 2, vms->memmap[VIRT_GIC_DIST].size,
91
+ 2, vms->memmap[VIRT_GIC_REDIST].base,
92
+ 2, vms->memmap[VIRT_GIC_REDIST].size);
93
+ } else {
94
+ qemu_fdt_setprop_sized_cells(vms->fdt, "/intc", "reg",
95
+ 2, vms->memmap[VIRT_GIC_DIST].base,
96
+ 2, vms->memmap[VIRT_GIC_DIST].size,
97
+ 2, vms->memmap[VIRT_GIC_REDIST].base,
98
+ 2, vms->memmap[VIRT_GIC_REDIST].size,
99
+ 2, vms->memmap[VIRT_GIC_REDIST2].base,
100
+ 2, vms->memmap[VIRT_GIC_REDIST2].size);
101
+ }
102
+
103
if (vms->virt) {
104
qemu_fdt_setprop_cells(vms->fdt, "/intc", "interrupts",
105
GIC_FDT_IRQ_TYPE_PPI, ARCH_GICV3_MAINT_IRQ,
106
--
107
2.17.1
108
109
diff view generated by jsdifflib
New patch
1
From: Eric Auger <eric.auger@redhat.com>
1
2
3
Depending on the number of smp_cpus we now register one or two
4
GICR structures.
5
6
Signed-off-by: Eric Auger <eric.auger@redhat.com>
7
Reviewed-by: Andrew Jones <drjones@redhat.com>
8
Message-id: 1529072910-16156-7-git-send-email-eric.auger@redhat.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/arm/virt-acpi-build.c | 9 +++++++++
12
1 file changed, 9 insertions(+)
13
14
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/virt-acpi-build.c
17
+++ b/hw/arm/virt-acpi-build.c
18
@@ -XXX,XX +XXX,XX @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
19
20
if (vms->gic_version == 3) {
21
AcpiMadtGenericTranslator *gic_its;
22
+ int nb_redist_regions = virt_gicv3_redist_region_count(vms);
23
AcpiMadtGenericRedistributor *gicr = acpi_data_push(table_data,
24
sizeof *gicr);
25
26
@@ -XXX,XX +XXX,XX @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
27
gicr->base_address = cpu_to_le64(memmap[VIRT_GIC_REDIST].base);
28
gicr->range_length = cpu_to_le32(memmap[VIRT_GIC_REDIST].size);
29
30
+ if (nb_redist_regions == 2) {
31
+ gicr = acpi_data_push(table_data, sizeof(*gicr));
32
+ gicr->type = ACPI_APIC_GENERIC_REDISTRIBUTOR;
33
+ gicr->length = sizeof(*gicr);
34
+ gicr->base_address = cpu_to_le64(memmap[VIRT_GIC_REDIST2].base);
35
+ gicr->range_length = cpu_to_le32(memmap[VIRT_GIC_REDIST2].size);
36
+ }
37
+
38
if (its_class_name() && !vmc->no_its) {
39
gic_its = acpi_data_push(table_data, sizeof *gic_its);
40
gic_its->type = ACPI_APIC_GENERIC_TRANSLATOR;
41
--
42
2.17.1
43
44
diff view generated by jsdifflib
New patch
1
From: Eric Auger <eric.auger@redhat.com>
1
2
3
With a VGICv3 KVM device, if the number of vcpus exceeds the
4
capacity of the legacy redistributor region (123 redistributors),
5
we now attempt to register a second redistributor region. Up to
6
512 redistributors can fit in this latter on top of the 123 allowed
7
by the legacy redistributor region.
8
9
Registering this second redistributor region is possible if the
10
host kernel supports the following VGICv3 KVM device group/attribute:
11
KVM_DEV_ARM_VGIC_GRP_ADDR/KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION.
12
13
In case the host kernel does not support the registration of several
14
redistributor regions and the requested number of vcpus exceeds the
15
capacity of the legacy redistributor region, the GICv3 device
16
initialization fails with a proper error message and qemu exits.
17
18
At the moment the max number of vcpus still is capped by the
19
virt machine class max_cpus.
20
21
Signed-off-by: Eric Auger <eric.auger@redhat.com>
22
Reviewed-by: Andrew Jones <drjones@redhat.com>
23
Message-id: 1529072910-16156-8-git-send-email-eric.auger@redhat.com
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
---
26
hw/arm/virt.c | 18 +++++++++++++++++-
27
1 file changed, 17 insertions(+), 1 deletion(-)
28
29
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/virt.c
32
+++ b/hw/arm/virt.c
33
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
34
SysBusDevice *gicbusdev;
35
const char *gictype;
36
int type = vms->gic_version, i;
37
+ uint32_t nb_redist_regions = 0;
38
39
gictype = (type == 3) ? gicv3_class_name() : gic_class_name();
40
41
@@ -XXX,XX +XXX,XX @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
42
vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
43
uint32_t redist0_count = MIN(smp_cpus, redist0_capacity);
44
45
- qdev_prop_set_uint32(gicdev, "len-redist-region-count", 1);
46
+ nb_redist_regions = virt_gicv3_redist_region_count(vms);
47
+
48
+ qdev_prop_set_uint32(gicdev, "len-redist-region-count",
49
+ nb_redist_regions);
50
qdev_prop_set_uint32(gicdev, "redist-region-count[0]", redist0_count);
51
+
52
+ if (nb_redist_regions == 2) {
53
+ uint32_t redist1_capacity =
54
+ vms->memmap[VIRT_GIC_REDIST2].size / GICV3_REDIST_SIZE;
55
+
56
+ qdev_prop_set_uint32(gicdev, "redist-region-count[1]",
57
+ MIN(smp_cpus - redist0_count, redist1_capacity));
58
+ }
59
}
60
qdev_init_nofail(gicdev);
61
gicbusdev = SYS_BUS_DEVICE(gicdev);
62
sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base);
63
if (type == 3) {
64
sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_REDIST].base);
65
+ if (nb_redist_regions == 2) {
66
+ sysbus_mmio_map(gicbusdev, 2, vms->memmap[VIRT_GIC_REDIST2].base);
67
+ }
68
} else {
69
sysbus_mmio_map(gicbusdev, 1, vms->memmap[VIRT_GIC_CPU].base);
70
}
71
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
72
*/
73
if (vms->gic_version == 3) {
74
virt_max_cpus = vms->memmap[VIRT_GIC_REDIST].size / GICV3_REDIST_SIZE;
75
+ virt_max_cpus += vms->memmap[VIRT_GIC_REDIST2].size / GICV3_REDIST_SIZE;
76
} else {
77
virt_max_cpus = GIC_NCPU;
78
}
79
--
80
2.17.1
81
82
diff view generated by jsdifflib
1
In several places we have a local variable max_l2_entries which is
1
From: Eric Auger <eric.auger@redhat.com>
2
the number of entries which will fit in a level 2 table. The
3
calculations done on this value are correct; rename it to
4
num_l2_entries to fit the convention we're using in this code.
5
2
3
This patch defines a new ECAM region located after the 256GB limit.
4
5
The virt machine state is augmented with a new highmem_ecam field
6
which guards the usage of this new ECAM region instead of the legacy
7
16MB one. With the highmem ECAM region, up to 256 PCIe buses can be
8
used.
9
10
Signed-off-by: Eric Auger <eric.auger@redhat.com>
11
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
12
Reviewed-by: Andrew Jones <drjones@redhat.com>
13
Message-id: 1529072910-16156-9-git-send-email-eric.auger@redhat.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
---
15
---
11
hw/intc/arm_gicv3_its.c | 24 ++++++++++++------------
16
include/hw/arm/virt.h | 4 ++++
12
1 file changed, 12 insertions(+), 12 deletions(-)
17
hw/arm/virt-acpi-build.c | 21 +++++++++++++--------
18
hw/arm/virt.c | 12 ++++++++----
19
3 files changed, 25 insertions(+), 12 deletions(-)
13
20
14
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
21
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
15
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/arm_gicv3_its.c
23
--- a/include/hw/arm/virt.h
17
+++ b/hw/intc/arm_gicv3_its.c
24
+++ b/include/hw/arm/virt.h
18
@@ -XXX,XX +XXX,XX @@ static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte,
25
@@ -XXX,XX +XXX,XX @@ enum {
19
uint64_t value;
26
VIRT_PCIE_MMIO,
20
bool valid_l2t;
27
VIRT_PCIE_PIO,
21
uint32_t l2t_id;
28
VIRT_PCIE_ECAM,
22
- uint32_t max_l2_entries;
29
+ VIRT_PCIE_ECAM_HIGH,
23
+ uint32_t num_l2_entries;
30
VIRT_PLATFORM_BUS,
24
31
VIRT_PCIE_MMIO_HIGH,
25
if (s->ct.indirect) {
32
VIRT_GPIO,
26
l2t_id = icid / (s->ct.page_sz / L1TABLE_ENTRY_SIZE);
33
@@ -XXX,XX +XXX,XX @@ typedef struct {
27
@@ -XXX,XX +XXX,XX @@ static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte,
34
FWCfgState *fw_cfg;
28
valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
35
bool secure;
29
36
bool highmem;
30
if (valid_l2t) {
37
+ bool highmem_ecam;
31
- max_l2_entries = s->ct.page_sz / s->ct.entry_sz;
38
bool its;
32
+ num_l2_entries = s->ct.page_sz / s->ct.entry_sz;
39
bool virt;
33
40
int32_t gic_version;
34
l2t_addr = value & ((1ULL << 51) - 1);
41
@@ -XXX,XX +XXX,XX @@ typedef struct {
35
42
int psci_conduit;
36
*cte = address_space_ldq_le(as, l2t_addr +
43
} VirtMachineState;
37
- ((icid % max_l2_entries) * GITS_CTE_SIZE),
44
38
+ ((icid % num_l2_entries) * GITS_CTE_SIZE),
45
+#define VIRT_ECAM_ID(high) (high ? VIRT_PCIE_ECAM_HIGH : VIRT_PCIE_ECAM)
39
MEMTXATTRS_UNSPECIFIED, res);
46
+
40
}
47
#define TYPE_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
41
}
48
#define VIRT_MACHINE(obj) \
42
@@ -XXX,XX +XXX,XX @@ static uint64_t get_dte(GICv3ITSState *s, uint32_t devid, MemTxResult *res)
49
OBJECT_CHECK(VirtMachineState, (obj), TYPE_VIRT_MACHINE)
43
uint64_t value;
50
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
44
bool valid_l2t;
51
index XXXXXXX..XXXXXXX 100644
45
uint32_t l2t_id;
52
--- a/hw/arm/virt-acpi-build.c
46
- uint32_t max_l2_entries;
53
+++ b/hw/arm/virt-acpi-build.c
47
+ uint32_t num_l2_entries;
54
@@ -XXX,XX +XXX,XX @@ static void acpi_dsdt_add_virtio(Aml *scope,
48
55
}
49
if (s->dt.indirect) {
56
50
l2t_id = devid / (s->dt.page_sz / L1TABLE_ENTRY_SIZE);
57
static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
51
@@ -XXX,XX +XXX,XX @@ static uint64_t get_dte(GICv3ITSState *s, uint32_t devid, MemTxResult *res)
58
- uint32_t irq, bool use_highmem)
52
valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
59
+ uint32_t irq, bool use_highmem, bool highmem_ecam)
53
60
{
54
if (valid_l2t) {
61
+ int ecam_id = VIRT_ECAM_ID(highmem_ecam);
55
- max_l2_entries = s->dt.page_sz / s->dt.entry_sz;
62
Aml *method, *crs, *ifctx, *UUID, *ifctx1, *elsectx, *buf;
56
+ num_l2_entries = s->dt.page_sz / s->dt.entry_sz;
63
int i, bus_no;
57
64
hwaddr base_mmio = memmap[VIRT_PCIE_MMIO].base;
58
l2t_addr = value & ((1ULL << 51) - 1);
65
hwaddr size_mmio = memmap[VIRT_PCIE_MMIO].size;
59
66
hwaddr base_pio = memmap[VIRT_PCIE_PIO].base;
60
value = address_space_ldq_le(as, l2t_addr +
67
hwaddr size_pio = memmap[VIRT_PCIE_PIO].size;
61
- ((devid % max_l2_entries) * GITS_DTE_SIZE),
68
- hwaddr base_ecam = memmap[VIRT_PCIE_ECAM].base;
62
+ ((devid % num_l2_entries) * GITS_DTE_SIZE),
69
- hwaddr size_ecam = memmap[VIRT_PCIE_ECAM].size;
63
MEMTXATTRS_UNSPECIFIED, res);
70
+ hwaddr base_ecam = memmap[ecam_id].base;
64
}
71
+ hwaddr size_ecam = memmap[ecam_id].size;
65
}
72
int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
66
@@ -XXX,XX +XXX,XX @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
73
67
uint64_t l2t_addr;
74
Aml *dev = aml_device("%s", "PCI0");
68
bool valid_l2t;
75
@@ -XXX,XX +XXX,XX @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
69
uint32_t l2t_id;
76
aml_append(dev, aml_name_decl("_CCA", aml_int(1)));
70
- uint32_t max_l2_entries;
77
71
+ uint32_t num_l2_entries;
78
/* Declare the PCI Routing Table. */
72
uint64_t cte = 0;
79
- Aml *rt_pkg = aml_package(nr_pcie_buses * PCI_NUM_PINS);
73
MemTxResult res = MEMTX_OK;
80
+ Aml *rt_pkg = aml_varpackage(nr_pcie_buses * PCI_NUM_PINS);
74
81
for (bus_no = 0; bus_no < nr_pcie_buses; bus_no++) {
75
@@ -XXX,XX +XXX,XX @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
82
for (i = 0; i < PCI_NUM_PINS; i++) {
76
valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
83
int gsi = (i + bus_no) % PCI_NUM_PINS;
77
84
@@ -XXX,XX +XXX,XX @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
78
if (valid_l2t) {
85
Aml *dev_res0 = aml_device("%s", "RES0");
79
- max_l2_entries = s->ct.page_sz / s->ct.entry_sz;
86
aml_append(dev_res0, aml_name_decl("_HID", aml_string("PNP0C02")));
80
+ num_l2_entries = s->ct.page_sz / s->ct.entry_sz;
87
crs = aml_resource_template();
81
88
- aml_append(crs, aml_memory32_fixed(base_ecam, size_ecam, AML_READ_WRITE));
82
l2t_addr = value & ((1ULL << 51) - 1);
89
+ aml_append(crs,
83
90
+ aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
84
address_space_stq_le(as, l2t_addr +
91
+ AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000, base_ecam,
85
- ((icid % max_l2_entries) * GITS_CTE_SIZE),
92
+ base_ecam + size_ecam - 1, 0x0000, size_ecam));
86
+ ((icid % num_l2_entries) * GITS_CTE_SIZE),
93
aml_append(dev_res0, aml_name_decl("_CRS", crs));
87
cte, MEMTXATTRS_UNSPECIFIED, &res);
94
aml_append(dev, dev_res0);
88
}
95
aml_append(scope, dev);
89
} else {
96
@@ -XXX,XX +XXX,XX @@ build_mcfg(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
90
@@ -XXX,XX +XXX,XX @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
97
{
91
uint64_t l2t_addr;
98
AcpiTableMcfg *mcfg;
92
bool valid_l2t;
99
const MemMapEntry *memmap = vms->memmap;
93
uint32_t l2t_id;
100
+ int ecam_id = VIRT_ECAM_ID(vms->highmem_ecam);
94
- uint32_t max_l2_entries;
101
int len = sizeof(*mcfg) + sizeof(mcfg->allocation[0]);
95
+ uint32_t num_l2_entries;
102
int mcfg_start = table_data->len;
96
uint64_t dte = 0;
103
97
MemTxResult res = MEMTX_OK;
104
mcfg = acpi_data_push(table_data, len);
98
105
- mcfg->allocation[0].address = cpu_to_le64(memmap[VIRT_PCIE_ECAM].base);
99
@@ -XXX,XX +XXX,XX @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
106
+ mcfg->allocation[0].address = cpu_to_le64(memmap[ecam_id].base);
100
valid_l2t = (value & L2_TABLE_VALID_MASK) != 0;
107
101
108
/* Only a single allocation so no need to play with segments */
102
if (valid_l2t) {
109
mcfg->allocation[0].pci_segment = cpu_to_le16(0);
103
- max_l2_entries = s->dt.page_sz / s->dt.entry_sz;
110
mcfg->allocation[0].start_bus_number = 0;
104
+ num_l2_entries = s->dt.page_sz / s->dt.entry_sz;
111
- mcfg->allocation[0].end_bus_number = (memmap[VIRT_PCIE_ECAM].size
105
112
+ mcfg->allocation[0].end_bus_number = (memmap[ecam_id].size
106
l2t_addr = value & ((1ULL << 51) - 1);
113
/ PCIE_MMCFG_SIZE_MIN) - 1;
107
114
108
address_space_stq_le(as, l2t_addr +
115
build_header(linker, table_data, (void *)(table_data->data + mcfg_start),
109
- ((devid % max_l2_entries) * GITS_DTE_SIZE),
116
@@ -XXX,XX +XXX,XX @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
110
+ ((devid % num_l2_entries) * GITS_DTE_SIZE),
117
acpi_dsdt_add_virtio(scope, &memmap[VIRT_MMIO],
111
dte, MEMTXATTRS_UNSPECIFIED, &res);
118
(irqmap[VIRT_MMIO] + ARM_SPI_BASE), NUM_VIRTIO_TRANSPORTS);
112
}
119
acpi_dsdt_add_pci(scope, memmap, (irqmap[VIRT_PCIE] + ARM_SPI_BASE),
113
} else {
120
- vms->highmem);
121
+ vms->highmem, vms->highmem_ecam);
122
acpi_dsdt_add_gpio(scope, &memmap[VIRT_GPIO],
123
(irqmap[VIRT_GPIO] + ARM_SPI_BASE));
124
acpi_dsdt_add_power_button(scope);
125
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
126
index XXXXXXX..XXXXXXX 100644
127
--- a/hw/arm/virt.c
128
+++ b/hw/arm/virt.c
129
@@ -XXX,XX +XXX,XX @@ static const MemMapEntry a15memmap[] = {
130
[VIRT_MEM] = { 0x40000000, RAMLIMIT_BYTES },
131
/* Additional 64 MB redist region (can contain up to 512 redistributors) */
132
[VIRT_GIC_REDIST2] = { 0x4000000000ULL, 0x4000000 },
133
+ [VIRT_PCIE_ECAM_HIGH] = { 0x4010000000ULL, 0x10000000 },
134
/* Second PCIe window, 512GB wide at the 512GB boundary */
135
[VIRT_PCIE_MMIO_HIGH] = { 0x8000000000ULL, 0x8000000000ULL },
136
};
137
@@ -XXX,XX +XXX,XX @@ static void create_pcie(VirtMachineState *vms, qemu_irq *pic)
138
hwaddr size_mmio_high = vms->memmap[VIRT_PCIE_MMIO_HIGH].size;
139
hwaddr base_pio = vms->memmap[VIRT_PCIE_PIO].base;
140
hwaddr size_pio = vms->memmap[VIRT_PCIE_PIO].size;
141
- hwaddr base_ecam = vms->memmap[VIRT_PCIE_ECAM].base;
142
- hwaddr size_ecam = vms->memmap[VIRT_PCIE_ECAM].size;
143
+ hwaddr base_ecam, size_ecam;
144
hwaddr base = base_mmio;
145
- int nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
146
+ int nr_pcie_buses;
147
int irq = vms->irqmap[VIRT_PCIE];
148
MemoryRegion *mmio_alias;
149
MemoryRegion *mmio_reg;
150
@@ -XXX,XX +XXX,XX @@ static void create_pcie(VirtMachineState *vms, qemu_irq *pic)
151
MemoryRegion *ecam_reg;
152
DeviceState *dev;
153
char *nodename;
154
- int i;
155
+ int i, ecam_id;
156
PCIHostState *pci;
157
158
dev = qdev_create(NULL, TYPE_GPEX_HOST);
159
qdev_init_nofail(dev);
160
161
+ ecam_id = VIRT_ECAM_ID(vms->highmem_ecam);
162
+ base_ecam = vms->memmap[ecam_id].base;
163
+ size_ecam = vms->memmap[ecam_id].size;
164
+ nr_pcie_buses = size_ecam / PCIE_MMCFG_SIZE_MIN;
165
/* Map only the first size_ecam bytes of ECAM space */
166
ecam_alias = g_new0(MemoryRegion, 1);
167
ecam_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
114
--
168
--
115
2.25.1
169
2.17.1
116
170
117
171
diff view generated by jsdifflib
1
From: Shengtan Mao <stmao@google.com>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
Signed-off-by: Shengtan Mao <stmao@google.com>
3
Add virt-3.0 machine type.
4
Reviewed-by: Hao Wu <wuhaotsh@google.com>
4
5
Reviewed-by: Chris Rauer <crauer@google.com>
5
Signed-off-by: Eric Auger <eric.auger@redhat.com>
6
Message-id: 20220102215844.2888833-3-venture@google.com
6
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
7
Reviewed-by: Andrew Jones <drjones@redhat.com>
8
Message-id: 1529072910-16156-10-git-send-email-eric.auger@redhat.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
10
---
9
hw/arm/npcm7xx_boards.c | 1 +
11
hw/arm/virt.c | 15 +++++++++++++--
10
1 file changed, 1 insertion(+)
12
1 file changed, 13 insertions(+), 2 deletions(-)
11
13
12
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
14
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/npcm7xx_boards.c
16
--- a/hw/arm/virt.c
15
+++ b/hw/arm/npcm7xx_boards.c
17
+++ b/hw/arm/virt.c
16
@@ -XXX,XX +XXX,XX @@ static void kudo_bmc_init(MachineState *machine)
18
@@ -XXX,XX +XXX,XX @@ type_init(machvirt_machine_init);
17
drive_get(IF_MTD, 3, 0));
19
#define VIRT_COMPAT_2_12 \
18
20
HW_COMPAT_2_12
19
kudo_bmc_i2c_init(soc);
21
20
+ sdhci_attach_drive(&soc->mmc.sdhci, 0);
22
-static void virt_2_12_instance_init(Object *obj)
21
npcm7xx_load_kernel(machine, soc);
23
+static void virt_3_0_instance_init(Object *obj)
24
{
25
VirtMachineState *vms = VIRT_MACHINE(obj);
26
VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms);
27
@@ -XXX,XX +XXX,XX @@ static void virt_2_12_instance_init(Object *obj)
28
vms->irqmap = a15irqmap;
22
}
29
}
23
30
31
+static void virt_machine_3_0_options(MachineClass *mc)
32
+{
33
+}
34
+DEFINE_VIRT_MACHINE_AS_LATEST(3, 0)
35
+
36
+static void virt_2_12_instance_init(Object *obj)
37
+{
38
+ virt_3_0_instance_init(obj);
39
+}
40
+
41
static void virt_machine_2_12_options(MachineClass *mc)
42
{
43
+ virt_machine_3_0_options(mc);
44
SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_12);
45
}
46
-DEFINE_VIRT_MACHINE_AS_LATEST(2, 12)
47
+DEFINE_VIRT_MACHINE(2, 12)
48
49
#define VIRT_COMPAT_2_11 \
50
HW_COMPAT_2_11
24
--
51
--
25
2.25.1
52
2.17.1
26
53
27
54
diff view generated by jsdifflib
1
The MAPI command takes arguments DeviceID, EventID, ICID, and is
1
From: Eric Auger <eric.auger@redhat.com>
2
defined to be equivalent to MAPTI DeviceID, EventID, EventID, ICID.
3
(That is, where MAPTI takes an explicit pINTID, MAPI uses the EventID
4
as the pINTID.)
5
2
6
We didn't quite get this right. In particular the error checks for
3
With this patch, virt-3.0 machine uses a new 256MB ECAM region
7
MAPI include "EventID does not specify a valid LPI identifier", which
4
by default instead of the legacy 16MB one, if highmem is set
8
is the same as MAPTI's error check for the pINTID field. QEMU's code
5
(LPAE supported by the guest) and (!firmware_loaded || aarch64).
9
skips the pINTID error check entirely in the MAPI case.
10
6
11
We can fix this bug and in the process simplify the code by switching
7
Indeed aarch32 mode FW may not support this high ECAM region.
12
to the obvious implementation of setting pIntid = eventid early
13
if ignore_pInt is true.
14
8
9
Signed-off-by: Eric Auger <eric.auger@redhat.com>
10
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
11
Reviewed-by: Andrew Jones <drjones@redhat.com>
12
Message-id: 1529072910-16156-11-git-send-email-eric.auger@redhat.com
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
---
14
---
19
hw/intc/arm_gicv3_its.c | 18 +++++++-----------
15
include/hw/arm/virt.h | 1 +
20
1 file changed, 7 insertions(+), 11 deletions(-)
16
hw/arm/virt.c | 10 ++++++++++
17
2 files changed, 11 insertions(+)
21
18
22
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
19
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
23
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
24
--- a/hw/intc/arm_gicv3_its.c
21
--- a/include/hw/arm/virt.h
25
+++ b/hw/intc/arm_gicv3_its.c
22
+++ b/include/hw/arm/virt.h
26
@@ -XXX,XX +XXX,XX @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
23
@@ -XXX,XX +XXX,XX @@ typedef struct {
27
24
bool no_pmu;
28
eventid = (value & EVENTID_MASK);
25
bool claim_edge_triggered_timers;
29
26
bool smbios_old_sys_ver;
30
- if (!ignore_pInt) {
27
+ bool no_highmem_ecam;
31
+ if (ignore_pInt) {
28
} VirtMachineClass;
32
+ pIntid = eventid;
29
33
+ } else {
30
typedef struct {
34
pIntid = ((value & pINTID_MASK) >> pINTID_SHIFT);
31
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
32
index XXXXXXX..XXXXXXX 100644
33
--- a/hw/arm/virt.c
34
+++ b/hw/arm/virt.c
35
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
36
int n, virt_max_cpus;
37
MemoryRegion *ram = g_new(MemoryRegion, 1);
38
bool firmware_loaded = bios_name || drive_get(IF_PFLASH, 0, 0);
39
+ bool aarch64 = true;
40
41
/* We can probe only here because during property set
42
* KVM is not available yet
43
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
44
numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpuobj),
45
&error_fatal);
46
47
+ aarch64 &= object_property_get_bool(cpuobj, "aarch64", NULL);
48
+
49
if (!vms->secure) {
50
object_property_set_bool(cpuobj, false, "has_el3", NULL);
51
}
52
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
53
create_uart(vms, pic, VIRT_SECURE_UART, secure_sysmem, serial_hd(1));
35
}
54
}
36
55
37
@@ -XXX,XX +XXX,XX @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
56
+ vms->highmem_ecam &= vms->highmem && (!firmware_loaded || aarch64);
38
57
+
39
max_eventid = (1UL << (((dte >> 1U) & SIZE_MASK) + 1));
58
create_rtc(vms, pic);
40
59
41
- if (!ignore_pInt) {
60
create_pcie(vms, pic);
42
- max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1;
61
@@ -XXX,XX +XXX,XX @@ static void virt_3_0_instance_init(Object *obj)
43
- }
62
"Set GIC version. "
44
+ max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1;
63
"Valid values are 2, 3 and host", NULL);
45
64
46
if ((devid > s->dt.max_ids) || (icid > s->ct.max_ids)
65
+ vms->highmem_ecam = !vmc->no_highmem_ecam;
47
|| !dte_valid || (eventid > max_eventid) ||
66
+
48
- (!ignore_pInt && (((pIntid < GICV3_LPI_INTID_START) ||
67
if (vmc->no_its) {
49
- (pIntid > max_Intid)) && (pIntid != INTID_SPURIOUS)))) {
68
vms->its = false;
50
+ (((pIntid < GICV3_LPI_INTID_START) || (pIntid > max_Intid)) &&
69
} else {
51
+ (pIntid != INTID_SPURIOUS))) {
70
@@ -XXX,XX +XXX,XX @@ static void virt_2_12_instance_init(Object *obj)
52
qemu_log_mask(LOG_GUEST_ERROR,
71
53
"%s: invalid command attributes "
72
static void virt_machine_2_12_options(MachineClass *mc)
54
"devid %d or icid %d or eventid %d or pIntid %d or"
73
{
55
@@ -XXX,XX +XXX,XX @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
74
+ VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
56
IteEntry ite = {};
75
+
57
ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, dte_valid);
76
virt_machine_3_0_options(mc);
58
ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL);
77
SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_12);
59
- if (ignore_pInt) {
78
+ vmc->no_highmem_ecam = true;
60
- ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, eventid);
79
}
61
- } else {
80
DEFINE_VIRT_MACHINE(2, 12)
62
- ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, pIntid);
63
- }
64
+ ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, pIntid);
65
ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS);
66
ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, icid);
67
81
68
--
82
--
69
2.25.1
83
2.17.1
70
84
71
85
diff view generated by jsdifflib
1
From: Patrick Venture <venture@google.com>
1
From: Eric Auger <eric.auger@redhat.com>
2
2
3
Add the four lm75s behind the mux on bus 13.
3
virt 3.0 now allows up to 512 vcpus whereas for earlier machine
4
types, max_cpus was set to 255 and any attempt to start the
5
machine with vcpus > 255 was rejected at a very early stage,
6
in vl.c/main level.
4
7
5
Tested by booting the firmware:
8
512 is the max supported by KVM. Anyway the actual vcpu count
6
lm75 42-0048: hwmon0: sensor 'lm75'
9
that can be achieved depends on other parameters such as the
7
lm75 43-0049: supply vs not found, using dummy regulator
10
acceleration mode, the vgic version, the host kernel version.
8
lm75 43-0049: hwmon1: sensor 'lm75'
11
Those are discovered later on.
9
lm75 44-0048: supply vs not found, using dummy regulator
10
lm75 44-0048: hwmon2: sensor 'lm75'
11
lm75 45-0049: supply vs not found, using dummy regulator
12
lm75 45-0049: hwmon3: sensor 'lm75'
13
12
14
Signed-off-by: Patrick Venture <venture@google.com>
13
Signed-off-by: Eric Auger <eric.auger@redhat.com>
15
Reviewed-by: Titus Rwantare <titusr@google.com>
14
Reviewed-by: Andrew Jones <drjones@redhat.com>
16
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
Message-id: 1529072910-16156-12-git-send-email-eric.auger@redhat.com
17
Message-id: 20220102215844.2888833-5-venture@google.com
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
---
17
---
20
hw/arm/npcm7xx_boards.c | 11 ++++++++++-
18
hw/arm/virt.c | 7 ++++---
21
1 file changed, 10 insertions(+), 1 deletion(-)
19
1 file changed, 4 insertions(+), 3 deletions(-)
22
20
23
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
21
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
24
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/arm/npcm7xx_boards.c
23
--- a/hw/arm/virt.c
26
+++ b/hw/arm/npcm7xx_boards.c
24
+++ b/hw/arm/virt.c
27
@@ -XXX,XX +XXX,XX @@ static void quanta_gbs_i2c_init(NPCM7xxState *soc)
25
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
28
26
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
29
static void kudo_bmc_i2c_init(NPCM7xxState *soc)
27
30
{
28
mc->init = machvirt_init;
31
+ I2CSlave *i2c_mux;
29
- /* Start max_cpus at the maximum QEMU supports. We'll further restrict
32
+
30
- * it later in machvirt_init, where we have more information about the
33
i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), TYPE_PCA9548, 0x75);
31
+ /* Start with max_cpus set to 512, which is the maximum supported by KVM.
34
i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), TYPE_PCA9548, 0x77);
32
+ * The value may be reduced later when we have more information about the
35
33
* configuration of the particular instance.
36
@@ -XXX,XX +XXX,XX @@ static void kudo_bmc_i2c_init(NPCM7xxState *soc)
34
*/
37
35
- mc->max_cpus = 255;
38
at24c_eeprom_init(soc, 4, 0x50, 8192); /* mbfru */
36
+ mc->max_cpus = 512;
39
37
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_CALXEDA_XGMAC);
40
- i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 13), TYPE_PCA9548, 0x77);
38
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_AMD_XGBE);
41
+ i2c_mux = i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 13),
39
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
42
+ TYPE_PCA9548, 0x77);
40
@@ -XXX,XX +XXX,XX @@ static void virt_machine_2_12_options(MachineClass *mc)
43
+
41
virt_machine_3_0_options(mc);
44
+ /* tmp105 is compatible with the lm75 */
42
SET_MACHINE_COMPAT(mc, VIRT_COMPAT_2_12);
45
+ i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 2), "tmp105", 0x48);
43
vmc->no_highmem_ecam = true;
46
+ i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 3), "tmp105", 0x49);
44
+ mc->max_cpus = 255;
47
+ i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 4), "tmp105", 0x48);
45
}
48
+ i2c_slave_create_simple(pca954x_i2c_get_bus(i2c_mux, 5), "tmp105", 0x49);
46
DEFINE_VIRT_MACHINE(2, 12)
49
50
at24c_eeprom_init(soc, 14, 0x55, 8192); /* bmcfru */
51
47
52
--
48
--
53
2.25.1
49
2.17.1
54
50
55
51
diff view generated by jsdifflib
1
From: Patrick Venture <venture@google.com>
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
2
2
3
Signed-off-by: Patrick Venture <venture@google.com>
3
Add the Cortex-R5F with the optional FPU enabled.
4
Reviewed-by: Hao Wu <wuhaotsh@google.com>
4
5
Reviewed-by: KONRAD Frederic <frederic.konrad@adacore.com>
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20220102215844.2888833-4-venture@google.com
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
10
Message-id: 20180529124707.3025-2-edgar.iglesias@gmail.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
12
---
9
hw/arm/npcm7xx_boards.c | 9 +++++++++
13
target/arm/cpu.c | 9 +++++++++
10
1 file changed, 9 insertions(+)
14
1 file changed, 9 insertions(+)
11
15
12
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
16
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
13
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/npcm7xx_boards.c
18
--- a/target/arm/cpu.c
15
+++ b/hw/arm/npcm7xx_boards.c
19
+++ b/target/arm/cpu.c
16
@@ -XXX,XX +XXX,XX @@ static void quanta_gbs_i2c_init(NPCM7xxState *soc)
20
@@ -XXX,XX +XXX,XX @@ static void cortex_r5_initfn(Object *obj)
17
21
define_arm_cp_regs(cpu, cortexr5_cp_reginfo);
18
static void kudo_bmc_i2c_init(NPCM7xxState *soc)
22
}
19
{
23
20
+ i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), TYPE_PCA9548, 0x75);
24
+static void cortex_r5f_initfn(Object *obj)
21
+ i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 1), TYPE_PCA9548, 0x77);
25
+{
26
+ ARMCPU *cpu = ARM_CPU(obj);
22
+
27
+
23
+ i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 4), TYPE_PCA9548, 0x77);
28
+ cortex_r5_initfn(obj);
29
+ set_feature(&cpu->env, ARM_FEATURE_VFP3);
30
+}
24
+
31
+
25
at24c_eeprom_init(soc, 4, 0x50, 8192); /* mbfru */
32
static const ARMCPRegInfo cortexa8_cp_reginfo[] = {
26
+
33
{ .name = "L2LOCKDOWN", .cp = 15, .crn = 9, .crm = 0, .opc1 = 1, .opc2 = 0,
27
+ i2c_slave_create_simple(npcm7xx_i2c_get_bus(soc, 13), TYPE_PCA9548, 0x77);
34
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
28
+
35
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_cpus[] = {
29
at24c_eeprom_init(soc, 14, 0x55, 8192); /* bmcfru */
36
{ .name = "cortex-m33", .initfn = cortex_m33_initfn,
30
+
37
.class_init = arm_v7m_class_init },
31
/* TODO: Add remaining i2c devices. */
38
{ .name = "cortex-r5", .initfn = cortex_r5_initfn },
32
}
39
+ { .name = "cortex-r5f", .initfn = cortex_r5f_initfn },
33
40
{ .name = "cortex-a7", .initfn = cortex_a7_initfn },
41
{ .name = "cortex-a8", .initfn = cortex_a8_initfn },
42
{ .name = "cortex-a9", .initfn = cortex_a9_initfn },
34
--
43
--
35
2.25.1
44
2.17.1
36
45
37
46
diff view generated by jsdifflib
1
From: Idan Horowitz <idan.horowitz@gmail.com>
1
From: "Edgar E. Iglesias" <edgar.iglesias@xilinx.com>
2
2
3
Some of the instructions added by the FEAT_TLBIOS extension were forgotten
3
The ZynqMP has Cortex-R5Fs with the optional FPU enabled.
4
when the extension was originally added to QEMU.
5
4
6
Fixes: 7113d618505b ("target/arm: Add support for FEAT_TLBIOS")
5
Reviewed-by: KONRAD Frederic <frederic.konrad@adacore.com>
7
Signed-off-by: Idan Horowitz <idan.horowitz@gmail.com>
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20211231103928.1455657-1-idan.horowitz@gmail.com
8
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
10
Message-id: 20180529124707.3025-3-edgar.iglesias@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
target/arm/helper.c | 32 ++++++++++++++++++++++++++++++++
13
hw/arm/xlnx-zcu102.c | 2 +-
13
1 file changed, 32 insertions(+)
14
hw/arm/xlnx-zynqmp.c | 2 +-
15
2 files changed, 2 insertions(+), 2 deletions(-)
14
16
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
17
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
16
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper.c
19
--- a/hw/arm/xlnx-zcu102.c
18
+++ b/target/arm/helper.c
20
+++ b/hw/arm/xlnx-zcu102.c
19
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo tlbios_reginfo[] = {
21
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data)
20
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 0,
22
{
21
.access = PL1_W, .type = ARM_CP_NO_RAW,
23
MachineClass *mc = MACHINE_CLASS(oc);
22
.writefn = tlbi_aa64_vmalle1is_write },
24
23
+ { .name = "TLBI_VAE1OS", .state = ARM_CP_STATE_AA64,
25
- mc->desc = "Xilinx ZynqMP ZCU102 board with 4xA53s and 2xR5s based on " \
24
+ .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 1,
26
+ mc->desc = "Xilinx ZynqMP ZCU102 board with 4xA53s and 2xR5Fs based on " \
25
+ .access = PL1_W, .type = ARM_CP_NO_RAW,
27
"the value of smp";
26
+ .writefn = tlbi_aa64_vae1is_write },
28
mc->init = xlnx_zcu102_init;
27
{ .name = "TLBI_ASIDE1OS", .state = ARM_CP_STATE_AA64,
29
mc->block_default_type = IF_IDE;
28
.opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 2,
30
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
29
.access = PL1_W, .type = ARM_CP_NO_RAW,
31
index XXXXXXX..XXXXXXX 100644
30
.writefn = tlbi_aa64_vmalle1is_write },
32
--- a/hw/arm/xlnx-zynqmp.c
31
+ { .name = "TLBI_VAAE1OS", .state = ARM_CP_STATE_AA64,
33
+++ b/hw/arm/xlnx-zynqmp.c
32
+ .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 3,
34
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_create_rpu(XlnxZynqMPState *s, const char *boot_cpu,
33
+ .access = PL1_W, .type = ARM_CP_NO_RAW,
35
char *name;
34
+ .writefn = tlbi_aa64_vae1is_write },
36
35
+ { .name = "TLBI_VALE1OS", .state = ARM_CP_STATE_AA64,
37
object_initialize(&s->rpu_cpu[i], sizeof(s->rpu_cpu[i]),
36
+ .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 5,
38
- "cortex-r5-" TYPE_ARM_CPU);
37
+ .access = PL1_W, .type = ARM_CP_NO_RAW,
39
+ "cortex-r5f-" TYPE_ARM_CPU);
38
+ .writefn = tlbi_aa64_vae1is_write },
40
object_property_add_child(OBJECT(s), "rpu-cpu[*]",
39
+ { .name = "TLBI_VAALE1OS", .state = ARM_CP_STATE_AA64,
41
OBJECT(&s->rpu_cpu[i]), &error_abort);
40
+ .opc0 = 1, .opc1 = 0, .crn = 8, .crm = 1, .opc2 = 7,
41
+ .access = PL1_W, .type = ARM_CP_NO_RAW,
42
+ .writefn = tlbi_aa64_vae1is_write },
43
{ .name = "TLBI_ALLE2OS", .state = ARM_CP_STATE_AA64,
44
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 0,
45
.access = PL2_W, .type = ARM_CP_NO_RAW,
46
.writefn = tlbi_aa64_alle2is_write },
47
+ { .name = "TLBI_VAE2OS", .state = ARM_CP_STATE_AA64,
48
+ .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 1,
49
+ .access = PL2_W, .type = ARM_CP_NO_RAW,
50
+ .writefn = tlbi_aa64_vae2is_write },
51
{ .name = "TLBI_ALLE1OS", .state = ARM_CP_STATE_AA64,
52
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 4,
53
.access = PL2_W, .type = ARM_CP_NO_RAW,
54
.writefn = tlbi_aa64_alle1is_write },
55
+ { .name = "TLBI_VALE2OS", .state = ARM_CP_STATE_AA64,
56
+ .opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 5,
57
+ .access = PL2_W, .type = ARM_CP_NO_RAW,
58
+ .writefn = tlbi_aa64_vae2is_write },
59
{ .name = "TLBI_VMALLS12E1OS", .state = ARM_CP_STATE_AA64,
60
.opc0 = 1, .opc1 = 4, .crn = 8, .crm = 1, .opc2 = 6,
61
.access = PL2_W, .type = ARM_CP_NO_RAW,
62
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo tlbios_reginfo[] = {
63
.opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 0,
64
.access = PL3_W, .type = ARM_CP_NO_RAW,
65
.writefn = tlbi_aa64_alle3is_write },
66
+ { .name = "TLBI_VAE3OS", .state = ARM_CP_STATE_AA64,
67
+ .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 1,
68
+ .access = PL3_W, .type = ARM_CP_NO_RAW,
69
+ .writefn = tlbi_aa64_vae3is_write },
70
+ { .name = "TLBI_VALE3OS", .state = ARM_CP_STATE_AA64,
71
+ .opc0 = 1, .opc1 = 6, .crn = 8, .crm = 1, .opc2 = 5,
72
+ .access = PL3_W, .type = ARM_CP_NO_RAW,
73
+ .writefn = tlbi_aa64_vae3is_write },
74
REGINFO_SENTINEL
75
};
76
42
77
--
43
--
78
2.25.1
44
2.17.1
79
45
80
46
diff view generated by jsdifflib
1
The comment says that in our CTE format the RDBase field is 36 bits;
1
Implement the Arm TrustZone Memory Protection Controller, which sits
2
in fact for us it is only 16 bits, because we use the RDBase format
2
in front of RAM and allows secure software to configure it to either
3
where it specifies a 16-bit CPU number. The code already uses
3
pass through or reject transactions.
4
RDBASE_PROCNUM_LENGTH (16) as the field width, so fix the comment
4
5
to match it.
5
We implement the MPC as a QEMU IOMMU, which will direct transactions
6
either through to the devices and memory behind it or to a special
7
"never works" AddressSpace if they are blocked.
8
9
This initial commit implements the skeleton of the device:
10
* it always permits accesses
11
* it doesn't implement most of the registers
12
* it doesn't implement the interrupt or other behaviour
13
for blocked transactions
6
14
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
16
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Reviewed-by: Eric Auger <eric.auger@redhat.com>
18
Message-id: 20180620132032.28865-2-peter.maydell@linaro.org
10
---
19
---
11
hw/intc/gicv3_internal.h | 2 +-
20
hw/misc/Makefile.objs | 1 +
12
1 file changed, 1 insertion(+), 1 deletion(-)
21
include/hw/misc/tz-mpc.h | 70 ++++++
22
hw/misc/tz-mpc.c | 399 ++++++++++++++++++++++++++++++++
23
MAINTAINERS | 2 +
24
default-configs/arm-softmmu.mak | 1 +
25
hw/misc/trace-events | 7 +
26
6 files changed, 480 insertions(+)
27
create mode 100644 include/hw/misc/tz-mpc.h
28
create mode 100644 hw/misc/tz-mpc.c
13
29
14
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
30
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
15
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/gicv3_internal.h
32
--- a/hw/misc/Makefile.objs
17
+++ b/hw/intc/gicv3_internal.h
33
+++ b/hw/misc/Makefile.objs
18
@@ -XXX,XX +XXX,XX @@ FIELD(DTE, ITTADDR, 6, 44)
34
@@ -XXX,XX +XXX,XX @@ obj-$(CONFIG_MIPS_ITU) += mips_itu.o
19
35
obj-$(CONFIG_MPS2_FPGAIO) += mps2-fpgaio.o
20
/*
36
obj-$(CONFIG_MPS2_SCC) += mps2-scc.o
21
* 8 bytes Collection Table Entry size
37
22
- * Valid = 1 bit,RDBase = 36 bits(considering max RDBASE)
38
+obj-$(CONFIG_TZ_MPC) += tz-mpc.o
23
+ * Valid = 1 bit, RDBase = 16 bits
39
obj-$(CONFIG_TZ_PPC) += tz-ppc.o
24
*/
40
obj-$(CONFIG_IOTKIT_SECCTL) += iotkit-secctl.o
25
#define GITS_CTE_SIZE (0x8ULL)
41
26
#define GITS_CTE_RDBASE_PROCNUM_MASK MAKE_64BIT_MASK(1, RDBASE_PROCNUM_LENGTH)
42
diff --git a/include/hw/misc/tz-mpc.h b/include/hw/misc/tz-mpc.h
43
new file mode 100644
44
index XXXXXXX..XXXXXXX
45
--- /dev/null
46
+++ b/include/hw/misc/tz-mpc.h
47
@@ -XXX,XX +XXX,XX @@
48
+/*
49
+ * ARM AHB5 TrustZone Memory Protection Controller emulation
50
+ *
51
+ * Copyright (c) 2018 Linaro Limited
52
+ * Written by Peter Maydell
53
+ *
54
+ * This program is free software; you can redistribute it and/or modify
55
+ * it under the terms of the GNU General Public License version 2 or
56
+ * (at your option) any later version.
57
+ */
58
+
59
+/* This is a model of the TrustZone memory protection controller (MPC).
60
+ * It is documented in the ARM CoreLink SIE-200 System IP for Embedded TRM
61
+ * (DDI 0571G):
62
+ * https://developer.arm.com/products/architecture/m-profile/docs/ddi0571/g
63
+ *
64
+ * The MPC sits in front of memory and allows secure software to
65
+ * configure it to either pass through or reject transactions.
66
+ * Rejected transactions may be configured to either be aborted, or to
67
+ * behave as RAZ/WI. An interrupt can be signalled for a rejected transaction.
68
+ *
69
+ * The MPC has a register interface which the guest uses to configure it.
70
+ *
71
+ * QEMU interface:
72
+ * + sysbus MMIO region 0: MemoryRegion for the MPC's config registers
73
+ * + sysbus MMIO region 1: MemoryRegion for the upstream end of the MPC
74
+ * + Property "downstream": MemoryRegion defining the downstream memory
75
+ * + Named GPIO output "irq": set for a transaction-failed interrupt
76
+ */
77
+
78
+#ifndef TZ_MPC_H
79
+#define TZ_MPC_H
80
+
81
+#include "hw/sysbus.h"
82
+
83
+#define TYPE_TZ_MPC "tz-mpc"
84
+#define TZ_MPC(obj) OBJECT_CHECK(TZMPC, (obj), TYPE_TZ_MPC)
85
+
86
+#define TZ_NUM_PORTS 16
87
+
88
+#define TYPE_TZ_MPC_IOMMU_MEMORY_REGION "tz-mpc-iommu-memory-region"
89
+
90
+typedef struct TZMPC TZMPC;
91
+
92
+struct TZMPC {
93
+ /*< private >*/
94
+ SysBusDevice parent_obj;
95
+
96
+ /*< public >*/
97
+
98
+ qemu_irq irq;
99
+
100
+ /* Properties */
101
+ MemoryRegion *downstream;
102
+
103
+ hwaddr blocksize;
104
+ uint32_t blk_max;
105
+
106
+ /* MemoryRegions exposed to user */
107
+ MemoryRegion regmr;
108
+ IOMMUMemoryRegion upstream;
109
+
110
+ /* MemoryRegion used internally */
111
+ MemoryRegion blocked_io;
112
+
113
+ AddressSpace downstream_as;
114
+ AddressSpace blocked_io_as;
115
+};
116
+
117
+#endif
118
diff --git a/hw/misc/tz-mpc.c b/hw/misc/tz-mpc.c
119
new file mode 100644
120
index XXXXXXX..XXXXXXX
121
--- /dev/null
122
+++ b/hw/misc/tz-mpc.c
123
@@ -XXX,XX +XXX,XX @@
124
+/*
125
+ * ARM AHB5 TrustZone Memory Protection Controller emulation
126
+ *
127
+ * Copyright (c) 2018 Linaro Limited
128
+ * Written by Peter Maydell
129
+ *
130
+ * This program is free software; you can redistribute it and/or modify
131
+ * it under the terms of the GNU General Public License version 2 or
132
+ * (at your option) any later version.
133
+ */
134
+
135
+#include "qemu/osdep.h"
136
+#include "qemu/log.h"
137
+#include "qapi/error.h"
138
+#include "trace.h"
139
+#include "hw/sysbus.h"
140
+#include "hw/registerfields.h"
141
+#include "hw/misc/tz-mpc.h"
142
+
143
+/* Our IOMMU has two IOMMU indexes, one for secure transactions and one for
144
+ * non-secure transactions.
145
+ */
146
+enum {
147
+ IOMMU_IDX_S,
148
+ IOMMU_IDX_NS,
149
+ IOMMU_NUM_INDEXES,
150
+};
151
+
152
+/* Config registers */
153
+REG32(CTRL, 0x00)
154
+REG32(BLK_MAX, 0x10)
155
+REG32(BLK_CFG, 0x14)
156
+REG32(BLK_IDX, 0x18)
157
+REG32(BLK_LUT, 0x1c)
158
+REG32(INT_STAT, 0x20)
159
+REG32(INT_CLEAR, 0x24)
160
+REG32(INT_EN, 0x28)
161
+REG32(INT_INFO1, 0x2c)
162
+REG32(INT_INFO2, 0x30)
163
+REG32(INT_SET, 0x34)
164
+REG32(PIDR4, 0xfd0)
165
+REG32(PIDR5, 0xfd4)
166
+REG32(PIDR6, 0xfd8)
167
+REG32(PIDR7, 0xfdc)
168
+REG32(PIDR0, 0xfe0)
169
+REG32(PIDR1, 0xfe4)
170
+REG32(PIDR2, 0xfe8)
171
+REG32(PIDR3, 0xfec)
172
+REG32(CIDR0, 0xff0)
173
+REG32(CIDR1, 0xff4)
174
+REG32(CIDR2, 0xff8)
175
+REG32(CIDR3, 0xffc)
176
+
177
+static const uint8_t tz_mpc_idregs[] = {
178
+ 0x04, 0x00, 0x00, 0x00,
179
+ 0x60, 0xb8, 0x1b, 0x00,
180
+ 0x0d, 0xf0, 0x05, 0xb1,
181
+};
182
+
183
+static MemTxResult tz_mpc_reg_read(void *opaque, hwaddr addr,
184
+ uint64_t *pdata,
185
+ unsigned size, MemTxAttrs attrs)
186
+{
187
+ uint64_t r;
188
+ uint32_t offset = addr & ~0x3;
189
+
190
+ if (!attrs.secure && offset < A_PIDR4) {
191
+ /* NS accesses can only see the ID registers */
192
+ qemu_log_mask(LOG_GUEST_ERROR,
193
+ "TZ MPC register read: NS access to offset 0x%x\n",
194
+ offset);
195
+ r = 0;
196
+ goto read_out;
197
+ }
198
+
199
+ switch (offset) {
200
+ case A_PIDR4:
201
+ case A_PIDR5:
202
+ case A_PIDR6:
203
+ case A_PIDR7:
204
+ case A_PIDR0:
205
+ case A_PIDR1:
206
+ case A_PIDR2:
207
+ case A_PIDR3:
208
+ case A_CIDR0:
209
+ case A_CIDR1:
210
+ case A_CIDR2:
211
+ case A_CIDR3:
212
+ r = tz_mpc_idregs[(offset - A_PIDR4) / 4];
213
+ break;
214
+ case A_INT_CLEAR:
215
+ case A_INT_SET:
216
+ qemu_log_mask(LOG_GUEST_ERROR,
217
+ "TZ MPC register read: write-only offset 0x%x\n",
218
+ offset);
219
+ r = 0;
220
+ break;
221
+ default:
222
+ qemu_log_mask(LOG_GUEST_ERROR,
223
+ "TZ MPC register read: bad offset 0x%x\n", offset);
224
+ r = 0;
225
+ break;
226
+ }
227
+
228
+ if (size != 4) {
229
+ /* None of our registers are read-sensitive (except BLK_LUT,
230
+ * which can special case the "size not 4" case), so just
231
+ * pull the right bytes out of the word read result.
232
+ */
233
+ r = extract32(r, (addr & 3) * 8, size * 8);
234
+ }
235
+
236
+read_out:
237
+ trace_tz_mpc_reg_read(addr, r, size);
238
+ *pdata = r;
239
+ return MEMTX_OK;
240
+}
241
+
242
+static MemTxResult tz_mpc_reg_write(void *opaque, hwaddr addr,
243
+ uint64_t value,
244
+ unsigned size, MemTxAttrs attrs)
245
+{
246
+ uint32_t offset = addr & ~0x3;
247
+
248
+ trace_tz_mpc_reg_write(addr, value, size);
249
+
250
+ if (!attrs.secure && offset < A_PIDR4) {
251
+ /* NS accesses can only see the ID registers */
252
+ qemu_log_mask(LOG_GUEST_ERROR,
253
+ "TZ MPC register write: NS access to offset 0x%x\n",
254
+ offset);
255
+ return MEMTX_OK;
256
+ }
257
+
258
+ if (size != 4) {
259
+ /* Expand the byte or halfword write to a full word size.
260
+ * In most cases we can do this with zeroes; the exceptions
261
+ * are CTRL, BLK_IDX and BLK_LUT.
262
+ */
263
+ uint32_t oldval;
264
+
265
+ switch (offset) {
266
+ /* As we add support for registers which need expansions
267
+ * other than zeroes we'll fill in cases here.
268
+ */
269
+ default:
270
+ oldval = 0;
271
+ break;
272
+ }
273
+ value = deposit32(oldval, (addr & 3) * 8, size * 8, value);
274
+ }
275
+
276
+ switch (offset) {
277
+ case A_PIDR4:
278
+ case A_PIDR5:
279
+ case A_PIDR6:
280
+ case A_PIDR7:
281
+ case A_PIDR0:
282
+ case A_PIDR1:
283
+ case A_PIDR2:
284
+ case A_PIDR3:
285
+ case A_CIDR0:
286
+ case A_CIDR1:
287
+ case A_CIDR2:
288
+ case A_CIDR3:
289
+ qemu_log_mask(LOG_GUEST_ERROR,
290
+ "TZ MPC register write: read-only offset 0x%x\n", offset);
291
+ break;
292
+ default:
293
+ qemu_log_mask(LOG_GUEST_ERROR,
294
+ "TZ MPC register write: bad offset 0x%x\n", offset);
295
+ break;
296
+ }
297
+
298
+ return MEMTX_OK;
299
+}
300
+
301
+static const MemoryRegionOps tz_mpc_reg_ops = {
302
+ .read_with_attrs = tz_mpc_reg_read,
303
+ .write_with_attrs = tz_mpc_reg_write,
304
+ .endianness = DEVICE_LITTLE_ENDIAN,
305
+ .valid.min_access_size = 1,
306
+ .valid.max_access_size = 4,
307
+ .impl.min_access_size = 1,
308
+ .impl.max_access_size = 4,
309
+};
310
+
311
+/* Accesses only reach these read and write functions if the MPC is
312
+ * blocking them; non-blocked accesses go directly to the downstream
313
+ * memory region without passing through this code.
314
+ */
315
+static MemTxResult tz_mpc_mem_blocked_read(void *opaque, hwaddr addr,
316
+ uint64_t *pdata,
317
+ unsigned size, MemTxAttrs attrs)
318
+{
319
+ trace_tz_mpc_mem_blocked_read(addr, size, attrs.secure);
320
+
321
+ *pdata = 0;
322
+ return MEMTX_OK;
323
+}
324
+
325
+static MemTxResult tz_mpc_mem_blocked_write(void *opaque, hwaddr addr,
326
+ uint64_t value,
327
+ unsigned size, MemTxAttrs attrs)
328
+{
329
+ trace_tz_mpc_mem_blocked_write(addr, value, size, attrs.secure);
330
+
331
+ return MEMTX_OK;
332
+}
333
+
334
+static const MemoryRegionOps tz_mpc_mem_blocked_ops = {
335
+ .read_with_attrs = tz_mpc_mem_blocked_read,
336
+ .write_with_attrs = tz_mpc_mem_blocked_write,
337
+ .endianness = DEVICE_LITTLE_ENDIAN,
338
+ .valid.min_access_size = 1,
339
+ .valid.max_access_size = 8,
340
+ .impl.min_access_size = 1,
341
+ .impl.max_access_size = 8,
342
+};
343
+
344
+static IOMMUTLBEntry tz_mpc_translate(IOMMUMemoryRegion *iommu,
345
+ hwaddr addr, IOMMUAccessFlags flags,
346
+ int iommu_idx)
347
+{
348
+ TZMPC *s = TZ_MPC(container_of(iommu, TZMPC, upstream));
349
+ bool ok;
350
+
351
+ IOMMUTLBEntry ret = {
352
+ .iova = addr & ~(s->blocksize - 1),
353
+ .translated_addr = addr & ~(s->blocksize - 1),
354
+ .addr_mask = s->blocksize - 1,
355
+ .perm = IOMMU_RW,
356
+ };
357
+
358
+ /* Look at the per-block configuration for this address, and
359
+ * return a TLB entry directing the transaction at either
360
+ * downstream_as or blocked_io_as, as appropriate.
361
+ * For the moment, always permit accesses.
362
+ */
363
+ ok = true;
364
+
365
+ trace_tz_mpc_translate(addr, flags,
366
+ iommu_idx == IOMMU_IDX_S ? "S" : "NS",
367
+ ok ? "pass" : "block");
368
+
369
+ ret.target_as = ok ? &s->downstream_as : &s->blocked_io_as;
370
+ return ret;
371
+}
372
+
373
+static int tz_mpc_attrs_to_index(IOMMUMemoryRegion *iommu, MemTxAttrs attrs)
374
+{
375
+ /* We treat unspecified attributes like secure. Transactions with
376
+ * unspecified attributes come from places like
377
+ * cpu_physical_memory_write_rom() for initial image load, and we want
378
+ * those to pass through the from-reset "everything is secure" config.
379
+ * All the real during-emulation transactions from the CPU will
380
+ * specify attributes.
381
+ */
382
+ return (attrs.unspecified || attrs.secure) ? IOMMU_IDX_S : IOMMU_IDX_NS;
383
+}
384
+
385
+static int tz_mpc_num_indexes(IOMMUMemoryRegion *iommu)
386
+{
387
+ return IOMMU_NUM_INDEXES;
388
+}
389
+
390
+static void tz_mpc_reset(DeviceState *dev)
391
+{
392
+}
393
+
394
+static void tz_mpc_init(Object *obj)
395
+{
396
+ DeviceState *dev = DEVICE(obj);
397
+ TZMPC *s = TZ_MPC(obj);
398
+
399
+ qdev_init_gpio_out_named(dev, &s->irq, "irq", 1);
400
+}
401
+
402
+static void tz_mpc_realize(DeviceState *dev, Error **errp)
403
+{
404
+ Object *obj = OBJECT(dev);
405
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
406
+ TZMPC *s = TZ_MPC(dev);
407
+ uint64_t size;
408
+
409
+ /* We can't create the upstream end of the port until realize,
410
+ * as we don't know the size of the MR used as the downstream until then.
411
+ * We insist on having a downstream, to avoid complicating the code
412
+ * with handling the "don't know how big this is" case. It's easy
413
+ * enough for the user to create an unimplemented_device as downstream
414
+ * if they have nothing else to plug into this.
415
+ */
416
+ if (!s->downstream) {
417
+ error_setg(errp, "MPC 'downstream' link not set");
418
+ return;
419
+ }
420
+
421
+ size = memory_region_size(s->downstream);
422
+
423
+ memory_region_init_iommu(&s->upstream, sizeof(s->upstream),
424
+ TYPE_TZ_MPC_IOMMU_MEMORY_REGION,
425
+ obj, "tz-mpc-upstream", size);
426
+
427
+ /* In real hardware the block size is configurable. In QEMU we could
428
+ * make it configurable but will need it to be at least as big as the
429
+ * target page size so we can execute out of the resulting MRs. Guest
430
+ * software is supposed to check the block size using the BLK_CFG
431
+ * register, so make it fixed at the page size.
432
+ */
433
+ s->blocksize = memory_region_iommu_get_min_page_size(&s->upstream);
434
+ if (size % s->blocksize != 0) {
435
+ error_setg(errp,
436
+ "MPC 'downstream' size %" PRId64
437
+ " is not a multiple of %" HWADDR_PRIx " bytes",
438
+ size, s->blocksize);
439
+ object_unref(OBJECT(&s->upstream));
440
+ return;
441
+ }
442
+
443
+ /* BLK_MAX is the max value of BLK_IDX, which indexes an array of 32-bit
444
+ * words, each bit of which indicates one block.
445
+ */
446
+ s->blk_max = DIV_ROUND_UP(size / s->blocksize, 32);
447
+
448
+ memory_region_init_io(&s->regmr, obj, &tz_mpc_reg_ops,
449
+ s, "tz-mpc-regs", 0x1000);
450
+ sysbus_init_mmio(sbd, &s->regmr);
451
+
452
+ sysbus_init_mmio(sbd, MEMORY_REGION(&s->upstream));
453
+
454
+ /* This memory region is not exposed to users of this device as a
455
+ * sysbus MMIO region, but is instead used internally as something
456
+ * that our IOMMU translate function might direct accesses to.
457
+ */
458
+ memory_region_init_io(&s->blocked_io, obj, &tz_mpc_mem_blocked_ops,
459
+ s, "tz-mpc-blocked-io", size);
460
+
461
+ address_space_init(&s->downstream_as, s->downstream,
462
+ "tz-mpc-downstream");
463
+ address_space_init(&s->blocked_io_as, &s->blocked_io,
464
+ "tz-mpc-blocked-io");
465
+}
466
+
467
+static const VMStateDescription tz_mpc_vmstate = {
468
+ .name = "tz-mpc",
469
+ .version_id = 1,
470
+ .minimum_version_id = 1,
471
+ .fields = (VMStateField[]) {
472
+ VMSTATE_END_OF_LIST()
473
+ }
474
+};
475
+
476
+static Property tz_mpc_properties[] = {
477
+ DEFINE_PROP_LINK("downstream", TZMPC, downstream,
478
+ TYPE_MEMORY_REGION, MemoryRegion *),
479
+ DEFINE_PROP_END_OF_LIST(),
480
+};
481
+
482
+static void tz_mpc_class_init(ObjectClass *klass, void *data)
483
+{
484
+ DeviceClass *dc = DEVICE_CLASS(klass);
485
+
486
+ dc->realize = tz_mpc_realize;
487
+ dc->vmsd = &tz_mpc_vmstate;
488
+ dc->reset = tz_mpc_reset;
489
+ dc->props = tz_mpc_properties;
490
+}
491
+
492
+static const TypeInfo tz_mpc_info = {
493
+ .name = TYPE_TZ_MPC,
494
+ .parent = TYPE_SYS_BUS_DEVICE,
495
+ .instance_size = sizeof(TZMPC),
496
+ .instance_init = tz_mpc_init,
497
+ .class_init = tz_mpc_class_init,
498
+};
499
+
500
+static void tz_mpc_iommu_memory_region_class_init(ObjectClass *klass,
501
+ void *data)
502
+{
503
+ IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
504
+
505
+ imrc->translate = tz_mpc_translate;
506
+ imrc->attrs_to_index = tz_mpc_attrs_to_index;
507
+ imrc->num_indexes = tz_mpc_num_indexes;
508
+}
509
+
510
+static const TypeInfo tz_mpc_iommu_memory_region_info = {
511
+ .name = TYPE_TZ_MPC_IOMMU_MEMORY_REGION,
512
+ .parent = TYPE_IOMMU_MEMORY_REGION,
513
+ .class_init = tz_mpc_iommu_memory_region_class_init,
514
+};
515
+
516
+static void tz_mpc_register_types(void)
517
+{
518
+ type_register_static(&tz_mpc_info);
519
+ type_register_static(&tz_mpc_iommu_memory_region_info);
520
+}
521
+
522
+type_init(tz_mpc_register_types);
523
diff --git a/MAINTAINERS b/MAINTAINERS
524
index XXXXXXX..XXXXXXX 100644
525
--- a/MAINTAINERS
526
+++ b/MAINTAINERS
527
@@ -XXX,XX +XXX,XX @@ F: hw/char/cmsdk-apb-uart.c
528
F: include/hw/char/cmsdk-apb-uart.h
529
F: hw/misc/tz-ppc.c
530
F: include/hw/misc/tz-ppc.h
531
+F: hw/misc/tz-mpc.c
532
+F: include/hw/misc/tz-mpc.h
533
534
ARM cores
535
M: Peter Maydell <peter.maydell@linaro.org>
536
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
537
index XXXXXXX..XXXXXXX 100644
538
--- a/default-configs/arm-softmmu.mak
539
+++ b/default-configs/arm-softmmu.mak
540
@@ -XXX,XX +XXX,XX @@ CONFIG_CMSDK_APB_UART=y
541
CONFIG_MPS2_FPGAIO=y
542
CONFIG_MPS2_SCC=y
543
544
+CONFIG_TZ_MPC=y
545
CONFIG_TZ_PPC=y
546
CONFIG_IOTKIT=y
547
CONFIG_IOTKIT_SECCTL=y
548
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
549
index XXXXXXX..XXXXXXX 100644
550
--- a/hw/misc/trace-events
551
+++ b/hw/misc/trace-events
552
@@ -XXX,XX +XXX,XX @@ mos6522_set_sr_int(void) "set sr_int"
553
mos6522_write(uint64_t addr, uint64_t val) "reg=0x%"PRIx64 " val=0x%"PRIx64
554
mos6522_read(uint64_t addr, unsigned val) "reg=0x%"PRIx64 " val=0x%x"
555
556
+# hw/misc/tz-mpc.c
557
+tz_mpc_reg_read(uint32_t offset, uint64_t data, unsigned size) "TZ MPC regs read: offset 0x%x data 0x%" PRIx64 " size %u"
558
+tz_mpc_reg_write(uint32_t offset, uint64_t data, unsigned size) "TZ MPC regs write: offset 0x%x data 0x%" PRIx64 " size %u"
559
+tz_mpc_mem_blocked_read(uint64_t addr, unsigned size, bool secure) "TZ MPC blocked read: offset 0x%" PRIx64 " size %u secure %d"
560
+tz_mpc_mem_blocked_write(uint64_t addr, uint64_t data, unsigned size, bool secure) "TZ MPC blocked write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d"
561
+tz_mpc_translate(uint64_t addr, int flags, const char *idx, const char *res) "TZ MPC translate: addr 0x%" PRIx64 " flags 0x%x iommu_idx %s: %s"
562
+
563
# hw/misc/tz-ppc.c
564
tz_ppc_reset(void) "TZ PPC: reset"
565
tz_ppc_cfg_nonsec(int n, int level) "TZ PPC: cfg_nonsec[%d] = %d"
27
--
566
--
28
2.25.1
567
2.17.1
29
568
30
569
diff view generated by jsdifflib
1
Use FIELD macros to handle CTEs, rather than ad-hoc mask-and-shift.
1
Implement the missing registers for the TZ MPC.
2
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
4
Reviewed-by: Eric Auger <eric.auger@redhat.com>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20180620132032.28865-3-peter.maydell@linaro.org
6
---
6
---
7
hw/intc/gicv3_internal.h | 3 ++-
7
include/hw/misc/tz-mpc.h | 10 +++
8
hw/intc/arm_gicv3_its.c | 7 ++++---
8
hw/misc/tz-mpc.c | 140 ++++++++++++++++++++++++++++++++++++++-
9
2 files changed, 6 insertions(+), 4 deletions(-)
9
2 files changed, 147 insertions(+), 3 deletions(-)
10
10
11
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
11
diff --git a/include/hw/misc/tz-mpc.h b/include/hw/misc/tz-mpc.h
12
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/intc/gicv3_internal.h
13
--- a/include/hw/misc/tz-mpc.h
14
+++ b/hw/intc/gicv3_internal.h
14
+++ b/include/hw/misc/tz-mpc.h
15
@@ -XXX,XX +XXX,XX @@ FIELD(DTE, ITTADDR, 6, 44)
15
@@ -XXX,XX +XXX,XX @@ struct TZMPC {
16
* Valid = 1 bit, RDBase = 16 bits
16
17
*/
17
/*< public >*/
18
#define GITS_CTE_SIZE (0x8ULL)
18
19
-#define GITS_CTE_RDBASE_PROCNUM_MASK MAKE_64BIT_MASK(1, RDBASE_PROCNUM_LENGTH)
19
+ /* State */
20
+FIELD(CTE, VALID, 0, 1)
20
+ uint32_t ctrl;
21
+FIELD(CTE, RDBASE, 1, RDBASE_PROCNUM_LENGTH)
21
+ uint32_t blk_idx;
22
22
+ uint32_t int_stat;
23
/* Special interrupt IDs */
23
+ uint32_t int_en;
24
#define INTID_SECURE 1020
24
+ uint32_t int_info1;
25
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
25
+ uint32_t int_info2;
26
+
27
+ uint32_t *blk_lut;
28
+
29
qemu_irq irq;
30
31
/* Properties */
32
diff --git a/hw/misc/tz-mpc.c b/hw/misc/tz-mpc.c
26
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
27
--- a/hw/intc/arm_gicv3_its.c
34
--- a/hw/misc/tz-mpc.c
28
+++ b/hw/intc/arm_gicv3_its.c
35
+++ b/hw/misc/tz-mpc.c
29
@@ -XXX,XX +XXX,XX @@ static bool get_cte(GICv3ITSState *s, uint16_t icid, uint64_t *cte,
36
@@ -XXX,XX +XXX,XX @@ enum {
30
MEMTXATTRS_UNSPECIFIED, res);
37
38
/* Config registers */
39
REG32(CTRL, 0x00)
40
+ FIELD(CTRL, SEC_RESP, 4, 1)
41
+ FIELD(CTRL, AUTOINC, 8, 1)
42
+ FIELD(CTRL, LOCKDOWN, 31, 1)
43
REG32(BLK_MAX, 0x10)
44
REG32(BLK_CFG, 0x14)
45
REG32(BLK_IDX, 0x18)
46
REG32(BLK_LUT, 0x1c)
47
REG32(INT_STAT, 0x20)
48
+ FIELD(INT_STAT, IRQ, 0, 1)
49
REG32(INT_CLEAR, 0x24)
50
+ FIELD(INT_CLEAR, IRQ, 0, 1)
51
REG32(INT_EN, 0x28)
52
+ FIELD(INT_EN, IRQ, 0, 1)
53
REG32(INT_INFO1, 0x2c)
54
REG32(INT_INFO2, 0x30)
55
REG32(INT_SET, 0x34)
56
+ FIELD(INT_SET, IRQ, 0, 1)
57
REG32(PIDR4, 0xfd0)
58
REG32(PIDR5, 0xfd4)
59
REG32(PIDR6, 0xfd8)
60
@@ -XXX,XX +XXX,XX @@ static const uint8_t tz_mpc_idregs[] = {
61
0x0d, 0xf0, 0x05, 0xb1,
62
};
63
64
+static void tz_mpc_irq_update(TZMPC *s)
65
+{
66
+ qemu_set_irq(s->irq, s->int_stat && s->int_en);
67
+}
68
+
69
+static void tz_mpc_autoinc_idx(TZMPC *s, unsigned access_size)
70
+{
71
+ /* Auto-increment BLK_IDX if necessary */
72
+ if (access_size == 4 && (s->ctrl & R_CTRL_AUTOINC_MASK)) {
73
+ s->blk_idx++;
74
+ s->blk_idx %= s->blk_max;
75
+ }
76
+}
77
+
78
static MemTxResult tz_mpc_reg_read(void *opaque, hwaddr addr,
79
uint64_t *pdata,
80
unsigned size, MemTxAttrs attrs)
81
{
82
+ TZMPC *s = TZ_MPC(opaque);
83
uint64_t r;
84
uint32_t offset = addr & ~0x3;
85
86
@@ -XXX,XX +XXX,XX @@ static MemTxResult tz_mpc_reg_read(void *opaque, hwaddr addr,
31
}
87
}
32
88
33
- return (*cte & TABLE_ENTRY_VALID_MASK) != 0;
89
switch (offset) {
34
+ return FIELD_EX64(*cte, CTE, VALID);
90
+ case A_CTRL:
91
+ r = s->ctrl;
92
+ break;
93
+ case A_BLK_MAX:
94
+ r = s->blk_max;
95
+ break;
96
+ case A_BLK_CFG:
97
+ /* We are never in "init in progress state", so this just indicates
98
+ * the block size. s->blocksize == (1 << BLK_CFG + 5), so
99
+ * BLK_CFG == ctz32(s->blocksize) - 5
100
+ */
101
+ r = ctz32(s->blocksize) - 5;
102
+ break;
103
+ case A_BLK_IDX:
104
+ r = s->blk_idx;
105
+ break;
106
+ case A_BLK_LUT:
107
+ r = s->blk_lut[s->blk_idx];
108
+ tz_mpc_autoinc_idx(s, size);
109
+ break;
110
+ case A_INT_STAT:
111
+ r = s->int_stat;
112
+ break;
113
+ case A_INT_EN:
114
+ r = s->int_en;
115
+ break;
116
+ case A_INT_INFO1:
117
+ r = s->int_info1;
118
+ break;
119
+ case A_INT_INFO2:
120
+ r = s->int_info2;
121
+ break;
122
case A_PIDR4:
123
case A_PIDR5:
124
case A_PIDR6:
125
@@ -XXX,XX +XXX,XX @@ static MemTxResult tz_mpc_reg_write(void *opaque, hwaddr addr,
126
uint64_t value,
127
unsigned size, MemTxAttrs attrs)
128
{
129
+ TZMPC *s = TZ_MPC(opaque);
130
uint32_t offset = addr & ~0x3;
131
132
trace_tz_mpc_reg_write(addr, value, size);
133
@@ -XXX,XX +XXX,XX @@ static MemTxResult tz_mpc_reg_write(void *opaque, hwaddr addr,
134
uint32_t oldval;
135
136
switch (offset) {
137
- /* As we add support for registers which need expansions
138
- * other than zeroes we'll fill in cases here.
139
- */
140
+ case A_CTRL:
141
+ oldval = s->ctrl;
142
+ break;
143
+ case A_BLK_IDX:
144
+ oldval = s->blk_idx;
145
+ break;
146
+ case A_BLK_LUT:
147
+ oldval = s->blk_lut[s->blk_idx];
148
+ break;
149
default:
150
oldval = 0;
151
break;
152
@@ -XXX,XX +XXX,XX @@ static MemTxResult tz_mpc_reg_write(void *opaque, hwaddr addr,
153
value = deposit32(oldval, (addr & 3) * 8, size * 8, value);
154
}
155
156
+ if ((s->ctrl & R_CTRL_LOCKDOWN_MASK) &&
157
+ (offset == A_CTRL || offset == A_BLK_LUT || offset == A_INT_EN)) {
158
+ /* Lockdown mode makes these three registers read-only, and
159
+ * the only way out of it is to reset the device.
160
+ */
161
+ qemu_log_mask(LOG_GUEST_ERROR, "TZ MPC register write to offset 0x%x "
162
+ "while MPC is in lockdown mode\n", offset);
163
+ return MEMTX_OK;
164
+ }
165
+
166
switch (offset) {
167
+ case A_CTRL:
168
+ /* We don't implement the 'data gating' feature so all other bits
169
+ * are reserved and we make them RAZ/WI.
170
+ */
171
+ s->ctrl = value & (R_CTRL_SEC_RESP_MASK |
172
+ R_CTRL_AUTOINC_MASK |
173
+ R_CTRL_LOCKDOWN_MASK);
174
+ break;
175
+ case A_BLK_IDX:
176
+ s->blk_idx = value % s->blk_max;
177
+ break;
178
+ case A_BLK_LUT:
179
+ s->blk_lut[s->blk_idx] = value;
180
+ tz_mpc_autoinc_idx(s, size);
181
+ break;
182
+ case A_INT_CLEAR:
183
+ if (value & R_INT_CLEAR_IRQ_MASK) {
184
+ s->int_stat = 0;
185
+ tz_mpc_irq_update(s);
186
+ }
187
+ break;
188
+ case A_INT_EN:
189
+ s->int_en = value & R_INT_EN_IRQ_MASK;
190
+ tz_mpc_irq_update(s);
191
+ break;
192
+ case A_INT_SET:
193
+ if (value & R_INT_SET_IRQ_MASK) {
194
+ s->int_stat = R_INT_STAT_IRQ_MASK;
195
+ tz_mpc_irq_update(s);
196
+ }
197
+ break;
198
case A_PIDR4:
199
case A_PIDR5:
200
case A_PIDR6:
201
@@ -XXX,XX +XXX,XX @@ static int tz_mpc_num_indexes(IOMMUMemoryRegion *iommu)
202
203
static void tz_mpc_reset(DeviceState *dev)
204
{
205
+ TZMPC *s = TZ_MPC(dev);
206
+
207
+ s->ctrl = 0x00000100;
208
+ s->blk_idx = 0;
209
+ s->int_stat = 0;
210
+ s->int_en = 1;
211
+ s->int_info1 = 0;
212
+ s->int_info2 = 0;
213
+
214
+ memset(s->blk_lut, 0, s->blk_max * sizeof(uint32_t));
35
}
215
}
36
216
37
static bool update_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
217
static void tz_mpc_init(Object *obj)
38
@@ -XXX,XX +XXX,XX @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
218
@@ -XXX,XX +XXX,XX @@ static void tz_mpc_realize(DeviceState *dev, Error **errp)
39
* Current implementation only supports rdbase == procnum
219
"tz-mpc-downstream");
40
* Hence rdbase physical address is ignored
220
address_space_init(&s->blocked_io_as, &s->blocked_io,
41
*/
221
"tz-mpc-blocked-io");
42
- rdbase = (cte & GITS_CTE_RDBASE_PROCNUM_MASK) >> 1U;
222
+
43
+ rdbase = FIELD_EX64(cte, CTE, RDBASE);
223
+ s->blk_lut = g_new(uint32_t, s->blk_max);
44
224
+}
45
if (rdbase >= s->gicv3->num_cpu) {
225
+
46
return result;
226
+static int tz_mpc_post_load(void *opaque, int version_id)
47
@@ -XXX,XX +XXX,XX @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, bool valid,
227
+{
48
228
+ TZMPC *s = TZ_MPC(opaque);
49
if (valid) {
229
+
50
/* add mapping entry to collection table */
230
+ /* Check the incoming data doesn't point blk_idx off the end of blk_lut. */
51
- cte = (valid & TABLE_ENTRY_VALID_MASK) | (rdbase << 1ULL);
231
+ if (s->blk_idx >= s->blk_max) {
52
+ cte = FIELD_DP64(cte, CTE, VALID, 1);
232
+ return -1;
53
+ cte = FIELD_DP64(cte, CTE, RDBASE, rdbase);
233
+ }
234
+ return 0;
235
}
236
237
static const VMStateDescription tz_mpc_vmstate = {
238
.name = "tz-mpc",
239
.version_id = 1,
240
.minimum_version_id = 1,
241
+ .post_load = tz_mpc_post_load,
242
.fields = (VMStateField[]) {
243
+ VMSTATE_UINT32(ctrl, TZMPC),
244
+ VMSTATE_UINT32(blk_idx, TZMPC),
245
+ VMSTATE_UINT32(int_stat, TZMPC),
246
+ VMSTATE_UINT32(int_en, TZMPC),
247
+ VMSTATE_UINT32(int_info1, TZMPC),
248
+ VMSTATE_UINT32(int_info2, TZMPC),
249
+ VMSTATE_VARRAY_UINT32(blk_lut, TZMPC, blk_max,
250
+ 0, vmstate_info_uint32, uint32_t),
251
VMSTATE_END_OF_LIST()
54
}
252
}
55
253
};
56
/*
57
--
254
--
58
2.25.1
255
2.17.1
59
256
60
257
diff view generated by jsdifflib
1
The ITS code has to check whether various parameters passed in
1
The MPC is guest-configurable for whether blocked accesses:
2
commands are in-bounds, where the limit is defined in terms of the
2
* should be RAZ/WI or cause a bus error
3
number of bits that are available for the parameter. (For example,
3
* should generate an interrupt or not
4
the GITS_TYPER.Devbits ID register field specifies the number of
5
DeviceID bits minus 1, and device IDs passed in the MAPTI and MAPD
6
command packets must fit in that many bits.)
7
4
8
Currently we have off-by-one bugs in many of these bounds checks.
5
Implement this behaviour in the blocked-access handlers.
9
The typical problem is that we define a max_foo as 1 << n. In
10
the Devbits example, we set
11
s->dt.max_ids = 1UL << (GITS_TYPER.Devbits + 1).
12
However later when we do the bounds check we write
13
if (devid > s->dt.max_ids) { /* command error */ }
14
which incorrectly permits a devid of 1 << n.
15
16
These bugs will not cause QEMU crashes because the ID values being
17
checked are only used for accesses into tables held in guest memory
18
which we access with address_space_*() functions, but they are
19
incorrect behaviour of our emulation.
20
21
Fix them by standardizing on this pattern:
22
* bounds limits are named num_foos and are the 2^n value
23
(equal to the number of valid foo values)
24
* bounds checks are either
25
if (fooid < num_foos) { good }
26
or
27
if (fooid >= num_foos) { bad }
28
29
In this commit we fix the handling of the number of IDs
30
in the device table and the collection table, and the number
31
of commands that will fit in the command queue.
32
6
33
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
34
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
8
Reviewed-by: Eric Auger <eric.auger@redhat.com>
9
Message-id: 20180620132032.28865-4-peter.maydell@linaro.org
35
---
10
---
36
include/hw/intc/arm_gicv3_its_common.h | 6 +++---
11
hw/misc/tz-mpc.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++--
37
hw/intc/arm_gicv3_its.c | 26 +++++++++++++-------------
12
1 file changed, 48 insertions(+), 2 deletions(-)
38
2 files changed, 16 insertions(+), 16 deletions(-)
39
13
40
diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h
14
diff --git a/hw/misc/tz-mpc.c b/hw/misc/tz-mpc.c
41
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
42
--- a/include/hw/intc/arm_gicv3_its_common.h
16
--- a/hw/misc/tz-mpc.c
43
+++ b/include/hw/intc/arm_gicv3_its_common.h
17
+++ b/hw/misc/tz-mpc.c
44
@@ -XXX,XX +XXX,XX @@ typedef struct {
18
@@ -XXX,XX +XXX,XX @@ REG32(INT_EN, 0x28)
45
bool indirect;
19
FIELD(INT_EN, IRQ, 0, 1)
46
uint16_t entry_sz;
20
REG32(INT_INFO1, 0x2c)
47
uint32_t page_sz;
21
REG32(INT_INFO2, 0x30)
48
- uint32_t max_entries;
22
+ FIELD(INT_INFO2, HMASTER, 0, 16)
49
- uint32_t max_ids;
23
+ FIELD(INT_INFO2, HNONSEC, 16, 1)
50
+ uint32_t num_entries;
24
+ FIELD(INT_INFO2, CFG_NS, 17, 1)
51
+ uint32_t num_ids;
25
REG32(INT_SET, 0x34)
52
uint64_t base_addr;
26
FIELD(INT_SET, IRQ, 0, 1)
53
} TableDesc;
27
REG32(PIDR4, 0xfd0)
54
28
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps tz_mpc_reg_ops = {
55
typedef struct {
29
.impl.max_access_size = 4,
56
bool valid;
30
};
57
- uint32_t max_entries;
31
58
+ uint32_t num_entries;
32
+static inline bool tz_mpc_cfg_ns(TZMPC *s, hwaddr addr)
59
uint64_t base_addr;
33
+{
60
} CmdQDesc;
34
+ /* Return the cfg_ns bit from the LUT for the specified address */
61
35
+ hwaddr blknum = addr / s->blocksize;
62
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
36
+ hwaddr blkword = blknum / 32;
63
index XXXXXXX..XXXXXXX 100644
37
+ uint32_t blkbit = 1U << (blknum % 32);
64
--- a/hw/intc/arm_gicv3_its.c
38
+
65
+++ b/hw/intc/arm_gicv3_its.c
39
+ /* This would imply the address was larger than the size we
66
@@ -XXX,XX +XXX,XX @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
40
+ * defined this memory region to be, so it can't happen.
67
* In this implementation, in case of guest errors we ignore the
41
+ */
68
* command and move onto the next command in the queue.
42
+ assert(blkword < s->blk_max);
69
*/
43
+ return s->blk_lut[blkword] & blkbit;
70
- if (devid > s->dt.max_ids) {
44
+}
71
+ if (devid >= s->dt.num_ids) {
45
+
72
qemu_log_mask(LOG_GUEST_ERROR,
46
+static MemTxResult tz_mpc_handle_block(TZMPC *s, hwaddr addr, MemTxAttrs attrs)
73
- "%s: invalid command attributes: devid %d>%d",
47
+{
74
- __func__, devid, s->dt.max_ids);
48
+ /* Handle a blocked transaction: raise IRQ, capture info, etc */
75
+ "%s: invalid command attributes: devid %d>=%d",
49
+ if (!s->int_stat) {
76
+ __func__, devid, s->dt.num_ids);
50
+ /* First blocked transfer: capture information into INT_INFO1 and
77
51
+ * INT_INFO2. Subsequent transfers are still blocked but don't
78
} else if (!dte_valid || !ite_valid || !cte_valid) {
52
+ * capture information until the guest clears the interrupt.
79
qemu_log_mask(LOG_GUEST_ERROR,
53
+ */
80
@@ -XXX,XX +XXX,XX @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
54
+
81
max_eventid = 1UL << (FIELD_EX64(dte, DTE, SIZE) + 1);
55
+ s->int_info1 = addr;
82
max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1;
56
+ s->int_info2 = 0;
83
57
+ s->int_info2 = FIELD_DP32(s->int_info2, INT_INFO2, HMASTER,
84
- if ((devid > s->dt.max_ids) || (icid > s->ct.max_ids)
58
+ attrs.requester_id & 0xffff);
85
+ if ((devid >= s->dt.num_ids) || (icid >= s->ct.num_ids)
59
+ s->int_info2 = FIELD_DP32(s->int_info2, INT_INFO2, HNONSEC,
86
|| !dte_valid || (eventid > max_eventid) ||
60
+ ~attrs.secure);
87
(((pIntid < GICV3_LPI_INTID_START) || (pIntid > max_Intid)) &&
61
+ s->int_info2 = FIELD_DP32(s->int_info2, INT_INFO2, CFG_NS,
88
(pIntid != INTID_SPURIOUS))) {
62
+ tz_mpc_cfg_ns(s, addr));
89
@@ -XXX,XX +XXX,XX @@ static bool process_mapc(GICv3ITSState *s, uint32_t offset)
63
+ s->int_stat |= R_INT_STAT_IRQ_MASK;
90
64
+ tz_mpc_irq_update(s);
91
valid = (value & CMD_FIELD_VALID_MASK);
65
+ }
92
66
+
93
- if ((icid > s->ct.max_ids) || (rdbase >= s->gicv3->num_cpu)) {
67
+ /* Generate bus error if desired; otherwise RAZ/WI */
94
+ if ((icid >= s->ct.num_ids) || (rdbase >= s->gicv3->num_cpu)) {
68
+ return (s->ctrl & R_CTRL_SEC_RESP_MASK) ? MEMTX_ERROR : MEMTX_OK;
95
qemu_log_mask(LOG_GUEST_ERROR,
69
+}
96
"ITS MAPC: invalid collection table attributes "
70
+
97
"icid %d rdbase %" PRIu64 "\n", icid, rdbase);
71
/* Accesses only reach these read and write functions if the MPC is
98
@@ -XXX,XX +XXX,XX @@ static bool process_mapd(GICv3ITSState *s, uint64_t value, uint32_t offset)
72
* blocking them; non-blocked accesses go directly to the downstream
99
73
* memory region without passing through this code.
100
valid = (value & CMD_FIELD_VALID_MASK);
74
@@ -XXX,XX +XXX,XX @@ static MemTxResult tz_mpc_mem_blocked_read(void *opaque, hwaddr addr,
101
75
uint64_t *pdata,
102
- if ((devid > s->dt.max_ids) ||
76
unsigned size, MemTxAttrs attrs)
103
+ if ((devid >= s->dt.num_ids) ||
77
{
104
(size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) {
78
+ TZMPC *s = TZ_MPC(opaque);
105
qemu_log_mask(LOG_GUEST_ERROR,
79
+
106
"ITS MAPD: invalid device table attributes "
80
trace_tz_mpc_mem_blocked_read(addr, size, attrs.secure);
107
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
81
108
82
*pdata = 0;
109
wr_offset = FIELD_EX64(s->cwriter, GITS_CWRITER, OFFSET);
83
- return MEMTX_OK;
110
84
+ return tz_mpc_handle_block(s, addr, attrs);
111
- if (wr_offset > s->cq.max_entries) {
112
+ if (wr_offset >= s->cq.num_entries) {
113
qemu_log_mask(LOG_GUEST_ERROR,
114
"%s: invalid write offset "
115
"%d\n", __func__, wr_offset);
116
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
117
118
rd_offset = FIELD_EX64(s->creadr, GITS_CREADR, OFFSET);
119
120
- if (rd_offset > s->cq.max_entries) {
121
+ if (rd_offset >= s->cq.num_entries) {
122
qemu_log_mask(LOG_GUEST_ERROR,
123
"%s: invalid read offset "
124
"%d\n", __func__, rd_offset);
125
@@ -XXX,XX +XXX,XX @@ static void process_cmdq(GICv3ITSState *s)
126
}
127
if (result) {
128
rd_offset++;
129
- rd_offset %= s->cq.max_entries;
130
+ rd_offset %= s->cq.num_entries;
131
s->creadr = FIELD_DP64(s->creadr, GITS_CREADR, OFFSET, rd_offset);
132
} else {
133
/*
134
@@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s)
135
td->entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE) + 1;
136
td->base_addr = baser_base_addr(value, page_sz);
137
if (!td->indirect) {
138
- td->max_entries = (num_pages * page_sz) / td->entry_sz;
139
+ td->num_entries = (num_pages * page_sz) / td->entry_sz;
140
} else {
141
- td->max_entries = (((num_pages * page_sz) /
142
+ td->num_entries = (((num_pages * page_sz) /
143
L1TABLE_ENTRY_SIZE) *
144
(page_sz / td->entry_sz));
145
}
146
- td->max_ids = 1ULL << idbits;
147
+ td->num_ids = 1ULL << idbits;
148
}
149
}
85
}
150
86
151
@@ -XXX,XX +XXX,XX @@ static void extract_cmdq_params(GICv3ITSState *s)
87
static MemTxResult tz_mpc_mem_blocked_write(void *opaque, hwaddr addr,
152
s->cq.valid = FIELD_EX64(value, GITS_CBASER, VALID);
88
uint64_t value,
153
89
unsigned size, MemTxAttrs attrs)
154
if (s->cq.valid) {
90
{
155
- s->cq.max_entries = (num_pages * GITS_PAGE_SIZE_4K) /
91
+ TZMPC *s = TZ_MPC(opaque);
156
+ s->cq.num_entries = (num_pages * GITS_PAGE_SIZE_4K) /
92
+
157
GITS_CMDQ_ENTRY_SIZE;
93
trace_tz_mpc_mem_blocked_write(addr, value, size, attrs.secure);
158
s->cq.base_addr = FIELD_EX64(value, GITS_CBASER, PHYADDR);
94
159
s->cq.base_addr <<= R_GITS_CBASER_PHYADDR_SHIFT;
95
- return MEMTX_OK;
96
+ return tz_mpc_handle_block(s, addr, attrs);
97
}
98
99
static const MemoryRegionOps tz_mpc_mem_blocked_ops = {
160
--
100
--
161
2.25.1
101
2.17.1
162
102
163
103
diff view generated by jsdifflib
1
Currently the ITS code that reads and writes DTEs uses open-coded
1
The final part of the Memory Protection Controller we need to
2
shift-and-mask to assemble the various fields into the 64-bit DTE
2
implement is actually using the BLK_LUT data programmed by the
3
word. The names of the macros used for mask and shift values are
3
guest to determine whether to block the transaction or not.
4
also somewhat inconsistent, and don't follow our usual convention
4
5
that a MASK macro should specify the bits in their place in the word.
5
Since this means we now change transaction mappings when
6
Replace all these with use of the FIELD macro.
6
the guest writes to BLK_LUT, we must also call the IOMMU
7
notifiers at that point.
7
8
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
10
Reviewed-by: Eric Auger <eric.auger@redhat.com>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20180620132032.28865-5-peter.maydell@linaro.org
11
---
12
---
12
hw/intc/gicv3_internal.h | 7 ++++---
13
hw/misc/tz-mpc.c | 53 ++++++++++++++++++++++++++++++++++++++++++--
13
hw/intc/arm_gicv3_its.c | 20 +++++++++-----------
14
hw/misc/trace-events | 1 +
14
2 files changed, 13 insertions(+), 14 deletions(-)
15
2 files changed, 52 insertions(+), 2 deletions(-)
15
16
16
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
17
diff --git a/hw/misc/tz-mpc.c b/hw/misc/tz-mpc.c
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/intc/gicv3_internal.h
19
--- a/hw/misc/tz-mpc.c
19
+++ b/hw/intc/gicv3_internal.h
20
+++ b/hw/misc/tz-mpc.c
20
@@ -XXX,XX +XXX,XX @@ FIELD(ITE_H, VPEID, 16, 16)
21
@@ -XXX,XX +XXX,XX @@ static void tz_mpc_irq_update(TZMPC *s)
21
* Valid = 1 bit,ITTAddr = 44 bits,Size = 5 bits
22
qemu_set_irq(s->irq, s->int_stat && s->int_en);
22
*/
23
}
23
#define GITS_DTE_SIZE (0x8ULL)
24
24
-#define GITS_DTE_ITTADDR_SHIFT 6
25
+static void tz_mpc_iommu_notify(TZMPC *s, uint32_t lutidx,
25
-#define GITS_DTE_ITTADDR_MASK MAKE_64BIT_MASK(GITS_DTE_ITTADDR_SHIFT, \
26
+ uint32_t oldlut, uint32_t newlut)
26
- ITTADDR_LENGTH)
27
+{
28
+ /* Called when the LUT word at lutidx has changed from oldlut to newlut;
29
+ * must call the IOMMU notifiers for the changed blocks.
30
+ */
31
+ IOMMUTLBEntry entry = {
32
+ .addr_mask = s->blocksize - 1,
33
+ };
34
+ hwaddr addr = lutidx * s->blocksize * 32;
35
+ int i;
27
+
36
+
28
+FIELD(DTE, VALID, 0, 1)
37
+ for (i = 0; i < 32; i++, addr += s->blocksize) {
29
+FIELD(DTE, SIZE, 1, 5)
38
+ bool block_is_ns;
30
+FIELD(DTE, ITTADDR, 6, 44)
39
+
31
40
+ if (!((oldlut ^ newlut) & (1 << i))) {
32
/*
41
+ continue;
33
* 8 bytes Collection Table Entry size
42
+ }
34
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
43
+ /* This changes the mappings for both the S and the NS space,
44
+ * so we need to do four notifies: an UNMAP then a MAP for each.
45
+ */
46
+ block_is_ns = newlut & (1 << i);
47
+
48
+ trace_tz_mpc_iommu_notify(addr);
49
+ entry.iova = addr;
50
+ entry.translated_addr = addr;
51
+
52
+ entry.perm = IOMMU_NONE;
53
+ memory_region_notify_iommu(&s->upstream, IOMMU_IDX_S, entry);
54
+ memory_region_notify_iommu(&s->upstream, IOMMU_IDX_NS, entry);
55
+
56
+ entry.perm = IOMMU_RW;
57
+ if (block_is_ns) {
58
+ entry.target_as = &s->blocked_io_as;
59
+ } else {
60
+ entry.target_as = &s->downstream_as;
61
+ }
62
+ memory_region_notify_iommu(&s->upstream, IOMMU_IDX_S, entry);
63
+ if (block_is_ns) {
64
+ entry.target_as = &s->downstream_as;
65
+ } else {
66
+ entry.target_as = &s->blocked_io_as;
67
+ }
68
+ memory_region_notify_iommu(&s->upstream, IOMMU_IDX_NS, entry);
69
+ }
70
+}
71
+
72
static void tz_mpc_autoinc_idx(TZMPC *s, unsigned access_size)
73
{
74
/* Auto-increment BLK_IDX if necessary */
75
@@ -XXX,XX +XXX,XX @@ static MemTxResult tz_mpc_reg_write(void *opaque, hwaddr addr,
76
s->blk_idx = value % s->blk_max;
77
break;
78
case A_BLK_LUT:
79
+ tz_mpc_iommu_notify(s, s->blk_idx, s->blk_lut[s->blk_idx], value);
80
s->blk_lut[s->blk_idx] = value;
81
tz_mpc_autoinc_idx(s, size);
82
break;
83
@@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry tz_mpc_translate(IOMMUMemoryRegion *iommu,
84
/* Look at the per-block configuration for this address, and
85
* return a TLB entry directing the transaction at either
86
* downstream_as or blocked_io_as, as appropriate.
87
- * For the moment, always permit accesses.
88
+ * If the LUT cfg_ns bit is 1, only non-secure transactions
89
+ * may pass. If the bit is 0, only secure transactions may pass.
90
*/
91
- ok = true;
92
+ ok = tz_mpc_cfg_ns(s, addr) == (iommu_idx == IOMMU_IDX_NS);
93
94
trace_tz_mpc_translate(addr, flags,
95
iommu_idx == IOMMU_IDX_S ? "S" : "NS",
96
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
35
index XXXXXXX..XXXXXXX 100644
97
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/intc/arm_gicv3_its.c
98
--- a/hw/misc/trace-events
37
+++ b/hw/intc/arm_gicv3_its.c
99
+++ b/hw/misc/trace-events
38
@@ -XXX,XX +XXX,XX @@ static bool update_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
100
@@ -XXX,XX +XXX,XX @@ tz_mpc_reg_write(uint32_t offset, uint64_t data, unsigned size) "TZ MPC regs wri
39
uint64_t itt_addr;
101
tz_mpc_mem_blocked_read(uint64_t addr, unsigned size, bool secure) "TZ MPC blocked read: offset 0x%" PRIx64 " size %u secure %d"
40
MemTxResult res = MEMTX_OK;
102
tz_mpc_mem_blocked_write(uint64_t addr, uint64_t data, unsigned size, bool secure) "TZ MPC blocked write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d"
41
103
tz_mpc_translate(uint64_t addr, int flags, const char *idx, const char *res) "TZ MPC translate: addr 0x%" PRIx64 " flags 0x%x iommu_idx %s: %s"
42
- itt_addr = (dte & GITS_DTE_ITTADDR_MASK) >> GITS_DTE_ITTADDR_SHIFT;
104
+tz_mpc_iommu_notify(uint64_t addr) "TZ MPC iommu: notifying UNMAP/MAP for 0x%" PRIx64
43
+ itt_addr = FIELD_EX64(dte, DTE, ITTADDR);
105
44
itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */
106
# hw/misc/tz-ppc.c
45
107
tz_ppc_reset(void) "TZ PPC: reset"
46
address_space_stq_le(as, itt_addr + (eventid * (sizeof(uint64_t) +
47
@@ -XXX,XX +XXX,XX @@ static bool get_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
48
bool status = false;
49
IteEntry ite = {};
50
51
- itt_addr = (dte & GITS_DTE_ITTADDR_MASK) >> GITS_DTE_ITTADDR_SHIFT;
52
+ itt_addr = FIELD_EX64(dte, DTE, ITTADDR);
53
itt_addr <<= ITTADDR_SHIFT; /* 256 byte aligned */
54
55
ite.itel = address_space_ldq_le(as, itt_addr +
56
@@ -XXX,XX +XXX,XX @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
57
if (res != MEMTX_OK) {
58
return result;
59
}
60
- dte_valid = dte & TABLE_ENTRY_VALID_MASK;
61
+ dte_valid = FIELD_EX64(dte, DTE, VALID);
62
63
if (dte_valid) {
64
- max_eventid = (1UL << (((dte >> 1U) & SIZE_MASK) + 1));
65
+ max_eventid = 1UL << (FIELD_EX64(dte, DTE, SIZE) + 1);
66
67
ite_valid = get_ite(s, eventid, dte, &icid, &pIntid, &res);
68
69
@@ -XXX,XX +XXX,XX @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
70
if (res != MEMTX_OK) {
71
return result;
72
}
73
- dte_valid = dte & TABLE_ENTRY_VALID_MASK;
74
-
75
- max_eventid = (1UL << (((dte >> 1U) & SIZE_MASK) + 1));
76
-
77
+ dte_valid = FIELD_EX64(dte, DTE, VALID);
78
+ max_eventid = 1UL << (FIELD_EX64(dte, DTE, SIZE) + 1);
79
max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1;
80
81
if ((devid > s->dt.max_ids) || (icid > s->ct.max_ids)
82
@@ -XXX,XX +XXX,XX @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, bool valid,
83
if (s->dt.valid) {
84
if (valid) {
85
/* add mapping entry to device table */
86
- dte = (valid & TABLE_ENTRY_VALID_MASK) |
87
- ((size & SIZE_MASK) << 1U) |
88
- (itt_addr << GITS_DTE_ITTADDR_SHIFT);
89
+ dte = FIELD_DP64(dte, DTE, VALID, 1);
90
+ dte = FIELD_DP64(dte, DTE, SIZE, size);
91
+ dte = FIELD_DP64(dte, DTE, ITTADDR, itt_addr);
92
}
93
} else {
94
return true;
95
--
108
--
96
2.25.1
109
2.17.1
97
110
98
111
diff view generated by jsdifflib
1
The GITS_TYPE_PHYSICAL define is the value we set the
1
Implement the SECMPCINTSTATUS register. This is the only register
2
GITS_TYPER.Physical field to -- this is 1 to indicate that we support
2
in the security controller that deals with Memory Protection
3
physical LPIs. (Support for virtual LPIs is the GITS_TYPER.Virtual
3
Controllers, and it simply provides a read-only view of the
4
field.) We also use this define as the *value* that we write into an
4
interrupt lines from the various MPCs in the system.
5
interrupt translation table entry's INTTYPE field, which should be 1
6
for a physical interrupt and 0 for a virtual interrupt. Finally, we
7
use it as a *mask* when we read the interrupt translation table entry
8
INTTYPE field.
9
10
Untangle this confusion: define an ITE_INTTYPE_VIRTUAL and
11
ITE_INTTYPE_PHYSICAL to be the valid values of the ITE INTTYPE
12
field, and replace the ad-hoc collection of ITE_ENTRY_* defines with
13
use of the FIELD() macro to define the fields of an ITE and the
14
FIELD_EX64() and FIELD_DP64() macros to read and write them.
15
We use ITE in the new setup, rather than ITE_ENTRY, because
16
ITE stands for "Interrupt translation entry" and so the extra
17
"entry" would be redundant.
18
19
We take the opportunity to correct the name of the field that holds
20
the GICv4 'doorbell' interrupt ID (this is always the value 1023 in a
21
GICv3, which is why we were calling it the 'spurious' field).
22
23
The GITS_TYPE_PHYSICAL define is then used in only one place, where
24
we set the initial GITS_TYPER value. Since GITS_TYPER.Physical is
25
essentially a boolean, hiding the '1' value behind a macro is more
26
confusing than helpful, so expand out the macro there and remove the
27
define entirely.
28
5
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
7
Message-id: 20180620132032.28865-6-peter.maydell@linaro.org
31
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
32
---
8
---
33
hw/intc/gicv3_internal.h | 26 ++++++++++++++------------
9
include/hw/misc/iotkit-secctl.h | 8 +++++++
34
hw/intc/arm_gicv3_its.c | 30 +++++++++++++-----------------
10
hw/misc/iotkit-secctl.c | 38 +++++++++++++++++++++++++++++++--
35
2 files changed, 27 insertions(+), 29 deletions(-)
11
2 files changed, 44 insertions(+), 2 deletions(-)
36
12
37
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
13
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
38
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/intc/gicv3_internal.h
15
--- a/include/hw/misc/iotkit-secctl.h
40
+++ b/hw/intc/gicv3_internal.h
16
+++ b/include/hw/misc/iotkit-secctl.h
41
@@ -XXX,XX +XXX,XX @@ FIELD(MAPC, RDBASE, 16, 32)
17
@@ -XXX,XX +XXX,XX @@
42
#define L2_TABLE_VALID_MASK CMD_FIELD_VALID_MASK
18
* + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_enable
43
#define TABLE_ENTRY_VALID_MASK (1ULL << 0)
19
* + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_clear
44
20
* + named GPIO inputs ahb_ppcexp{0,1,2,3}_irq_status
45
-/**
21
+ * Controlling the MPC in the IoTKit:
46
- * Default features advertised by this version of ITS
22
+ * + named GPIO input mpc_status
47
- */
23
+ * Controlling each of the 16 expansion MPCs which a system using the IoTKit
48
-/* Physical LPIs supported */
24
+ * might provide:
49
-#define GITS_TYPE_PHYSICAL (1U << 0)
25
+ * + named GPIO inputs mpcexp_status[0..15]
50
-
51
/*
52
* 12 bytes Interrupt translation Table Entry size
53
* as per Table 5.3 in GICv3 spec
54
* ITE Lower 8 Bytes
55
* Bits: | 49 ... 26 | 25 ... 2 | 1 | 0 |
56
- * Values: | 1023 | IntNum | IntType | Valid |
57
+ * Values: | Doorbell | IntNum | IntType | Valid |
58
* ITE Higher 4 Bytes
59
* Bits: | 31 ... 16 | 15 ...0 |
60
* Values: | vPEID | ICID |
61
+ * (When Doorbell is unused, as it always is in GICv3, it is 1023)
62
*/
26
*/
63
#define ITS_ITT_ENTRY_SIZE 0xC
27
64
-#define ITE_ENTRY_INTTYPE_SHIFT 1
28
#ifndef IOTKIT_SECCTL_H
65
-#define ITE_ENTRY_INTID_SHIFT 2
29
@@ -XXX,XX +XXX,XX @@
66
-#define ITE_ENTRY_INTID_MASK MAKE_64BIT_MASK(2, 24)
30
#define IOTS_NUM_APB_PPC 2
67
-#define ITE_ENTRY_INTSP_SHIFT 26
31
#define IOTS_NUM_APB_EXP_PPC 4
68
-#define ITE_ENTRY_ICID_MASK MAKE_64BIT_MASK(0, 16)
32
#define IOTS_NUM_AHB_EXP_PPC 4
33
+#define IOTS_NUM_EXP_MPC 16
34
+#define IOTS_NUM_MPC 1
35
36
typedef struct IoTKitSecCtl IoTKitSecCtl;
37
38
@@ -XXX,XX +XXX,XX @@ struct IoTKitSecCtl {
39
uint32_t secrespcfg;
40
uint32_t nsccfg;
41
uint32_t brginten;
42
+ uint32_t mpcintstatus;
43
44
IoTKitSecCtlPPC apb[IOTS_NUM_APB_PPC];
45
IoTKitSecCtlPPC apbexp[IOTS_NUM_APB_EXP_PPC];
46
diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/misc/iotkit-secctl.c
49
+++ b/hw/misc/iotkit-secctl.c
50
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
51
case A_NSCCFG:
52
r = s->nsccfg;
53
break;
54
+ case A_SECMPCINTSTATUS:
55
+ r = s->mpcintstatus;
56
+ break;
57
case A_SECPPCINTSTAT:
58
r = s->secppcintstat;
59
break;
60
@@ -XXX,XX +XXX,XX @@ static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
61
case A_APBSPPPCEXP3:
62
r = s->apbexp[offset_to_ppc_idx(offset)].sp;
63
break;
64
- case A_SECMPCINTSTATUS:
65
case A_SECMSCINTSTAT:
66
case A_SECMSCINTEN:
67
case A_NSMSCEXP:
68
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_reset(DeviceState *dev)
69
foreach_ppc(s, iotkit_secctl_reset_ppc);
70
}
71
72
+static void iotkit_secctl_mpc_status(void *opaque, int n, int level)
73
+{
74
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
69
+
75
+
70
+FIELD(ITE_L, VALID, 0, 1)
76
+ s->mpcintstatus = deposit32(s->mpcintstatus, 0, 1, !!level);
71
+FIELD(ITE_L, INTTYPE, 1, 1)
77
+}
72
+FIELD(ITE_L, INTID, 2, 24)
73
+FIELD(ITE_L, DOORBELL, 26, 24)
74
+
78
+
75
+FIELD(ITE_H, ICID, 0, 16)
79
+static void iotkit_secctl_mpcexp_status(void *opaque, int n, int level)
76
+FIELD(ITE_H, VPEID, 16, 16)
80
+{
81
+ IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
77
+
82
+
78
+/* Possible values for ITE_L INTTYPE */
83
+ s->mpcintstatus = deposit32(s->mpcintstatus, n + 16, 1, !!level);
79
+#define ITE_INTTYPE_VIRTUAL 0
84
+}
80
+#define ITE_INTTYPE_PHYSICAL 1
85
+
81
86
static void iotkit_secctl_ppc_irqstatus(void *opaque, int n, int level)
82
/* 16 bits EventId */
87
{
83
#define ITS_IDBITS GICD_TYPER_IDBITS
88
IoTKitSecCtlPPC *ppc = opaque;
84
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
89
@@ -XXX,XX +XXX,XX @@ static void iotkit_secctl_init(Object *obj)
85
index XXXXXXX..XXXXXXX 100644
90
qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
86
--- a/hw/intc/arm_gicv3_its.c
91
qdev_init_gpio_out_named(dev, &s->nsc_cfg_irq, "nsc_cfg", 1);
87
+++ b/hw/intc/arm_gicv3_its.c
92
88
@@ -XXX,XX +XXX,XX @@ static bool get_ite(GICv3ITSState *s, uint32_t eventid, uint64_t dte,
93
+ qdev_init_gpio_in_named(dev, iotkit_secctl_mpc_status, "mpc_status", 1);
89
MEMTXATTRS_UNSPECIFIED, res);
94
+ qdev_init_gpio_in_named(dev, iotkit_secctl_mpcexp_status,
90
95
+ "mpcexp_status", IOTS_NUM_EXP_MPC);
91
if (*res == MEMTX_OK) {
96
+
92
- if (ite.itel & TABLE_ENTRY_VALID_MASK) {
97
memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
93
- if ((ite.itel >> ITE_ENTRY_INTTYPE_SHIFT) &
98
s, "iotkit-secctl-s-regs", 0x1000);
94
- GITS_TYPE_PHYSICAL) {
99
memory_region_init_io(&s->ns_regs, obj, &iotkit_secctl_ns_ops,
95
- *pIntid = (ite.itel & ITE_ENTRY_INTID_MASK) >>
100
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_secctl_ppc_vmstate = {
96
- ITE_ENTRY_INTID_SHIFT;
97
- *icid = ite.iteh & ITE_ENTRY_ICID_MASK;
98
+ if (FIELD_EX64(ite.itel, ITE_L, VALID)) {
99
+ int inttype = FIELD_EX64(ite.itel, ITE_L, INTTYPE);
100
+ if (inttype == ITE_INTTYPE_PHYSICAL) {
101
+ *pIntid = FIELD_EX64(ite.itel, ITE_L, INTID);
102
+ *icid = FIELD_EX32(ite.iteh, ITE_H, ICID);
103
status = true;
104
}
105
}
106
@@ -XXX,XX +XXX,XX @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
107
MemTxResult res = MEMTX_OK;
108
uint16_t icid = 0;
109
uint64_t dte = 0;
110
- IteEntry ite;
111
- uint32_t int_spurious = INTID_SPURIOUS;
112
bool result = false;
113
114
devid = ((value & DEVID_MASK) >> DEVID_SHIFT);
115
@@ -XXX,XX +XXX,XX @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
116
*/
117
} else {
118
/* add ite entry to interrupt translation table */
119
- ite.itel = (dte_valid & TABLE_ENTRY_VALID_MASK) |
120
- (GITS_TYPE_PHYSICAL << ITE_ENTRY_INTTYPE_SHIFT);
121
-
122
+ IteEntry ite = {};
123
+ ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, dte_valid);
124
+ ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL);
125
if (ignore_pInt) {
126
- ite.itel |= (eventid << ITE_ENTRY_INTID_SHIFT);
127
+ ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, eventid);
128
} else {
129
- ite.itel |= (pIntid << ITE_ENTRY_INTID_SHIFT);
130
+ ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, pIntid);
131
}
132
- ite.itel |= (int_spurious << ITE_ENTRY_INTSP_SHIFT);
133
- ite.iteh = icid;
134
+ ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS);
135
+ ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, icid);
136
137
result = update_ite(s, eventid, dte, ite);
138
}
101
}
139
@@ -XXX,XX +XXX,XX @@ static void gicv3_arm_its_realize(DeviceState *dev, Error **errp)
102
};
140
"gicv3-its-sysmem");
103
141
104
+static const VMStateDescription iotkit_secctl_mpcintstatus_vmstate = {
142
/* set the ITS default features supported */
105
+ .name = "iotkit-secctl-mpcintstatus",
143
- s->typer = FIELD_DP64(s->typer, GITS_TYPER, PHYSICAL,
106
+ .version_id = 1,
144
- GITS_TYPE_PHYSICAL);
107
+ .minimum_version_id = 1,
145
+ s->typer = FIELD_DP64(s->typer, GITS_TYPER, PHYSICAL, 1);
108
+ .fields = (VMStateField[]) {
146
s->typer = FIELD_DP64(s->typer, GITS_TYPER, ITT_ENTRY_SIZE,
109
+ VMSTATE_UINT32(mpcintstatus, IoTKitSecCtl),
147
ITS_ITT_ENTRY_SIZE - 1);
110
+ VMSTATE_END_OF_LIST()
148
s->typer = FIELD_DP64(s->typer, GITS_TYPER, IDBITS, ITS_IDBITS);
111
+ }
112
+};
113
+
114
static const VMStateDescription iotkit_secctl_vmstate = {
115
.name = "iotkit-secctl",
116
.version_id = 1,
117
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription iotkit_secctl_vmstate = {
118
VMSTATE_STRUCT_ARRAY(ahbexp, IoTKitSecCtl, IOTS_NUM_AHB_EXP_PPC, 1,
119
iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
120
VMSTATE_END_OF_LIST()
121
- }
122
+ },
123
+ .subsections = (const VMStateDescription*[]) {
124
+ &iotkit_secctl_mpcintstatus_vmstate,
125
+ NULL
126
+ },
127
};
128
129
static void iotkit_secctl_class_init(ObjectClass *klass, void *data)
149
--
130
--
150
2.25.1
131
2.17.1
151
132
152
133
diff view generated by jsdifflib
1
The extract_table_params() decodes the fields in the GITS_BASER<n>
1
Wire up the one MPC that is part of the IoTKit itself. For the
2
registers into TableDesc structs. Since the fields are the same for
2
moment we don't wire up its interrupt line.
3
all the GITS_BASER<n> registers, there is currently a lot of code
4
duplication within the switch (type) statement. Refactor so that the
5
cases include only what is genuinely different for each type:
6
the calculation of the number of bits in the ID value that indexes
7
into the table.
8
3
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20180620132032.28865-7-peter.maydell@linaro.org
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
---
7
---
14
hw/intc/arm_gicv3_its.c | 97 +++++++++++++++++------------------------
8
include/hw/arm/iotkit.h | 2 ++
15
1 file changed, 40 insertions(+), 57 deletions(-)
9
hw/arm/iotkit.c | 38 +++++++++++++++++++++++++++-----------
10
2 files changed, 29 insertions(+), 11 deletions(-)
16
11
17
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
12
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
18
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/intc/arm_gicv3_its.c
14
--- a/include/hw/arm/iotkit.h
20
+++ b/hw/intc/arm_gicv3_its.c
15
+++ b/include/hw/arm/iotkit.h
21
@@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s)
16
@@ -XXX,XX +XXX,XX @@
22
uint64_t value;
17
#include "hw/arm/armv7m.h"
23
18
#include "hw/misc/iotkit-secctl.h"
24
for (int i = 0; i < 8; i++) {
19
#include "hw/misc/tz-ppc.h"
25
+ TableDesc *td;
20
+#include "hw/misc/tz-mpc.h"
26
+ int idbits;
21
#include "hw/timer/cmsdk-apb-timer.h"
22
#include "hw/misc/unimp.h"
23
#include "hw/or-irq.h"
24
@@ -XXX,XX +XXX,XX @@ typedef struct IoTKit {
25
IoTKitSecCtl secctl;
26
TZPPC apb_ppc0;
27
TZPPC apb_ppc1;
28
+ TZMPC mpc;
29
CMSDKAPBTIMER timer0;
30
CMSDKAPBTIMER timer1;
31
qemu_or_irq ppc_irq_orgate;
32
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/arm/iotkit.c
35
+++ b/hw/arm/iotkit.c
36
@@ -XXX,XX +XXX,XX @@ static void iotkit_init(Object *obj)
37
TYPE_TZ_PPC);
38
init_sysbus_child(obj, "apb-ppc1", &s->apb_ppc1, sizeof(s->apb_ppc1),
39
TYPE_TZ_PPC);
40
+ init_sysbus_child(obj, "mpc", &s->mpc, sizeof(s->mpc), TYPE_TZ_MPC);
41
init_sysbus_child(obj, "timer0", &s->timer0, sizeof(s->timer0),
42
TYPE_CMSDK_APB_TIMER);
43
init_sysbus_child(obj, "timer1", &s->timer1, sizeof(s->timer1),
44
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
45
*/
46
make_alias(s, &s->alias3, "alias 3", 0x50000000, 0x10000000, 0x40000000);
47
48
- /* This RAM should be behind a Memory Protection Controller, but we
49
- * don't implement that yet.
50
- */
51
- memory_region_init_ram(&s->sram0, NULL, "iotkit.sram0", 0x00008000, &err);
52
- if (err) {
53
- error_propagate(errp, err);
54
- return;
55
- }
56
- memory_region_add_subregion(&s->container, 0x20000000, &s->sram0);
57
58
/* Security controller */
59
object_property_set_bool(OBJECT(&s->secctl), true, "realized", &err);
60
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
61
qdev_connect_gpio_out_named(dev_secctl, "sec_resp_cfg", 0,
62
qdev_get_gpio_in(dev_splitter, 0));
63
64
+ /* This RAM lives behind the Memory Protection Controller */
65
+ memory_region_init_ram(&s->sram0, NULL, "iotkit.sram0", 0x00008000, &err);
66
+ if (err) {
67
+ error_propagate(errp, err);
68
+ return;
69
+ }
70
+ object_property_set_link(OBJECT(&s->mpc), OBJECT(&s->sram0),
71
+ "downstream", &err);
72
+ if (err) {
73
+ error_propagate(errp, err);
74
+ return;
75
+ }
76
+ object_property_set_bool(OBJECT(&s->mpc), true, "realized", &err);
77
+ if (err) {
78
+ error_propagate(errp, err);
79
+ return;
80
+ }
81
+ /* Map the upstream end of the MPC into the right place... */
82
+ memory_region_add_subregion(&s->container, 0x20000000,
83
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mpc),
84
+ 1));
85
+ /* ...and its register interface */
86
+ memory_region_add_subregion(&s->container, 0x50083000,
87
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mpc),
88
+ 0));
27
+
89
+
28
value = s->baser[i];
90
/* Devices behind APB PPC0:
29
91
* 0x40000000: timer0
30
if (!value) {
92
* 0x40001000: timer1
31
@@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s)
93
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
32
type = FIELD_EX64(value, GITS_BASER, TYPE);
94
create_unimplemented_device("NS watchdog", 0x40081000, 0x1000);
33
95
create_unimplemented_device("S watchdog", 0x50081000, 0x1000);
34
switch (type) {
96
97
- create_unimplemented_device("SRAM0 MPC", 0x50083000, 0x1000);
35
-
98
-
36
case GITS_BASER_TYPE_DEVICE:
99
for (i = 0; i < ARRAY_SIZE(s->ppc_irq_splitter); i++) {
37
- memset(&s->dt, 0 , sizeof(s->dt));
100
Object *splitter = OBJECT(&s->ppc_irq_splitter[i]);
38
- s->dt.valid = FIELD_EX64(value, GITS_BASER, VALID);
39
-
40
- if (!s->dt.valid) {
41
- break;
42
- }
43
-
44
- s->dt.page_sz = page_sz;
45
- s->dt.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
46
- s->dt.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
47
-
48
- if (!s->dt.indirect) {
49
- s->dt.max_entries = (num_pages * page_sz) / s->dt.entry_sz;
50
- } else {
51
- s->dt.max_entries = (((num_pages * page_sz) /
52
- L1TABLE_ENTRY_SIZE) *
53
- (page_sz / s->dt.entry_sz));
54
- }
55
-
56
- s->dt.max_ids = (1UL << (FIELD_EX64(s->typer, GITS_TYPER,
57
- DEVBITS) + 1));
58
-
59
- s->dt.base_addr = baser_base_addr(value, page_sz);
60
-
61
+ td = &s->dt;
62
+ idbits = FIELD_EX64(s->typer, GITS_TYPER, DEVBITS) + 1;
63
break;
64
-
65
case GITS_BASER_TYPE_COLLECTION:
66
- memset(&s->ct, 0 , sizeof(s->ct));
67
- s->ct.valid = FIELD_EX64(value, GITS_BASER, VALID);
68
-
69
- /*
70
- * GITS_TYPER.HCC is 0 for this implementation
71
- * hence writes are discarded if ct.valid is 0
72
- */
73
- if (!s->ct.valid) {
74
- break;
75
- }
76
-
77
- s->ct.page_sz = page_sz;
78
- s->ct.indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
79
- s->ct.entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
80
-
81
- if (!s->ct.indirect) {
82
- s->ct.max_entries = (num_pages * page_sz) / s->ct.entry_sz;
83
- } else {
84
- s->ct.max_entries = (((num_pages * page_sz) /
85
- L1TABLE_ENTRY_SIZE) *
86
- (page_sz / s->ct.entry_sz));
87
- }
88
-
89
+ td = &s->ct;
90
if (FIELD_EX64(s->typer, GITS_TYPER, CIL)) {
91
- s->ct.max_ids = (1UL << (FIELD_EX64(s->typer,
92
- GITS_TYPER, CIDBITS) + 1));
93
+ idbits = FIELD_EX64(s->typer, GITS_TYPER, CIDBITS) + 1;
94
} else {
95
/* 16-bit CollectionId supported when CIL == 0 */
96
- s->ct.max_ids = (1UL << 16);
97
+ idbits = 16;
98
}
99
-
100
- s->ct.base_addr = baser_base_addr(value, page_sz);
101
-
102
break;
103
-
104
default:
105
- break;
106
+ /*
107
+ * GITS_BASER<n>.TYPE is read-only, so GITS_BASER_RO_MASK
108
+ * ensures we will only see type values corresponding to
109
+ * the values set up in gicv3_its_reset().
110
+ */
111
+ g_assert_not_reached();
112
}
113
+
114
+ memset(td, 0, sizeof(*td));
115
+ td->valid = FIELD_EX64(value, GITS_BASER, VALID);
116
+ /*
117
+ * If GITS_BASER<n>.Valid is 0 for any <n> then we will not process
118
+ * interrupts. (GITS_TYPER.HCC is 0 for this implementation, so we
119
+ * do not have a special case where the GITS_BASER<n>.Valid bit is 0
120
+ * for the register corresponding to the Collection table but we
121
+ * still have to process interrupts using non-memory-backed
122
+ * Collection table entries.)
123
+ */
124
+ if (!td->valid) {
125
+ continue;
126
+ }
127
+ td->page_sz = page_sz;
128
+ td->indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
129
+ td->entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
130
+ td->base_addr = baser_base_addr(value, page_sz);
131
+ if (!td->indirect) {
132
+ td->max_entries = (num_pages * page_sz) / td->entry_sz;
133
+ } else {
134
+ td->max_entries = (((num_pages * page_sz) /
135
+ L1TABLE_ENTRY_SIZE) *
136
+ (page_sz / td->entry_sz));
137
+ }
138
+ td->max_ids = 1ULL << idbits;
139
}
140
}
141
101
142
--
102
--
143
2.25.1
103
2.17.1
144
104
145
105
diff view generated by jsdifflib
1
The TableDesc struct defines properties of the in-guest-memory tables
1
The interrupt outputs from the MPC in the IoTKit and the expansion
2
which the guest tells us about by writing to the GITS_BASER<n>
2
MPCs in the board must be wired up to the security controller, and
3
registers. This struct currently has a union 'maxids', but all the
3
also all ORed together to produce a single line to the NVIC.
4
fields of the union have the same type (uint32_t) and do the same
5
thing (record one-greater-than the maximum ID value that can be used
6
as an index into the table).
7
8
We're about to add another table type (the GICv4 vPE table); rather
9
than adding another specifically-named union field for that table
10
type with the same type as the other union fields, remove the union
11
entirely and just have a 'uint32_t max_ids' struct field.
12
4
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20180620132032.28865-8-peter.maydell@linaro.org
16
---
8
---
17
include/hw/intc/arm_gicv3_its_common.h | 5 +----
9
include/hw/arm/iotkit.h | 6 ++++
18
hw/intc/arm_gicv3_its.c | 20 ++++++++++----------
10
hw/arm/iotkit.c | 74 +++++++++++++++++++++++++++++++++++++++++
19
2 files changed, 11 insertions(+), 14 deletions(-)
11
2 files changed, 80 insertions(+)
20
12
21
diff --git a/include/hw/intc/arm_gicv3_its_common.h b/include/hw/intc/arm_gicv3_its_common.h
13
diff --git a/include/hw/arm/iotkit.h b/include/hw/arm/iotkit.h
22
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/intc/arm_gicv3_its_common.h
15
--- a/include/hw/arm/iotkit.h
24
+++ b/include/hw/intc/arm_gicv3_its_common.h
16
+++ b/include/hw/arm/iotkit.h
25
@@ -XXX,XX +XXX,XX @@ typedef struct {
17
@@ -XXX,XX +XXX,XX @@
26
uint16_t entry_sz;
18
* + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_enable
27
uint32_t page_sz;
19
* + named GPIO outputs ahb_ppcexp{0,1,2,3}_irq_clear
28
uint32_t max_entries;
20
* + named GPIO inputs ahb_ppcexp{0,1,2,3}_irq_status
29
- union {
21
+ * Controlling each of the 16 expansion MPCs which a system using the IoTKit
30
- uint32_t max_devids;
22
+ * might provide:
31
- uint32_t max_collids;
23
+ * + named GPIO inputs mpcexp_status[0..15]
32
- } maxids;
24
*/
33
+ uint32_t max_ids;
25
34
uint64_t base_addr;
26
#ifndef IOTKIT_H
35
} TableDesc;
27
@@ -XXX,XX +XXX,XX @@ typedef struct IoTKit {
36
28
qemu_or_irq ppc_irq_orgate;
37
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
29
SplitIRQ sec_resp_splitter;
30
SplitIRQ ppc_irq_splitter[NUM_PPCS];
31
+ SplitIRQ mpc_irq_splitter[IOTS_NUM_EXP_MPC + IOTS_NUM_MPC];
32
+ qemu_or_irq mpc_irq_orgate;
33
34
UnimplementedDeviceState dualtimer;
35
UnimplementedDeviceState s32ktimer;
36
@@ -XXX,XX +XXX,XX @@ typedef struct IoTKit {
37
qemu_irq nsc_cfg_in;
38
39
qemu_irq irq_status_in[NUM_EXTERNAL_PPCS];
40
+ qemu_irq mpcexp_status_in[IOTS_NUM_EXP_MPC];
41
42
uint32_t nsccfg;
43
44
diff --git a/hw/arm/iotkit.c b/hw/arm/iotkit.c
38
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/intc/arm_gicv3_its.c
46
--- a/hw/arm/iotkit.c
40
+++ b/hw/intc/arm_gicv3_its.c
47
+++ b/hw/arm/iotkit.c
41
@@ -XXX,XX +XXX,XX @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
48
@@ -XXX,XX +XXX,XX @@ static void iotkit_init(Object *obj)
42
* In this implementation, in case of guest errors we ignore the
49
init_sysbus_child(obj, "apb-ppc1", &s->apb_ppc1, sizeof(s->apb_ppc1),
43
* command and move onto the next command in the queue.
50
TYPE_TZ_PPC);
44
*/
51
init_sysbus_child(obj, "mpc", &s->mpc, sizeof(s->mpc), TYPE_TZ_MPC);
45
- if (devid > s->dt.maxids.max_devids) {
52
+ object_initialize(&s->mpc_irq_orgate, sizeof(s->mpc_irq_orgate),
46
+ if (devid > s->dt.max_ids) {
53
+ TYPE_OR_IRQ);
47
qemu_log_mask(LOG_GUEST_ERROR,
54
+ object_property_add_child(obj, "mpc-irq-orgate",
48
"%s: invalid command attributes: devid %d>%d",
55
+ OBJECT(&s->mpc_irq_orgate), &error_abort);
49
- __func__, devid, s->dt.maxids.max_devids);
56
+ for (i = 0; i < ARRAY_SIZE(s->mpc_irq_splitter); i++) {
50
+ __func__, devid, s->dt.max_ids);
57
+ char *name = g_strdup_printf("mpc-irq-splitter-%d", i);
51
58
+ SplitIRQ *splitter = &s->mpc_irq_splitter[i];
52
} else if (!dte_valid || !ite_valid || !cte_valid) {
59
+
53
qemu_log_mask(LOG_GUEST_ERROR,
60
+ object_initialize(splitter, sizeof(*splitter), TYPE_SPLIT_IRQ);
54
@@ -XXX,XX +XXX,XX @@ static bool process_mapti(GICv3ITSState *s, uint64_t value, uint32_t offset,
61
+ object_property_add_child(obj, name, OBJECT(splitter), &error_abort);
55
max_Intid = (1ULL << (GICD_TYPER_IDBITS + 1)) - 1;
62
+ g_free(name);
63
+ }
64
init_sysbus_child(obj, "timer0", &s->timer0, sizeof(s->timer0),
65
TYPE_CMSDK_APB_TIMER);
66
init_sysbus_child(obj, "timer1", &s->timer1, sizeof(s->timer1),
67
@@ -XXX,XX +XXX,XX @@ static void iotkit_exp_irq(void *opaque, int n, int level)
68
qemu_set_irq(s->exp_irqs[n], level);
69
}
70
71
+static void iotkit_mpcexp_status(void *opaque, int n, int level)
72
+{
73
+ IoTKit *s = IOTKIT(opaque);
74
+ qemu_set_irq(s->mpcexp_status_in[n], level);
75
+}
76
+
77
static void iotkit_realize(DeviceState *dev, Error **errp)
78
{
79
IoTKit *s = IOTKIT(dev);
80
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
81
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mpc),
82
0));
83
84
+ /* We must OR together lines from the MPC splitters to go to the NVIC */
85
+ object_property_set_int(OBJECT(&s->mpc_irq_orgate),
86
+ IOTS_NUM_EXP_MPC + IOTS_NUM_MPC, "num-lines", &err);
87
+ if (err) {
88
+ error_propagate(errp, err);
89
+ return;
90
+ }
91
+ object_property_set_bool(OBJECT(&s->mpc_irq_orgate), true,
92
+ "realized", &err);
93
+ if (err) {
94
+ error_propagate(errp, err);
95
+ return;
96
+ }
97
+ qdev_connect_gpio_out(DEVICE(&s->mpc_irq_orgate), 0,
98
+ qdev_get_gpio_in(DEVICE(&s->armv7m), 9));
99
+
100
/* Devices behind APB PPC0:
101
* 0x40000000: timer0
102
* 0x40001000: timer1
103
@@ -XXX,XX +XXX,XX @@ static void iotkit_realize(DeviceState *dev, Error **errp)
104
g_free(gpioname);
56
}
105
}
57
106
58
- if ((devid > s->dt.maxids.max_devids) || (icid > s->ct.maxids.max_collids)
107
+ /* Wire up the splitters for the MPC IRQs */
59
+ if ((devid > s->dt.max_ids) || (icid > s->ct.max_ids)
108
+ for (i = 0; i < IOTS_NUM_EXP_MPC + IOTS_NUM_MPC; i++) {
60
|| !dte_valid || (eventid > max_eventid) ||
109
+ SplitIRQ *splitter = &s->mpc_irq_splitter[i];
61
(!ignore_pInt && (((pIntid < GICV3_LPI_INTID_START) ||
110
+ DeviceState *dev_splitter = DEVICE(splitter);
62
(pIntid > max_Intid)) && (pIntid != INTID_SPURIOUS)))) {
111
+
63
@@ -XXX,XX +XXX,XX @@ static bool process_mapc(GICv3ITSState *s, uint32_t offset)
112
+ object_property_set_int(OBJECT(splitter), 2, "num-lines", &err);
64
113
+ if (err) {
65
valid = (value & CMD_FIELD_VALID_MASK);
114
+ error_propagate(errp, err);
66
115
+ return;
67
- if ((icid > s->ct.maxids.max_collids) || (rdbase >= s->gicv3->num_cpu)) {
116
+ }
68
+ if ((icid > s->ct.max_ids) || (rdbase >= s->gicv3->num_cpu)) {
117
+ object_property_set_bool(OBJECT(splitter), true, "realized", &err);
69
qemu_log_mask(LOG_GUEST_ERROR,
118
+ if (err) {
70
"ITS MAPC: invalid collection table attributes "
119
+ error_propagate(errp, err);
71
"icid %d rdbase %" PRIu64 "\n", icid, rdbase);
120
+ return;
72
@@ -XXX,XX +XXX,XX @@ static bool process_mapd(GICv3ITSState *s, uint64_t value, uint32_t offset)
121
+ }
73
122
+
74
valid = (value & CMD_FIELD_VALID_MASK);
123
+ if (i < IOTS_NUM_EXP_MPC) {
75
124
+ /* Splitter input is from GPIO input line */
76
- if ((devid > s->dt.maxids.max_devids) ||
125
+ s->mpcexp_status_in[i] = qdev_get_gpio_in(dev_splitter, 0);
77
+ if ((devid > s->dt.max_ids) ||
126
+ qdev_connect_gpio_out(dev_splitter, 0,
78
(size > FIELD_EX64(s->typer, GITS_TYPER, IDBITS))) {
127
+ qdev_get_gpio_in_named(dev_secctl,
79
qemu_log_mask(LOG_GUEST_ERROR,
128
+ "mpcexp_status", i));
80
"ITS MAPD: invalid device table attributes "
129
+ } else {
81
@@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s)
130
+ /* Splitter input is from our own MPC */
82
(page_sz / s->dt.entry_sz));
131
+ qdev_connect_gpio_out_named(DEVICE(&s->mpc), "irq", 0,
83
}
132
+ qdev_get_gpio_in(dev_splitter, 0));
84
133
+ qdev_connect_gpio_out(dev_splitter, 0,
85
- s->dt.maxids.max_devids = (1UL << (FIELD_EX64(s->typer, GITS_TYPER,
134
+ qdev_get_gpio_in_named(dev_secctl,
86
- DEVBITS) + 1));
135
+ "mpc_status", 0));
87
+ s->dt.max_ids = (1UL << (FIELD_EX64(s->typer, GITS_TYPER,
136
+ }
88
+ DEVBITS) + 1));
137
+
89
138
+ qdev_connect_gpio_out(dev_splitter, 1,
90
s->dt.base_addr = baser_base_addr(value, page_sz);
139
+ qdev_get_gpio_in(DEVICE(&s->mpc_irq_orgate), i));
91
140
+ }
92
@@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s)
141
+ /* Create GPIO inputs which will pass the line state for our
93
}
142
+ * mpcexp_irq inputs to the correct splitter devices.
94
143
+ */
95
if (FIELD_EX64(s->typer, GITS_TYPER, CIL)) {
144
+ qdev_init_gpio_in_named(dev, iotkit_mpcexp_status, "mpcexp_status",
96
- s->ct.maxids.max_collids = (1UL << (FIELD_EX64(s->typer,
145
+ IOTS_NUM_EXP_MPC);
97
- GITS_TYPER, CIDBITS) + 1));
146
+
98
+ s->ct.max_ids = (1UL << (FIELD_EX64(s->typer,
147
iotkit_forward_sec_resp_cfg(s);
99
+ GITS_TYPER, CIDBITS) + 1));
148
100
} else {
149
system_clock_scale = NANOSECONDS_PER_SECOND / s->mainclk_frq;
101
/* 16-bit CollectionId supported when CIL == 0 */
102
- s->ct.maxids.max_collids = (1UL << 16);
103
+ s->ct.max_ids = (1UL << 16);
104
}
105
106
s->ct.base_addr = baser_base_addr(value, page_sz);
107
--
150
--
108
2.25.1
151
2.17.1
109
152
110
153
diff view generated by jsdifflib
1
We set the TableDesc entry_sz field from the appropriate
1
Instantiate and wire up the Memory Protection Controllers
2
GITS_BASER.ENTRYSIZE field. That ID register field specifies the
2
in the MPS2 board itself.
3
number of bytes per table entry minus one. However when we use
4
td->entry_sz we assume it to be the number of bytes per table entry
5
(for instance we calculate the number of entries in a page by
6
dividing the page size by the entry size).
7
8
The effects of this bug are:
9
* we miscalculate the maximum number of entries in the table,
10
so our checks on guest index values are wrong (too lax)
11
* when looking up an entry in the second level of an indirect
12
table, we calculate an incorrect index into the L2 table.
13
Because we make the same incorrect calculation on both
14
reads and writes of the L2 table, the guest won't notice
15
unless it's unlucky enough to use an index value that
16
causes us to index off the end of the L2 table page and
17
cause guest memory corruption in whatever follows
18
3
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
21
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20180620132032.28865-9-peter.maydell@linaro.org
22
---
7
---
23
hw/intc/arm_gicv3_its.c | 2 +-
8
hw/arm/mps2-tz.c | 71 ++++++++++++++++++++++++++++++------------------
24
1 file changed, 1 insertion(+), 1 deletion(-)
9
1 file changed, 44 insertions(+), 27 deletions(-)
25
10
26
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
11
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
27
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/intc/arm_gicv3_its.c
13
--- a/hw/arm/mps2-tz.c
29
+++ b/hw/intc/arm_gicv3_its.c
14
+++ b/hw/arm/mps2-tz.c
30
@@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s)
15
@@ -XXX,XX +XXX,XX @@
31
}
16
#include "hw/timer/cmsdk-apb-timer.h"
32
td->page_sz = page_sz;
17
#include "hw/misc/mps2-scc.h"
33
td->indirect = FIELD_EX64(value, GITS_BASER, INDIRECT);
18
#include "hw/misc/mps2-fpgaio.h"
34
- td->entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE);
19
+#include "hw/misc/tz-mpc.h"
35
+ td->entry_sz = FIELD_EX64(value, GITS_BASER, ENTRYSIZE) + 1;
20
#include "hw/arm/iotkit.h"
36
td->base_addr = baser_base_addr(value, page_sz);
21
#include "hw/devices.h"
37
if (!td->indirect) {
22
#include "net/net.h"
38
td->max_entries = (num_pages * page_sz) / td->entry_sz;
23
@@ -XXX,XX +XXX,XX @@ typedef struct {
24
25
IoTKit iotkit;
26
MemoryRegion psram;
27
- MemoryRegion ssram1;
28
+ MemoryRegion ssram[3];
29
MemoryRegion ssram1_m;
30
- MemoryRegion ssram23;
31
MPS2SCC scc;
32
MPS2FPGAIO fpgaio;
33
TZPPC ppc[5];
34
- UnimplementedDeviceState ssram_mpc[3];
35
+ TZMPC ssram_mpc[3];
36
UnimplementedDeviceState spi[5];
37
UnimplementedDeviceState i2c[4];
38
UnimplementedDeviceState i2s_audio;
39
@@ -XXX,XX +XXX,XX @@ typedef struct {
40
/* Main SYSCLK frequency in Hz */
41
#define SYSCLK_FRQ 20000000
42
43
-/* Initialize the auxiliary RAM region @mr and map it into
44
- * the memory map at @base.
45
- */
46
-static void make_ram(MemoryRegion *mr, const char *name,
47
- hwaddr base, hwaddr size)
48
-{
49
- memory_region_init_ram(mr, NULL, name, size, &error_fatal);
50
- memory_region_add_subregion(get_system_memory(), base, mr);
51
-}
52
-
53
/* Create an alias of an entire original MemoryRegion @orig
54
* located at @base in the memory map.
55
*/
56
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
57
return sysbus_mmio_get_region(s, 0);
58
}
59
60
+static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
61
+ const char *name, hwaddr size)
62
+{
63
+ TZMPC *mpc = opaque;
64
+ int i = mpc - &mms->ssram_mpc[0];
65
+ MemoryRegion *ssram = &mms->ssram[i];
66
+ MemoryRegion *upstream;
67
+ char *mpcname = g_strdup_printf("%s-mpc", name);
68
+ static uint32_t ramsize[] = { 0x00400000, 0x00200000, 0x00200000 };
69
+ static uint32_t rambase[] = { 0x00000000, 0x28000000, 0x28200000 };
70
+
71
+ memory_region_init_ram(ssram, NULL, name, ramsize[i], &error_fatal);
72
+
73
+ init_sysbus_child(OBJECT(mms), mpcname, mpc,
74
+ sizeof(mms->ssram_mpc[0]), TYPE_TZ_MPC);
75
+ object_property_set_link(OBJECT(mpc), OBJECT(ssram),
76
+ "downstream", &error_fatal);
77
+ object_property_set_bool(OBJECT(mpc), true, "realized", &error_fatal);
78
+ /* Map the upstream end of the MPC into system memory */
79
+ upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1);
80
+ memory_region_add_subregion(get_system_memory(), rambase[i], upstream);
81
+ /* and connect its interrupt to the IoTKit */
82
+ qdev_connect_gpio_out_named(DEVICE(mpc), "irq", 0,
83
+ qdev_get_gpio_in_named(DEVICE(&mms->iotkit),
84
+ "mpcexp_status", i));
85
+
86
+ /* The first SSRAM is a special case as it has an alias; accesses to
87
+ * the alias region at 0x00400000 must also go to the MPC upstream.
88
+ */
89
+ if (i == 0) {
90
+ make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", upstream, 0x00400000);
91
+ }
92
+
93
+ g_free(mpcname);
94
+ /* Return the register interface MR for our caller to map behind the PPC */
95
+ return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0);
96
+}
97
+
98
static void mps2tz_common_init(MachineState *machine)
99
{
100
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
101
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
102
NULL, "mps.ram", 0x01000000);
103
memory_region_add_subregion(system_memory, 0x80000000, &mms->psram);
104
105
- /* The SSRAM memories should all be behind Memory Protection Controllers,
106
- * but we don't implement that yet.
107
- */
108
- make_ram(&mms->ssram1, "mps.ssram1", 0x00000000, 0x00400000);
109
- make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", &mms->ssram1, 0x00400000);
110
-
111
- make_ram(&mms->ssram23, "mps.ssram23", 0x28000000, 0x00400000);
112
-
113
/* The overflow IRQs for all UARTs are ORed together.
114
* Tx, Rx and "combined" IRQs are sent to the NVIC separately.
115
* Create the OR gate for this.
116
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
117
const PPCInfo ppcs[] = { {
118
.name = "apb_ppcexp0",
119
.ports = {
120
- { "ssram-mpc0", make_unimp_dev, &mms->ssram_mpc[0],
121
- 0x58007000, 0x1000 },
122
- { "ssram-mpc1", make_unimp_dev, &mms->ssram_mpc[1],
123
- 0x58008000, 0x1000 },
124
- { "ssram-mpc2", make_unimp_dev, &mms->ssram_mpc[2],
125
- 0x58009000, 0x1000 },
126
+ { "ssram-0", make_mpc, &mms->ssram_mpc[0], 0x58007000, 0x1000 },
127
+ { "ssram-1", make_mpc, &mms->ssram_mpc[1], 0x58008000, 0x1000 },
128
+ { "ssram-2", make_mpc, &mms->ssram_mpc[2], 0x58009000, 0x1000 },
129
},
130
}, {
131
.name = "apb_ppcexp1",
39
--
132
--
40
2.25.1
133
2.17.1
41
134
42
135
diff view generated by jsdifflib
1
From: Troy Lee <troy_lee@aspeedtech.com>
1
From: Julia Suvorova <jusual@mail.ru>
2
2
3
AST2600 Display Port MCU introduces 0x18000000~0x1803FFFF as it's memory
3
This feature is intended to distinguish ARMv8-M variants: Baseline and
4
and io address. If guest machine try to access DPMCU memory, it will
4
Mainline. ARMv7-M compatibility requires the Main Extension. ARMv6-M
5
cause a fatal error.
5
compatibility is provided by all ARMv8-M implementations.
6
6
7
Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
7
Signed-off-by: Julia Suvorova <jusual@mail.ru>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20180622080138.17702-2-jusual@mail.ru
9
Reviewed-by: Cédric Le Goater <clg@kaod.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Message-id: 20211210083034.726610-1-troy_lee@aspeedtech.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
11
---
13
include/hw/arm/aspeed_soc.h | 2 ++
12
target/arm/cpu.h | 1 +
14
hw/arm/aspeed_ast2600.c | 8 ++++++++
13
target/arm/cpu.c | 3 +++
15
2 files changed, 10 insertions(+)
14
2 files changed, 4 insertions(+)
16
15
17
diff --git a/include/hw/arm/aspeed_soc.h b/include/hw/arm/aspeed_soc.h
16
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/arm/aspeed_soc.h
18
--- a/target/arm/cpu.h
20
+++ b/include/hw/arm/aspeed_soc.h
19
+++ b/target/arm/cpu.h
21
@@ -XXX,XX +XXX,XX @@ enum {
20
@@ -XXX,XX +XXX,XX @@ enum arm_features {
22
ASPEED_DEV_EMMC,
21
ARM_FEATURE_V8_RDM, /* implements v8.1 simd round multiply */
23
ASPEED_DEV_KCS,
22
ARM_FEATURE_V8_FP16, /* implements v8.2 half-precision float */
24
ASPEED_DEV_HACE,
23
ARM_FEATURE_V8_FCMA, /* has complex number part of v8.3 extensions. */
25
+ ASPEED_DEV_DPMCU,
24
+ ARM_FEATURE_M_MAIN, /* M profile Main Extension */
26
+ ASPEED_DEV_DP,
27
};
25
};
28
26
29
#endif /* ASPEED_SOC_H */
27
static inline int arm_feature(CPUARMState *env, int feature)
30
diff --git a/hw/arm/aspeed_ast2600.c b/hw/arm/aspeed_ast2600.c
28
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
31
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/arm/aspeed_ast2600.c
30
--- a/target/arm/cpu.c
33
+++ b/hw/arm/aspeed_ast2600.c
31
+++ b/target/arm/cpu.c
34
@@ -XXX,XX +XXX,XX @@
32
@@ -XXX,XX +XXX,XX @@ static void cortex_m3_initfn(Object *obj)
35
#include "sysemu/sysemu.h"
33
ARMCPU *cpu = ARM_CPU(obj);
36
34
set_feature(&cpu->env, ARM_FEATURE_V7);
37
#define ASPEED_SOC_IOMEM_SIZE 0x00200000
35
set_feature(&cpu->env, ARM_FEATURE_M);
38
+#define ASPEED_SOC_DPMCU_SIZE 0x00040000
36
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
39
37
cpu->midr = 0x410fc231;
40
static const hwaddr aspeed_soc_ast2600_memmap[] = {
38
cpu->pmsav7_dregion = 8;
41
[ASPEED_DEV_SRAM] = 0x10000000,
39
cpu->id_pfr0 = 0x00000030;
42
+ [ASPEED_DEV_DPMCU] = 0x18000000,
40
@@ -XXX,XX +XXX,XX @@ static void cortex_m4_initfn(Object *obj)
43
/* 0x16000000 0x17FFFFFF : AHB BUS do LPC Bus bridge */
41
44
[ASPEED_DEV_IOMEM] = 0x1E600000,
42
set_feature(&cpu->env, ARM_FEATURE_V7);
45
[ASPEED_DEV_PWM] = 0x1E610000,
43
set_feature(&cpu->env, ARM_FEATURE_M);
46
@@ -XXX,XX +XXX,XX @@ static const hwaddr aspeed_soc_ast2600_memmap[] = {
44
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
47
[ASPEED_DEV_SCU] = 0x1E6E2000,
45
set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
48
[ASPEED_DEV_XDMA] = 0x1E6E7000,
46
cpu->midr = 0x410fc240; /* r0p0 */
49
[ASPEED_DEV_ADC] = 0x1E6E9000,
47
cpu->pmsav7_dregion = 8;
50
+ [ASPEED_DEV_DP] = 0x1E6EB000,
48
@@ -XXX,XX +XXX,XX @@ static void cortex_m33_initfn(Object *obj)
51
[ASPEED_DEV_VIDEO] = 0x1E700000,
49
52
[ASPEED_DEV_SDHCI] = 0x1E740000,
50
set_feature(&cpu->env, ARM_FEATURE_V8);
53
[ASPEED_DEV_EMMC] = 0x1E750000,
51
set_feature(&cpu->env, ARM_FEATURE_M);
54
@@ -XXX,XX +XXX,XX @@ static const int aspeed_soc_ast2600_irqmap[] = {
52
+ set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
55
[ASPEED_DEV_ETH3] = 32,
53
set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
56
[ASPEED_DEV_ETH4] = 33,
54
set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
57
[ASPEED_DEV_KCS] = 138, /* 138 -> 142 */
55
cpu->midr = 0x410fd213; /* r0p3 */
58
+ [ASPEED_DEV_DP] = 62,
59
};
60
61
static qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int ctrl)
62
@@ -XXX,XX +XXX,XX @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
63
memory_region_add_subregion(get_system_memory(),
64
sc->memmap[ASPEED_DEV_SRAM], &s->sram);
65
66
+ /* DPMCU */
67
+ create_unimplemented_device("aspeed.dpmcu", sc->memmap[ASPEED_DEV_DPMCU],
68
+ ASPEED_SOC_DPMCU_SIZE);
69
+
70
/* SCU */
71
if (!sysbus_realize(SYS_BUS_DEVICE(&s->scu), errp)) {
72
return;
73
--
56
--
74
2.25.1
57
2.17.1
75
58
76
59
diff view generated by jsdifflib
1
The checks in the ITS on the rdbase values in guest commands are
1
From: Julia Suvorova <jusual@mail.ru>
2
off-by-one: they permit the guest to pass us a value equal to
3
s->gicv3->num_cpu, but the valid values are 0...num_cpu-1. This
4
meant the guest could cause us to index off the end of the
5
s->gicv3->cpu[] array when calling gicv3_redist_process_lpi(), and we
6
would probably crash.
7
2
8
(This is not a security bug, because this code is only usable
3
Unlike ARMv7-M, ARMv6-M and ARMv8-M Baseline only supports naturally
9
with emulation, not with KVM.)
4
aligned memory accesses for load/store instructions.
10
5
11
Cc: qemu-stable@nongnu.org
6
Signed-off-by: Julia Suvorova <jusual@mail.ru>
12
Fixes: 17fb5e36aabd4b ("hw/intc: GICv3 redistributor ITS processing")
7
Message-id: 20180622080138.17702-3-jusual@mail.ru
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
---
10
---
17
hw/intc/arm_gicv3_its.c | 4 ++--
11
target/arm/translate.c | 18 ++++++++++++++++--
18
1 file changed, 2 insertions(+), 2 deletions(-)
12
1 file changed, 16 insertions(+), 2 deletions(-)
19
13
20
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
14
diff --git a/target/arm/translate.c b/target/arm/translate.c
21
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/intc/arm_gicv3_its.c
16
--- a/target/arm/translate.c
23
+++ b/hw/intc/arm_gicv3_its.c
17
+++ b/target/arm/translate.c
24
@@ -XXX,XX +XXX,XX @@ static bool process_its_cmd(GICv3ITSState *s, uint64_t value, uint32_t offset,
18
@@ -XXX,XX +XXX,XX @@ static inline TCGv gen_aa32_addr(DisasContext *s, TCGv_i32 a32, TCGMemOp op)
25
*/
19
static void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
26
rdbase = (cte & GITS_CTE_RDBASE_PROCNUM_MASK) >> 1U;
20
int index, TCGMemOp opc)
27
21
{
28
- if (rdbase > s->gicv3->num_cpu) {
22
- TCGv addr = gen_aa32_addr(s, a32, opc);
29
+ if (rdbase >= s->gicv3->num_cpu) {
23
+ TCGv addr;
30
return result;
24
+
31
}
25
+ if (arm_dc_feature(s, ARM_FEATURE_M) &&
32
26
+ !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
33
@@ -XXX,XX +XXX,XX @@ static bool process_mapc(GICv3ITSState *s, uint32_t offset)
27
+ opc |= MO_ALIGN;
34
28
+ }
35
valid = (value & CMD_FIELD_VALID_MASK);
29
+
36
30
+ addr = gen_aa32_addr(s, a32, opc);
37
- if ((icid > s->ct.maxids.max_collids) || (rdbase > s->gicv3->num_cpu)) {
31
tcg_gen_qemu_ld_i32(val, addr, index, opc);
38
+ if ((icid > s->ct.maxids.max_collids) || (rdbase >= s->gicv3->num_cpu)) {
32
tcg_temp_free(addr);
39
qemu_log_mask(LOG_GUEST_ERROR,
33
}
40
"ITS MAPC: invalid collection table attributes "
34
@@ -XXX,XX +XXX,XX @@ static void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
41
"icid %d rdbase %" PRIu64 "\n", icid, rdbase);
35
static void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
36
int index, TCGMemOp opc)
37
{
38
- TCGv addr = gen_aa32_addr(s, a32, opc);
39
+ TCGv addr;
40
+
41
+ if (arm_dc_feature(s, ARM_FEATURE_M) &&
42
+ !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
43
+ opc |= MO_ALIGN;
44
+ }
45
+
46
+ addr = gen_aa32_addr(s, a32, opc);
47
tcg_gen_qemu_st_i32(val, addr, index, opc);
48
tcg_temp_free(addr);
49
}
42
--
50
--
43
2.25.1
51
2.17.1
44
52
45
53
diff view generated by jsdifflib
1
In extract_table_params() we process each GITS_BASER<n> register. If
1
checkpatch reminds us that statics shouldn't be zero-initialized:
2
the register's Valid bit is not set, this means there is no
3
in-guest-memory table and so we should not try to interpret the other
4
fields in the register. This was incorrectly coded as a 'return'
5
rather than a 'break', so instead of looping round to process the
6
next GITS_BASER<n> we would stop entirely, treating any later tables
7
as being not valid also.
8
2
9
This has no real guest-visible effects because (since we don't have
3
ERROR: do not initialise statics to 0 or NULL
10
GITS_TYPER.HCC != 0) the guest must in any case set up all the
4
#35: FILE: vl.c:157:
11
GITS_BASER<n> to point to valid tables, so this only happens in an
5
+static int num_serial_hds = 0;
12
odd misbehaving-guest corner case.
13
6
14
Fix the check to 'break', so that we leave the case statement and
7
ERROR: do not initialise statics to 0 or NULL
15
loop back around to the next GITS_BASER<n>.
8
#36: FILE: vl.c:158:
9
+static Chardev **serial_hds = NULL;
10
11
I forgot to fix this in 6af2692e86f9fdfb3d; do so now.
16
12
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
14
Reviewed-by: Thomas Huth <thuth@redhat.com>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20180426140253.3918-1-peter.maydell@linaro.org
20
---
16
---
21
hw/intc/arm_gicv3_its.c | 4 ++--
17
vl.c | 4 ++--
22
1 file changed, 2 insertions(+), 2 deletions(-)
18
1 file changed, 2 insertions(+), 2 deletions(-)
23
19
24
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
20
diff --git a/vl.c b/vl.c
25
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/intc/arm_gicv3_its.c
22
--- a/vl.c
27
+++ b/hw/intc/arm_gicv3_its.c
23
+++ b/vl.c
28
@@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s)
24
@@ -XXX,XX +XXX,XX @@ QEMUClockType rtc_clock;
29
s->dt.valid = FIELD_EX64(value, GITS_BASER, VALID);
25
int vga_interface_type = VGA_NONE;
30
26
static DisplayOptions dpy;
31
if (!s->dt.valid) {
27
int no_frame;
32
- return;
28
-static int num_serial_hds = 0;
33
+ break;
29
-static Chardev **serial_hds = NULL;
34
}
30
+static int num_serial_hds;
35
31
+static Chardev **serial_hds;
36
s->dt.page_sz = page_sz;
32
Chardev *parallel_hds[MAX_PARALLEL_PORTS];
37
@@ -XXX,XX +XXX,XX @@ static void extract_table_params(GICv3ITSState *s)
33
Chardev *virtcon_hds[MAX_VIRTIO_CONSOLES];
38
* hence writes are discarded if ct.valid is 0
34
int win2k_install_hack = 0;
39
*/
40
if (!s->ct.valid) {
41
- return;
42
+ break;
43
}
44
45
s->ct.page_sz = page_sz;
46
--
35
--
47
2.25.1
36
2.17.1
48
37
49
38
diff view generated by jsdifflib
1
From: Chris Rauer <crauer@google.com>
1
The xen pci_assign_dev_load_option_rom() currently creates a RAM
2
memory region with memory_region_init_ram_nomigrate(), and then
3
manually registers it with vmstate_register_ram(). In fact for
4
its only callsite, the 'owner' pointer we use for the init call
5
and the '&dev->qdev' pointer we use for the vmstate_register_ram()
6
call refer to the same object. Simplify the function to only
7
take a pointer to the device once instead of twice, and use
8
memory_region_init_ram() which automatically does the vmstate
9
register for us.
2
10
3
Signed-off-by: Chris Rauer <crauer@google.com>
11
Acked-by: Anthony PERARD <anthony.perard@citrix.com>
4
Reviewed-by: Hao Wu <wuhaotsh@google.com>
5
Reviewed-by: Patrick Venture <venture@google.com>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20220102215844.2888833-2-venture@google.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
13
---
10
hw/arm/npcm7xx_boards.c | 8 ++++++++
14
hw/xen/xen_pt.h | 2 +-
11
1 file changed, 8 insertions(+)
15
hw/xen/xen_pt_graphics.c | 2 +-
16
hw/xen/xen_pt_load_rom.c | 6 +++---
17
3 files changed, 5 insertions(+), 5 deletions(-)
12
18
13
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
19
diff --git a/hw/xen/xen_pt.h b/hw/xen/xen_pt.h
14
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/npcm7xx_boards.c
21
--- a/hw/xen/xen_pt.h
16
+++ b/hw/arm/npcm7xx_boards.c
22
+++ b/hw/xen/xen_pt.h
17
@@ -XXX,XX +XXX,XX @@ static void quanta_gbs_i2c_init(NPCM7xxState *soc)
23
@@ -XXX,XX +XXX,XX @@ static inline bool xen_pt_has_msix_mapping(XenPCIPassthroughState *s, int bar)
18
*/
19
}
24
}
20
25
21
+static void kudo_bmc_i2c_init(NPCM7xxState *soc)
26
extern void *pci_assign_dev_load_option_rom(PCIDevice *dev,
22
+{
27
- struct Object *owner, int *size,
23
+ at24c_eeprom_init(soc, 4, 0x50, 8192); /* mbfru */
28
+ int *size,
24
+ at24c_eeprom_init(soc, 14, 0x55, 8192); /* bmcfru */
29
unsigned int domain,
25
+ /* TODO: Add remaining i2c devices. */
30
unsigned int bus, unsigned int slot,
26
+}
31
unsigned int function);
27
+
32
diff --git a/hw/xen/xen_pt_graphics.c b/hw/xen/xen_pt_graphics.c
28
static void npcm750_evb_init(MachineState *machine)
33
index XXXXXXX..XXXXXXX 100644
34
--- a/hw/xen/xen_pt_graphics.c
35
+++ b/hw/xen/xen_pt_graphics.c
36
@@ -XXX,XX +XXX,XX @@ int xen_pt_unregister_vga_regions(XenHostPCIDevice *dev)
37
static void *get_vgabios(XenPCIPassthroughState *s, int *size,
38
XenHostPCIDevice *dev)
29
{
39
{
30
NPCM7xxState *soc;
40
- return pci_assign_dev_load_option_rom(&s->dev, OBJECT(&s->dev), size,
31
@@ -XXX,XX +XXX,XX @@ static void kudo_bmc_init(MachineState *machine)
41
+ return pci_assign_dev_load_option_rom(&s->dev, size,
32
npcm7xx_connect_flash(&soc->fiu[1], 0, "mx66u51235f",
42
dev->domain, dev->bus,
33
drive_get(IF_MTD, 3, 0));
43
dev->dev, dev->func);
34
35
+ kudo_bmc_i2c_init(soc);
36
npcm7xx_load_kernel(machine, soc);
37
}
44
}
45
diff --git a/hw/xen/xen_pt_load_rom.c b/hw/xen/xen_pt_load_rom.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/hw/xen/xen_pt_load_rom.c
48
+++ b/hw/xen/xen_pt_load_rom.c
49
@@ -XXX,XX +XXX,XX @@
50
* load the corresponding ROM data to RAM. If an error occurs while loading an
51
* option ROM, we just ignore that option ROM and continue with the next one.
52
*/
53
-void *pci_assign_dev_load_option_rom(PCIDevice *dev, struct Object *owner,
54
+void *pci_assign_dev_load_option_rom(PCIDevice *dev,
55
int *size, unsigned int domain,
56
unsigned int bus, unsigned int slot,
57
unsigned int function)
58
@@ -XXX,XX +XXX,XX @@ void *pci_assign_dev_load_option_rom(PCIDevice *dev, struct Object *owner,
59
uint8_t val;
60
struct stat st;
61
void *ptr = NULL;
62
+ Object *owner = OBJECT(dev);
63
64
/* If loading ROM from file, pci handles it */
65
if (dev->romfile || !dev->rom_bar) {
66
@@ -XXX,XX +XXX,XX @@ void *pci_assign_dev_load_option_rom(PCIDevice *dev, struct Object *owner,
67
fseek(fp, 0, SEEK_SET);
68
69
snprintf(name, sizeof(name), "%s.rom", object_get_typename(owner));
70
- memory_region_init_ram_nomigrate(&dev->rom, owner, name, st.st_size, &error_abort);
71
- vmstate_register_ram(&dev->rom, &dev->qdev);
72
+ memory_region_init_ram(&dev->rom, owner, name, st.st_size, &error_abort);
73
ptr = memory_region_get_ram_ptr(&dev->rom);
74
memset(ptr, 0xff, st.st_size);
38
75
39
--
76
--
40
2.25.1
77
2.17.1
41
78
42
79
diff view generated by jsdifflib