| 
									
										
										
										
											2015-09-24 01:29:37 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * ARM Generic Interrupt Controller using KVM in-kernel support | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (c) 2015 Samsung Electronics Co., Ltd. | 
					
						
							|  |  |  |  * Written by Pavel Fedin | 
					
						
							|  |  |  |  * Based on vGICv2 code by Peter Maydell | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is free software; you can redistribute it and/or modify | 
					
						
							|  |  |  |  * it under the terms of the GNU General Public License as published by | 
					
						
							|  |  |  |  * the Free Software Foundation, either version 2 of the License, or | 
					
						
							|  |  |  |  * (at your option) any later version. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  |  * GNU General Public License for more details. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * You should have received a copy of the GNU General Public License along | 
					
						
							|  |  |  |  * with this program; if not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-26 18:17:05 +00:00
										 |  |  | #include "qemu/osdep.h"
 | 
					
						
							| 
									
										
											  
											
												include/qemu/osdep.h: Don't include qapi/error.h
Commit 57cb38b included qapi/error.h into qemu/osdep.h to get the
Error typedef.  Since then, we've moved to include qemu/osdep.h
everywhere.  Its file comment explains: "To avoid getting into
possible circular include dependencies, this file should not include
any other QEMU headers, with the exceptions of config-host.h,
compiler.h, os-posix.h and os-win32.h, all of which are doing a
similar job to this file and are under similar constraints."
qapi/error.h doesn't do a similar job, and it doesn't adhere to
similar constraints: it includes qapi-types.h.  That's in excess of
100KiB of crap most .c files don't actually need.
Add the typedef to qemu/typedefs.h, and include that instead of
qapi/error.h.  Include qapi/error.h in .c files that need it and don't
get it now.  Include qapi-types.h in qom/object.h for uint16List.
Update scripts/clean-includes accordingly.  Update it further to match
reality: replace config.h by config-target.h, add sysemu/os-posix.h,
sysemu/os-win32.h.  Update the list of includes in the qemu/osdep.h
comment quoted above similarly.
This reduces the number of objects depending on qapi/error.h from "all
of them" to less than a third.  Unfortunately, the number depending on
qapi-types.h shrinks only a little.  More work is needed for that one.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
[Fix compilation without the spice devel packages. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
											
										 
											2016-03-14 09:01:28 +01:00
										 |  |  | #include "qapi/error.h"
 | 
					
						
							| 
									
										
										
										
											2015-09-24 01:29:37 +01:00
										 |  |  | #include "hw/intc/arm_gicv3_common.h"
 | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  | #include "qemu/error-report.h"
 | 
					
						
							| 
									
										
										
										
											2019-05-23 16:35:07 +02:00
										 |  |  | #include "qemu/module.h"
 | 
					
						
							| 
									
										
										
										
											2015-09-24 01:29:37 +01:00
										 |  |  | #include "sysemu/kvm.h"
 | 
					
						
							| 
									
										
										
										
											2019-08-12 07:23:59 +02:00
										 |  |  | #include "sysemu/runstate.h"
 | 
					
						
							| 
									
										
										
										
											2015-09-24 01:29:37 +01:00
										 |  |  | #include "kvm_arm.h"
 | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  | #include "gicv3_internal.h"
 | 
					
						
							| 
									
										
										
										
											2015-09-24 01:29:37 +01:00
										 |  |  | #include "vgic_common.h"
 | 
					
						
							| 
									
										
										
										
											2017-04-06 12:00:28 +02:00
										 |  |  | #include "migration/blocker.h"
 | 
					
						
							| 
									
										
										
										
											2020-09-03 16:43:22 -04:00
										 |  |  | #include "qom/object.h"
 | 
					
						
							| 
									
										
										
										
											2022-04-30 22:49:43 -07:00
										 |  |  | #include "target/arm/cpregs.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-24 01:29:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef DEBUG_GICV3_KVM
 | 
					
						
							|  |  |  | #define DPRINTF(fmt, ...) \
 | 
					
						
							|  |  |  |     do { fprintf(stderr, "kvm_gicv3: " fmt, ## __VA_ARGS__); } while (0) | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | #define DPRINTF(fmt, ...) \
 | 
					
						
							|  |  |  |     do { } while (0) | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define TYPE_KVM_ARM_GICV3 "kvm-arm-gicv3"
 | 
					
						
							| 
									
										
										
										
											2020-09-03 16:43:22 -04:00
										 |  |  | typedef struct KVMARMGICv3Class KVMARMGICv3Class; | 
					
						
							| 
									
										
										
										
											2020-08-31 17:07:36 -04:00
										 |  |  | /* This is reusing the GICv3State typedef from ARM_GICV3_ITS_COMMON */ | 
					
						
							|  |  |  | DECLARE_OBJ_CHECKERS(GICv3State, KVMARMGICv3Class, | 
					
						
							|  |  |  |                      KVM_ARM_GICV3, TYPE_KVM_ARM_GICV3) | 
					
						
							| 
									
										
										
										
											2015-09-24 01:29:37 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  | #define   KVM_DEV_ARM_VGIC_SYSREG(op0, op1, crn, crm, op2)         \
 | 
					
						
							|  |  |  |                              (ARM64_SYS_REG_SHIFT_MASK(op0, OP0) | \ | 
					
						
							|  |  |  |                               ARM64_SYS_REG_SHIFT_MASK(op1, OP1) | \ | 
					
						
							|  |  |  |                               ARM64_SYS_REG_SHIFT_MASK(crn, CRN) | \ | 
					
						
							|  |  |  |                               ARM64_SYS_REG_SHIFT_MASK(crm, CRM) | \ | 
					
						
							|  |  |  |                               ARM64_SYS_REG_SHIFT_MASK(op2, OP2)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define ICC_PMR_EL1     \
 | 
					
						
							|  |  |  |     KVM_DEV_ARM_VGIC_SYSREG(3, 0, 4, 6, 0) | 
					
						
							|  |  |  | #define ICC_BPR0_EL1    \
 | 
					
						
							|  |  |  |     KVM_DEV_ARM_VGIC_SYSREG(3, 0, 12, 8, 3) | 
					
						
							|  |  |  | #define ICC_AP0R_EL1(n) \
 | 
					
						
							|  |  |  |     KVM_DEV_ARM_VGIC_SYSREG(3, 0, 12, 8, 4 | n) | 
					
						
							|  |  |  | #define ICC_AP1R_EL1(n) \
 | 
					
						
							|  |  |  |     KVM_DEV_ARM_VGIC_SYSREG(3, 0, 12, 9, n) | 
					
						
							|  |  |  | #define ICC_BPR1_EL1    \
 | 
					
						
							|  |  |  |     KVM_DEV_ARM_VGIC_SYSREG(3, 0, 12, 12, 3) | 
					
						
							|  |  |  | #define ICC_CTLR_EL1    \
 | 
					
						
							|  |  |  |     KVM_DEV_ARM_VGIC_SYSREG(3, 0, 12, 12, 4) | 
					
						
							|  |  |  | #define ICC_SRE_EL1 \
 | 
					
						
							|  |  |  |     KVM_DEV_ARM_VGIC_SYSREG(3, 0, 12, 12, 5) | 
					
						
							|  |  |  | #define ICC_IGRPEN0_EL1 \
 | 
					
						
							|  |  |  |     KVM_DEV_ARM_VGIC_SYSREG(3, 0, 12, 12, 6) | 
					
						
							|  |  |  | #define ICC_IGRPEN1_EL1 \
 | 
					
						
							|  |  |  |     KVM_DEV_ARM_VGIC_SYSREG(3, 0, 12, 12, 7) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-03 16:43:22 -04:00
										 |  |  | struct KVMARMGICv3Class { | 
					
						
							| 
									
										
										
										
											2015-09-24 01:29:37 +01:00
										 |  |  |     ARMGICv3CommonClass parent_class; | 
					
						
							|  |  |  |     DeviceRealize parent_realize; | 
					
						
							|  |  |  |     void (*parent_reset)(DeviceState *dev); | 
					
						
							| 
									
										
										
										
											2020-09-03 16:43:22 -04:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2015-09-24 01:29:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | static void kvm_arm_gicv3_set_irq(void *opaque, int irq, int level) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     GICv3State *s = (GICv3State *)opaque; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     kvm_arm_gic_set_irq(s->num_irq, irq, level); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  | #define KVM_VGIC_ATTR(reg, typer) \
 | 
					
						
							|  |  |  |     ((typer & KVM_DEV_ARM_VGIC_V3_MPIDR_MASK) | (reg)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void kvm_gicd_access(GICv3State *s, int offset, | 
					
						
							|  |  |  |                                    uint32_t *val, bool write) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS, | 
					
						
							|  |  |  |                       KVM_VGIC_ATTR(offset, 0), | 
					
						
							| 
									
										
										
										
											2017-06-13 14:57:00 +01:00
										 |  |  |                       val, write, &error_abort); | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void kvm_gicr_access(GICv3State *s, int offset, int cpu, | 
					
						
							|  |  |  |                                    uint32_t *val, bool write) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, | 
					
						
							|  |  |  |                       KVM_VGIC_ATTR(offset, s->cpu[cpu].gicr_typer), | 
					
						
							| 
									
										
										
										
											2017-06-13 14:57:00 +01:00
										 |  |  |                       val, write, &error_abort); | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void kvm_gicc_access(GICv3State *s, uint64_t reg, int cpu, | 
					
						
							|  |  |  |                                    uint64_t *val, bool write) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, | 
					
						
							|  |  |  |                       KVM_VGIC_ATTR(reg, s->cpu[cpu].gicr_typer), | 
					
						
							| 
									
										
										
										
											2017-06-13 14:57:00 +01:00
										 |  |  |                       val, write, &error_abort); | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static inline void kvm_gic_line_level_access(GICv3State *s, int irq, int cpu, | 
					
						
							|  |  |  |                                              uint32_t *val, bool write) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO, | 
					
						
							|  |  |  |                       KVM_VGIC_ATTR(irq, s->cpu[cpu].gicr_typer) | | 
					
						
							|  |  |  |                       (VGIC_LEVEL_INFO_LINE_LEVEL << | 
					
						
							|  |  |  |                        KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT), | 
					
						
							| 
									
										
										
										
											2017-06-13 14:57:00 +01:00
										 |  |  |                       val, write, &error_abort); | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Loop through each distributor IRQ related register; since bits
 | 
					
						
							|  |  |  |  * corresponding to SPIs and PPIs are RAZ/WI when affinity routing | 
					
						
							|  |  |  |  * is enabled, we skip those. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #define for_each_dist_irq_reg(_irq, _max, _field_width) \
 | 
					
						
							|  |  |  |     for (_irq = GIC_INTERNAL; _irq < _max; _irq += (32 / _field_width)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void kvm_dist_get_priority(GICv3State *s, uint32_t offset, uint8_t *bmp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint32_t reg, *field; | 
					
						
							|  |  |  |     int irq; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-15 14:57:13 +01:00
										 |  |  |     /* For the KVM GICv3, affinity routing is always enabled, and the first 8
 | 
					
						
							|  |  |  |      * GICD_IPRIORITYR<n> registers are always RAZ/WI. The corresponding | 
					
						
							|  |  |  |      * functionality is replaced by GICR_IPRIORITYR<n>. It doesn't need to | 
					
						
							|  |  |  |      * sync them. So it needs to skip the field of GIC_INTERNAL irqs in bmp and | 
					
						
							|  |  |  |      * offset. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     field = (uint32_t *)(bmp + GIC_INTERNAL); | 
					
						
							|  |  |  |     offset += (GIC_INTERNAL * 8) / 8; | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  |     for_each_dist_irq_reg(irq, s->num_irq, 8) { | 
					
						
							|  |  |  |         kvm_gicd_access(s, offset, ®, false); | 
					
						
							|  |  |  |         *field = reg; | 
					
						
							|  |  |  |         offset += 4; | 
					
						
							|  |  |  |         field++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void kvm_dist_put_priority(GICv3State *s, uint32_t offset, uint8_t *bmp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint32_t reg, *field; | 
					
						
							|  |  |  |     int irq; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-15 14:57:13 +01:00
										 |  |  |     /* For the KVM GICv3, affinity routing is always enabled, and the first 8
 | 
					
						
							|  |  |  |      * GICD_IPRIORITYR<n> registers are always RAZ/WI. The corresponding | 
					
						
							|  |  |  |      * functionality is replaced by GICR_IPRIORITYR<n>. It doesn't need to | 
					
						
							|  |  |  |      * sync them. So it needs to skip the field of GIC_INTERNAL irqs in bmp and | 
					
						
							|  |  |  |      * offset. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     field = (uint32_t *)(bmp + GIC_INTERNAL); | 
					
						
							|  |  |  |     offset += (GIC_INTERNAL * 8) / 8; | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  |     for_each_dist_irq_reg(irq, s->num_irq, 8) { | 
					
						
							|  |  |  |         reg = *field; | 
					
						
							|  |  |  |         kvm_gicd_access(s, offset, ®, true); | 
					
						
							|  |  |  |         offset += 4; | 
					
						
							|  |  |  |         field++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void kvm_dist_get_edge_trigger(GICv3State *s, uint32_t offset, | 
					
						
							|  |  |  |                                       uint32_t *bmp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint32_t reg; | 
					
						
							|  |  |  |     int irq; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-08 13:15:32 +01:00
										 |  |  |     /* For the KVM GICv3, affinity routing is always enabled, and the first 2
 | 
					
						
							|  |  |  |      * GICD_ICFGR<n> registers are always RAZ/WI. The corresponding | 
					
						
							|  |  |  |      * functionality is replaced by GICR_ICFGR<n>. It doesn't need to sync | 
					
						
							|  |  |  |      * them. So it should increase the offset to skip GIC_INTERNAL irqs. | 
					
						
							|  |  |  |      * This matches the for_each_dist_irq_reg() macro which also skips the | 
					
						
							|  |  |  |      * first GIC_INTERNAL irqs. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     offset += (GIC_INTERNAL * 2) / 8; | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  |     for_each_dist_irq_reg(irq, s->num_irq, 2) { | 
					
						
							|  |  |  |         kvm_gicd_access(s, offset, ®, false); | 
					
						
							|  |  |  |         reg = half_unshuffle32(reg >> 1); | 
					
						
							|  |  |  |         if (irq % 32 != 0) { | 
					
						
							|  |  |  |             reg = (reg << 16); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         *gic_bmp_ptr32(bmp, irq) |=  reg; | 
					
						
							|  |  |  |         offset += 4; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void kvm_dist_put_edge_trigger(GICv3State *s, uint32_t offset, | 
					
						
							|  |  |  |                                       uint32_t *bmp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint32_t reg; | 
					
						
							|  |  |  |     int irq; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-08 13:15:32 +01:00
										 |  |  |     /* For the KVM GICv3, affinity routing is always enabled, and the first 2
 | 
					
						
							|  |  |  |      * GICD_ICFGR<n> registers are always RAZ/WI. The corresponding | 
					
						
							|  |  |  |      * functionality is replaced by GICR_ICFGR<n>. It doesn't need to sync | 
					
						
							|  |  |  |      * them. So it should increase the offset to skip GIC_INTERNAL irqs. | 
					
						
							|  |  |  |      * This matches the for_each_dist_irq_reg() macro which also skips the | 
					
						
							|  |  |  |      * first GIC_INTERNAL irqs. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     offset += (GIC_INTERNAL * 2) / 8; | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  |     for_each_dist_irq_reg(irq, s->num_irq, 2) { | 
					
						
							|  |  |  |         reg = *gic_bmp_ptr32(bmp, irq); | 
					
						
							|  |  |  |         if (irq % 32 != 0) { | 
					
						
							|  |  |  |             reg = (reg & 0xffff0000) >> 16; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             reg = reg & 0xffff; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         reg = half_shuffle32(reg) << 1; | 
					
						
							|  |  |  |         kvm_gicd_access(s, offset, ®, true); | 
					
						
							|  |  |  |         offset += 4; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void kvm_gic_get_line_level_bmp(GICv3State *s, uint32_t *bmp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint32_t reg; | 
					
						
							|  |  |  |     int irq; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for_each_dist_irq_reg(irq, s->num_irq, 1) { | 
					
						
							|  |  |  |         kvm_gic_line_level_access(s, irq, 0, ®, false); | 
					
						
							|  |  |  |         *gic_bmp_ptr32(bmp, irq) = reg; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void kvm_gic_put_line_level_bmp(GICv3State *s, uint32_t *bmp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint32_t reg; | 
					
						
							|  |  |  |     int irq; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for_each_dist_irq_reg(irq, s->num_irq, 1) { | 
					
						
							|  |  |  |         reg = *gic_bmp_ptr32(bmp, irq); | 
					
						
							|  |  |  |         kvm_gic_line_level_access(s, irq, 0, ®, true); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Read a bitmap register group from the kernel VGIC. */ | 
					
						
							|  |  |  | static void kvm_dist_getbmp(GICv3State *s, uint32_t offset, uint32_t *bmp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint32_t reg; | 
					
						
							|  |  |  |     int irq; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-08 13:15:32 +01:00
										 |  |  |     /* For the KVM GICv3, affinity routing is always enabled, and the
 | 
					
						
							|  |  |  |      * GICD_IGROUPR0/GICD_IGRPMODR0/GICD_ISENABLER0/GICD_ISPENDR0/ | 
					
						
							|  |  |  |      * GICD_ISACTIVER0 registers are always RAZ/WI. The corresponding | 
					
						
							|  |  |  |      * functionality is replaced by the GICR registers. It doesn't need to sync | 
					
						
							|  |  |  |      * them. So it should increase the offset to skip GIC_INTERNAL irqs. | 
					
						
							|  |  |  |      * This matches the for_each_dist_irq_reg() macro which also skips the | 
					
						
							|  |  |  |      * first GIC_INTERNAL irqs. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     offset += (GIC_INTERNAL * 1) / 8; | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  |     for_each_dist_irq_reg(irq, s->num_irq, 1) { | 
					
						
							|  |  |  |         kvm_gicd_access(s, offset, ®, false); | 
					
						
							|  |  |  |         *gic_bmp_ptr32(bmp, irq) = reg; | 
					
						
							|  |  |  |         offset += 4; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void kvm_dist_putbmp(GICv3State *s, uint32_t offset, | 
					
						
							|  |  |  |                             uint32_t clroffset, uint32_t *bmp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint32_t reg; | 
					
						
							|  |  |  |     int irq; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-08 13:15:32 +01:00
										 |  |  |     /* For the KVM GICv3, affinity routing is always enabled, and the
 | 
					
						
							|  |  |  |      * GICD_IGROUPR0/GICD_IGRPMODR0/GICD_ISENABLER0/GICD_ISPENDR0/ | 
					
						
							|  |  |  |      * GICD_ISACTIVER0 registers are always RAZ/WI. The corresponding | 
					
						
							|  |  |  |      * functionality is replaced by the GICR registers. It doesn't need to sync | 
					
						
							|  |  |  |      * them. So it should increase the offset and clroffset to skip GIC_INTERNAL | 
					
						
							|  |  |  |      * irqs. This matches the for_each_dist_irq_reg() macro which also skips the | 
					
						
							|  |  |  |      * first GIC_INTERNAL irqs. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     offset += (GIC_INTERNAL * 1) / 8; | 
					
						
							|  |  |  |     if (clroffset != 0) { | 
					
						
							|  |  |  |         clroffset += (GIC_INTERNAL * 1) / 8; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  |     for_each_dist_irq_reg(irq, s->num_irq, 1) { | 
					
						
							|  |  |  |         /* If this bitmap is a set/clear register pair, first write to the
 | 
					
						
							|  |  |  |          * clear-reg to clear all bits before using the set-reg to write | 
					
						
							|  |  |  |          * the 1 bits. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         if (clroffset != 0) { | 
					
						
							|  |  |  |             reg = 0; | 
					
						
							|  |  |  |             kvm_gicd_access(s, clroffset, ®, true); | 
					
						
							| 
									
										
										
										
											2018-05-31 14:50:51 +01:00
										 |  |  |             clroffset += 4; | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  |         } | 
					
						
							|  |  |  |         reg = *gic_bmp_ptr32(bmp, irq); | 
					
						
							|  |  |  |         kvm_gicd_access(s, offset, ®, true); | 
					
						
							|  |  |  |         offset += 4; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void kvm_arm_gicv3_check(GICv3State *s) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint32_t reg; | 
					
						
							|  |  |  |     uint32_t num_irq; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Sanity checking s->num_irq */ | 
					
						
							|  |  |  |     kvm_gicd_access(s, GICD_TYPER, ®, false); | 
					
						
							|  |  |  |     num_irq = ((reg & 0x1f) + 1) * 32; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (num_irq < s->num_irq) { | 
					
						
							|  |  |  |         error_report("Model requests %u IRQs, but kernel supports max %u", | 
					
						
							|  |  |  |                      s->num_irq, num_irq); | 
					
						
							|  |  |  |         abort(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-24 01:29:37 +01:00
										 |  |  | static void kvm_arm_gicv3_put(GICv3State *s) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  |     uint32_t regl, regh, reg; | 
					
						
							|  |  |  |     uint64_t reg64, redist_typer; | 
					
						
							|  |  |  |     int ncpu, i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     kvm_arm_gicv3_check(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     kvm_gicr_access(s, GICR_TYPER, 0, ®l, false); | 
					
						
							|  |  |  |     kvm_gicr_access(s, GICR_TYPER + 4, 0, ®h, false); | 
					
						
							|  |  |  |     redist_typer = ((uint64_t)regh << 32) | regl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     reg = s->gicd_ctlr; | 
					
						
							|  |  |  |     kvm_gicd_access(s, GICD_CTLR, ®, true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (redist_typer & GICR_TYPER_PLPIS) { | 
					
						
							| 
									
										
										
										
											2020-01-30 16:02:05 +00:00
										 |  |  |         /*
 | 
					
						
							|  |  |  |          * Restore base addresses before LPIs are potentially enabled by | 
					
						
							|  |  |  |          * GICR_CTLR write | 
					
						
							|  |  |  |          */ | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  |         for (ncpu = 0; ncpu < s->num_cpu; ncpu++) { | 
					
						
							|  |  |  |             GICv3CPUState *c = &s->cpu[ncpu]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             reg64 = c->gicr_propbaser; | 
					
						
							|  |  |  |             regl = (uint32_t)reg64; | 
					
						
							|  |  |  |             kvm_gicr_access(s, GICR_PROPBASER, ncpu, ®l, true); | 
					
						
							|  |  |  |             regh = (uint32_t)(reg64 >> 32); | 
					
						
							|  |  |  |             kvm_gicr_access(s, GICR_PROPBASER + 4, ncpu, ®h, true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             reg64 = c->gicr_pendbaser; | 
					
						
							|  |  |  |             regl = (uint32_t)reg64; | 
					
						
							|  |  |  |             kvm_gicr_access(s, GICR_PENDBASER, ncpu, ®l, true); | 
					
						
							|  |  |  |             regh = (uint32_t)(reg64 >> 32); | 
					
						
							|  |  |  |             kvm_gicr_access(s, GICR_PENDBASER + 4, ncpu, ®h, true); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Redistributor state (one per CPU) */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (ncpu = 0; ncpu < s->num_cpu; ncpu++) { | 
					
						
							|  |  |  |         GICv3CPUState *c = &s->cpu[ncpu]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         reg = c->gicr_ctlr; | 
					
						
							|  |  |  |         kvm_gicr_access(s, GICR_CTLR, ncpu, ®, true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         reg = c->gicr_statusr[GICV3_NS]; | 
					
						
							|  |  |  |         kvm_gicr_access(s, GICR_STATUSR, ncpu, ®, true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         reg = c->gicr_waker; | 
					
						
							|  |  |  |         kvm_gicr_access(s, GICR_WAKER, ncpu, ®, true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         reg = c->gicr_igroupr0; | 
					
						
							|  |  |  |         kvm_gicr_access(s, GICR_IGROUPR0, ncpu, ®, true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         reg = ~0; | 
					
						
							|  |  |  |         kvm_gicr_access(s, GICR_ICENABLER0, ncpu, ®, true); | 
					
						
							|  |  |  |         reg = c->gicr_ienabler0; | 
					
						
							|  |  |  |         kvm_gicr_access(s, GICR_ISENABLER0, ncpu, ®, true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* Restore config before pending so we treat level/edge correctly */ | 
					
						
							|  |  |  |         reg = half_shuffle32(c->edge_trigger >> 16) << 1; | 
					
						
							|  |  |  |         kvm_gicr_access(s, GICR_ICFGR1, ncpu, ®, true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         reg = c->level; | 
					
						
							|  |  |  |         kvm_gic_line_level_access(s, 0, ncpu, ®, true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         reg = ~0; | 
					
						
							|  |  |  |         kvm_gicr_access(s, GICR_ICPENDR0, ncpu, ®, true); | 
					
						
							|  |  |  |         reg = c->gicr_ipendr0; | 
					
						
							|  |  |  |         kvm_gicr_access(s, GICR_ISPENDR0, ncpu, ®, true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         reg = ~0; | 
					
						
							|  |  |  |         kvm_gicr_access(s, GICR_ICACTIVER0, ncpu, ®, true); | 
					
						
							|  |  |  |         reg = c->gicr_iactiver0; | 
					
						
							|  |  |  |         kvm_gicr_access(s, GICR_ISACTIVER0, ncpu, ®, true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (i = 0; i < GIC_INTERNAL; i += 4) { | 
					
						
							|  |  |  |             reg = c->gicr_ipriorityr[i] | | 
					
						
							|  |  |  |                 (c->gicr_ipriorityr[i + 1] << 8) | | 
					
						
							|  |  |  |                 (c->gicr_ipriorityr[i + 2] << 16) | | 
					
						
							|  |  |  |                 (c->gicr_ipriorityr[i + 3] << 24); | 
					
						
							|  |  |  |             kvm_gicr_access(s, GICR_IPRIORITYR + i, ncpu, ®, true); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Distributor state (shared between all CPUs */ | 
					
						
							|  |  |  |     reg = s->gicd_statusr[GICV3_NS]; | 
					
						
							|  |  |  |     kvm_gicd_access(s, GICD_STATUSR, ®, true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* s->enable bitmap -> GICD_ISENABLERn */ | 
					
						
							|  |  |  |     kvm_dist_putbmp(s, GICD_ISENABLER, GICD_ICENABLER, s->enabled); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* s->group bitmap -> GICD_IGROUPRn */ | 
					
						
							|  |  |  |     kvm_dist_putbmp(s, GICD_IGROUPR, 0, s->group); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Restore targets before pending to ensure the pending state is set on
 | 
					
						
							|  |  |  |      * the appropriate CPU interfaces in the kernel | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* s->gicd_irouter[irq] -> GICD_IROUTERn
 | 
					
						
							|  |  |  |      * We can't use kvm_dist_put() here because the registers are 64-bit | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     for (i = GIC_INTERNAL; i < s->num_irq; i++) { | 
					
						
							|  |  |  |         uint32_t offset; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         offset = GICD_IROUTER + (sizeof(uint32_t) * i); | 
					
						
							|  |  |  |         reg = (uint32_t)s->gicd_irouter[i]; | 
					
						
							|  |  |  |         kvm_gicd_access(s, offset, ®, true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         offset = GICD_IROUTER + (sizeof(uint32_t) * i) + 4; | 
					
						
							|  |  |  |         reg = (uint32_t)(s->gicd_irouter[i] >> 32); | 
					
						
							|  |  |  |         kvm_gicd_access(s, offset, ®, true); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* s->trigger bitmap -> GICD_ICFGRn
 | 
					
						
							|  |  |  |      * (restore configuration registers before pending IRQs so we treat | 
					
						
							|  |  |  |      * level/edge correctly) | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     kvm_dist_put_edge_trigger(s, GICD_ICFGR, s->edge_trigger); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* s->level bitmap ->  line_level */ | 
					
						
							|  |  |  |     kvm_gic_put_line_level_bmp(s, s->level); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* s->pending bitmap -> GICD_ISPENDRn */ | 
					
						
							|  |  |  |     kvm_dist_putbmp(s, GICD_ISPENDR, GICD_ICPENDR, s->pending); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* s->active bitmap -> GICD_ISACTIVERn */ | 
					
						
							|  |  |  |     kvm_dist_putbmp(s, GICD_ISACTIVER, GICD_ICACTIVER, s->active); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* s->gicd_ipriority[] -> GICD_IPRIORITYRn */ | 
					
						
							|  |  |  |     kvm_dist_put_priority(s, GICD_IPRIORITYR, s->gicd_ipriority); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* CPU Interface state (one per CPU) */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (ncpu = 0; ncpu < s->num_cpu; ncpu++) { | 
					
						
							|  |  |  |         GICv3CPUState *c = &s->cpu[ncpu]; | 
					
						
							|  |  |  |         int num_pri_bits; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         kvm_gicc_access(s, ICC_SRE_EL1, ncpu, &c->icc_sre_el1, true); | 
					
						
							|  |  |  |         kvm_gicc_access(s, ICC_CTLR_EL1, ncpu, | 
					
						
							|  |  |  |                         &c->icc_ctlr_el1[GICV3_NS], true); | 
					
						
							|  |  |  |         kvm_gicc_access(s, ICC_IGRPEN0_EL1, ncpu, | 
					
						
							|  |  |  |                         &c->icc_igrpen[GICV3_G0], true); | 
					
						
							|  |  |  |         kvm_gicc_access(s, ICC_IGRPEN1_EL1, ncpu, | 
					
						
							|  |  |  |                         &c->icc_igrpen[GICV3_G1NS], true); | 
					
						
							|  |  |  |         kvm_gicc_access(s, ICC_PMR_EL1, ncpu, &c->icc_pmr_el1, true); | 
					
						
							|  |  |  |         kvm_gicc_access(s, ICC_BPR0_EL1, ncpu, &c->icc_bpr[GICV3_G0], true); | 
					
						
							|  |  |  |         kvm_gicc_access(s, ICC_BPR1_EL1, ncpu, &c->icc_bpr[GICV3_G1NS], true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         num_pri_bits = ((c->icc_ctlr_el1[GICV3_NS] & | 
					
						
							|  |  |  |                         ICC_CTLR_EL1_PRIBITS_MASK) >> | 
					
						
							|  |  |  |                         ICC_CTLR_EL1_PRIBITS_SHIFT) + 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch (num_pri_bits) { | 
					
						
							|  |  |  |         case 7: | 
					
						
							|  |  |  |             reg64 = c->icc_apr[GICV3_G0][3]; | 
					
						
							|  |  |  |             kvm_gicc_access(s, ICC_AP0R_EL1(3), ncpu, ®64, true); | 
					
						
							|  |  |  |             reg64 = c->icc_apr[GICV3_G0][2]; | 
					
						
							|  |  |  |             kvm_gicc_access(s, ICC_AP0R_EL1(2), ncpu, ®64, true); | 
					
						
							| 
									
										
											  
											
												hw/intc/arm_gicv3_kvm: silence the compiler warnings
When using -Wimplicit-fallthrough in our CFLAGS, the compiler showed warning:
hw/intc/arm_gicv3_kvm.c: In function ‘kvm_arm_gicv3_put’:
hw/intc/arm_gicv3_kvm.c:484:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
             kvm_gicc_access(s, ICC_AP0R_EL1(1), ncpu, ®64, true);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw/intc/arm_gicv3_kvm.c:485:9: note: here
         default:
         ^~~~~~~
hw/intc/arm_gicv3_kvm.c:495:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
             kvm_gicc_access(s, ICC_AP1R_EL1(2), ncpu, ®64, true);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw/intc/arm_gicv3_kvm.c:496:9: note: here
         case 6:
         ^~~~
hw/intc/arm_gicv3_kvm.c:498:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
             kvm_gicc_access(s, ICC_AP1R_EL1(1), ncpu, ®64, true);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw/intc/arm_gicv3_kvm.c:499:9: note: here
         default:
         ^~~~~~~
hw/intc/arm_gicv3_kvm.c: In function ‘kvm_arm_gicv3_get’:
hw/intc/arm_gicv3_kvm.c:634:37: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G0][2] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:635:9: note: here
         case 6:
         ^~~~
hw/intc/arm_gicv3_kvm.c:637:37: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G0][1] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:638:9: note: here
         default:
         ^~~~~~~
hw/intc/arm_gicv3_kvm.c:648:39: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G1NS][2] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:649:9: note: here
         case 6:
         ^~~~
hw/intc/arm_gicv3_kvm.c:651:39: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G1NS][1] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:652:9: note: here
         default:
         ^~~~~~~
Reported-by: Euler Robot <euler.robot@huawei.com>
Signed-off-by: Chen Qun <kuhn.chenqun@huawei.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-Id: <20201211152426.350966-7-thuth@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
											
										 
											2020-12-11 16:24:20 +01:00
										 |  |  |             /* fall through */ | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  |         case 6: | 
					
						
							|  |  |  |             reg64 = c->icc_apr[GICV3_G0][1]; | 
					
						
							|  |  |  |             kvm_gicc_access(s, ICC_AP0R_EL1(1), ncpu, ®64, true); | 
					
						
							| 
									
										
											  
											
												hw/intc/arm_gicv3_kvm: silence the compiler warnings
When using -Wimplicit-fallthrough in our CFLAGS, the compiler showed warning:
hw/intc/arm_gicv3_kvm.c: In function ‘kvm_arm_gicv3_put’:
hw/intc/arm_gicv3_kvm.c:484:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
             kvm_gicc_access(s, ICC_AP0R_EL1(1), ncpu, ®64, true);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw/intc/arm_gicv3_kvm.c:485:9: note: here
         default:
         ^~~~~~~
hw/intc/arm_gicv3_kvm.c:495:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
             kvm_gicc_access(s, ICC_AP1R_EL1(2), ncpu, ®64, true);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw/intc/arm_gicv3_kvm.c:496:9: note: here
         case 6:
         ^~~~
hw/intc/arm_gicv3_kvm.c:498:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
             kvm_gicc_access(s, ICC_AP1R_EL1(1), ncpu, ®64, true);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw/intc/arm_gicv3_kvm.c:499:9: note: here
         default:
         ^~~~~~~
hw/intc/arm_gicv3_kvm.c: In function ‘kvm_arm_gicv3_get’:
hw/intc/arm_gicv3_kvm.c:634:37: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G0][2] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:635:9: note: here
         case 6:
         ^~~~
hw/intc/arm_gicv3_kvm.c:637:37: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G0][1] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:638:9: note: here
         default:
         ^~~~~~~
hw/intc/arm_gicv3_kvm.c:648:39: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G1NS][2] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:649:9: note: here
         case 6:
         ^~~~
hw/intc/arm_gicv3_kvm.c:651:39: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G1NS][1] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:652:9: note: here
         default:
         ^~~~~~~
Reported-by: Euler Robot <euler.robot@huawei.com>
Signed-off-by: Chen Qun <kuhn.chenqun@huawei.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-Id: <20201211152426.350966-7-thuth@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
											
										 
											2020-12-11 16:24:20 +01:00
										 |  |  |             /* fall through */ | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  |         default: | 
					
						
							|  |  |  |             reg64 = c->icc_apr[GICV3_G0][0]; | 
					
						
							|  |  |  |             kvm_gicc_access(s, ICC_AP0R_EL1(0), ncpu, ®64, true); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch (num_pri_bits) { | 
					
						
							|  |  |  |         case 7: | 
					
						
							|  |  |  |             reg64 = c->icc_apr[GICV3_G1NS][3]; | 
					
						
							|  |  |  |             kvm_gicc_access(s, ICC_AP1R_EL1(3), ncpu, ®64, true); | 
					
						
							|  |  |  |             reg64 = c->icc_apr[GICV3_G1NS][2]; | 
					
						
							|  |  |  |             kvm_gicc_access(s, ICC_AP1R_EL1(2), ncpu, ®64, true); | 
					
						
							| 
									
										
											  
											
												hw/intc/arm_gicv3_kvm: silence the compiler warnings
When using -Wimplicit-fallthrough in our CFLAGS, the compiler showed warning:
hw/intc/arm_gicv3_kvm.c: In function ‘kvm_arm_gicv3_put’:
hw/intc/arm_gicv3_kvm.c:484:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
             kvm_gicc_access(s, ICC_AP0R_EL1(1), ncpu, ®64, true);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw/intc/arm_gicv3_kvm.c:485:9: note: here
         default:
         ^~~~~~~
hw/intc/arm_gicv3_kvm.c:495:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
             kvm_gicc_access(s, ICC_AP1R_EL1(2), ncpu, ®64, true);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw/intc/arm_gicv3_kvm.c:496:9: note: here
         case 6:
         ^~~~
hw/intc/arm_gicv3_kvm.c:498:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
             kvm_gicc_access(s, ICC_AP1R_EL1(1), ncpu, ®64, true);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw/intc/arm_gicv3_kvm.c:499:9: note: here
         default:
         ^~~~~~~
hw/intc/arm_gicv3_kvm.c: In function ‘kvm_arm_gicv3_get’:
hw/intc/arm_gicv3_kvm.c:634:37: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G0][2] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:635:9: note: here
         case 6:
         ^~~~
hw/intc/arm_gicv3_kvm.c:637:37: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G0][1] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:638:9: note: here
         default:
         ^~~~~~~
hw/intc/arm_gicv3_kvm.c:648:39: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G1NS][2] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:649:9: note: here
         case 6:
         ^~~~
hw/intc/arm_gicv3_kvm.c:651:39: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G1NS][1] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:652:9: note: here
         default:
         ^~~~~~~
Reported-by: Euler Robot <euler.robot@huawei.com>
Signed-off-by: Chen Qun <kuhn.chenqun@huawei.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-Id: <20201211152426.350966-7-thuth@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
											
										 
											2020-12-11 16:24:20 +01:00
										 |  |  |             /* fall through */ | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  |         case 6: | 
					
						
							|  |  |  |             reg64 = c->icc_apr[GICV3_G1NS][1]; | 
					
						
							|  |  |  |             kvm_gicc_access(s, ICC_AP1R_EL1(1), ncpu, ®64, true); | 
					
						
							| 
									
										
											  
											
												hw/intc/arm_gicv3_kvm: silence the compiler warnings
When using -Wimplicit-fallthrough in our CFLAGS, the compiler showed warning:
hw/intc/arm_gicv3_kvm.c: In function ‘kvm_arm_gicv3_put’:
hw/intc/arm_gicv3_kvm.c:484:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
             kvm_gicc_access(s, ICC_AP0R_EL1(1), ncpu, ®64, true);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw/intc/arm_gicv3_kvm.c:485:9: note: here
         default:
         ^~~~~~~
hw/intc/arm_gicv3_kvm.c:495:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
             kvm_gicc_access(s, ICC_AP1R_EL1(2), ncpu, ®64, true);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw/intc/arm_gicv3_kvm.c:496:9: note: here
         case 6:
         ^~~~
hw/intc/arm_gicv3_kvm.c:498:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
             kvm_gicc_access(s, ICC_AP1R_EL1(1), ncpu, ®64, true);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw/intc/arm_gicv3_kvm.c:499:9: note: here
         default:
         ^~~~~~~
hw/intc/arm_gicv3_kvm.c: In function ‘kvm_arm_gicv3_get’:
hw/intc/arm_gicv3_kvm.c:634:37: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G0][2] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:635:9: note: here
         case 6:
         ^~~~
hw/intc/arm_gicv3_kvm.c:637:37: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G0][1] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:638:9: note: here
         default:
         ^~~~~~~
hw/intc/arm_gicv3_kvm.c:648:39: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G1NS][2] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:649:9: note: here
         case 6:
         ^~~~
hw/intc/arm_gicv3_kvm.c:651:39: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G1NS][1] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:652:9: note: here
         default:
         ^~~~~~~
Reported-by: Euler Robot <euler.robot@huawei.com>
Signed-off-by: Chen Qun <kuhn.chenqun@huawei.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-Id: <20201211152426.350966-7-thuth@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
											
										 
											2020-12-11 16:24:20 +01:00
										 |  |  |             /* fall through */ | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  |         default: | 
					
						
							|  |  |  |             reg64 = c->icc_apr[GICV3_G1NS][0]; | 
					
						
							|  |  |  |             kvm_gicc_access(s, ICC_AP1R_EL1(0), ncpu, ®64, true); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-09-24 01:29:37 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void kvm_arm_gicv3_get(GICv3State *s) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  |     uint32_t regl, regh, reg; | 
					
						
							|  |  |  |     uint64_t reg64, redist_typer; | 
					
						
							|  |  |  |     int ncpu, i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     kvm_arm_gicv3_check(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     kvm_gicr_access(s, GICR_TYPER, 0, ®l, false); | 
					
						
							|  |  |  |     kvm_gicr_access(s, GICR_TYPER + 4, 0, ®h, false); | 
					
						
							|  |  |  |     redist_typer = ((uint64_t)regh << 32) | regl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     kvm_gicd_access(s, GICD_CTLR, ®, false); | 
					
						
							|  |  |  |     s->gicd_ctlr = reg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Redistributor state (one per CPU) */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (ncpu = 0; ncpu < s->num_cpu; ncpu++) { | 
					
						
							|  |  |  |         GICv3CPUState *c = &s->cpu[ncpu]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         kvm_gicr_access(s, GICR_CTLR, ncpu, ®, false); | 
					
						
							|  |  |  |         c->gicr_ctlr = reg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         kvm_gicr_access(s, GICR_STATUSR, ncpu, ®, false); | 
					
						
							|  |  |  |         c->gicr_statusr[GICV3_NS] = reg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         kvm_gicr_access(s, GICR_WAKER, ncpu, ®, false); | 
					
						
							|  |  |  |         c->gicr_waker = reg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         kvm_gicr_access(s, GICR_IGROUPR0, ncpu, ®, false); | 
					
						
							|  |  |  |         c->gicr_igroupr0 = reg; | 
					
						
							|  |  |  |         kvm_gicr_access(s, GICR_ISENABLER0, ncpu, ®, false); | 
					
						
							|  |  |  |         c->gicr_ienabler0 = reg; | 
					
						
							|  |  |  |         kvm_gicr_access(s, GICR_ICFGR1, ncpu, ®, false); | 
					
						
							|  |  |  |         c->edge_trigger = half_unshuffle32(reg >> 1) << 16; | 
					
						
							|  |  |  |         kvm_gic_line_level_access(s, 0, ncpu, ®, false); | 
					
						
							|  |  |  |         c->level = reg; | 
					
						
							|  |  |  |         kvm_gicr_access(s, GICR_ISPENDR0, ncpu, ®, false); | 
					
						
							|  |  |  |         c->gicr_ipendr0 = reg; | 
					
						
							|  |  |  |         kvm_gicr_access(s, GICR_ISACTIVER0, ncpu, ®, false); | 
					
						
							|  |  |  |         c->gicr_iactiver0 = reg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (i = 0; i < GIC_INTERNAL; i += 4) { | 
					
						
							|  |  |  |             kvm_gicr_access(s, GICR_IPRIORITYR + i, ncpu, ®, false); | 
					
						
							|  |  |  |             c->gicr_ipriorityr[i] = extract32(reg, 0, 8); | 
					
						
							|  |  |  |             c->gicr_ipriorityr[i + 1] = extract32(reg, 8, 8); | 
					
						
							|  |  |  |             c->gicr_ipriorityr[i + 2] = extract32(reg, 16, 8); | 
					
						
							|  |  |  |             c->gicr_ipriorityr[i + 3] = extract32(reg, 24, 8); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (redist_typer & GICR_TYPER_PLPIS) { | 
					
						
							|  |  |  |         for (ncpu = 0; ncpu < s->num_cpu; ncpu++) { | 
					
						
							|  |  |  |             GICv3CPUState *c = &s->cpu[ncpu]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             kvm_gicr_access(s, GICR_PROPBASER, ncpu, ®l, false); | 
					
						
							|  |  |  |             kvm_gicr_access(s, GICR_PROPBASER + 4, ncpu, ®h, false); | 
					
						
							|  |  |  |             c->gicr_propbaser = ((uint64_t)regh << 32) | regl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             kvm_gicr_access(s, GICR_PENDBASER, ncpu, ®l, false); | 
					
						
							|  |  |  |             kvm_gicr_access(s, GICR_PENDBASER + 4, ncpu, ®h, false); | 
					
						
							|  |  |  |             c->gicr_pendbaser = ((uint64_t)regh << 32) | regl; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Distributor state (shared between all CPUs */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     kvm_gicd_access(s, GICD_STATUSR, ®, false); | 
					
						
							|  |  |  |     s->gicd_statusr[GICV3_NS] = reg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* GICD_IGROUPRn -> s->group bitmap */ | 
					
						
							|  |  |  |     kvm_dist_getbmp(s, GICD_IGROUPR, s->group); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* GICD_ISENABLERn -> s->enabled bitmap */ | 
					
						
							|  |  |  |     kvm_dist_getbmp(s, GICD_ISENABLER, s->enabled); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Line level of irq */ | 
					
						
							|  |  |  |     kvm_gic_get_line_level_bmp(s, s->level); | 
					
						
							|  |  |  |     /* GICD_ISPENDRn -> s->pending bitmap */ | 
					
						
							|  |  |  |     kvm_dist_getbmp(s, GICD_ISPENDR, s->pending); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* GICD_ISACTIVERn -> s->active bitmap */ | 
					
						
							|  |  |  |     kvm_dist_getbmp(s, GICD_ISACTIVER, s->active); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* GICD_ICFGRn -> s->trigger bitmap */ | 
					
						
							|  |  |  |     kvm_dist_get_edge_trigger(s, GICD_ICFGR, s->edge_trigger); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* GICD_IPRIORITYRn -> s->gicd_ipriority[] */ | 
					
						
							|  |  |  |     kvm_dist_get_priority(s, GICD_IPRIORITYR, s->gicd_ipriority); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* GICD_IROUTERn -> s->gicd_irouter[irq] */ | 
					
						
							|  |  |  |     for (i = GIC_INTERNAL; i < s->num_irq; i++) { | 
					
						
							|  |  |  |         uint32_t offset; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         offset = GICD_IROUTER + (sizeof(uint32_t) * i); | 
					
						
							|  |  |  |         kvm_gicd_access(s, offset, ®l, false); | 
					
						
							|  |  |  |         offset = GICD_IROUTER + (sizeof(uint32_t) * i) + 4; | 
					
						
							|  |  |  |         kvm_gicd_access(s, offset, ®h, false); | 
					
						
							|  |  |  |         s->gicd_irouter[i] = ((uint64_t)regh << 32) | regl; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /*****************************************************************
 | 
					
						
							|  |  |  |      * CPU Interface(s) State | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (ncpu = 0; ncpu < s->num_cpu; ncpu++) { | 
					
						
							|  |  |  |         GICv3CPUState *c = &s->cpu[ncpu]; | 
					
						
							|  |  |  |         int num_pri_bits; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         kvm_gicc_access(s, ICC_SRE_EL1, ncpu, &c->icc_sre_el1, false); | 
					
						
							|  |  |  |         kvm_gicc_access(s, ICC_CTLR_EL1, ncpu, | 
					
						
							|  |  |  |                         &c->icc_ctlr_el1[GICV3_NS], false); | 
					
						
							|  |  |  |         kvm_gicc_access(s, ICC_IGRPEN0_EL1, ncpu, | 
					
						
							|  |  |  |                         &c->icc_igrpen[GICV3_G0], false); | 
					
						
							|  |  |  |         kvm_gicc_access(s, ICC_IGRPEN1_EL1, ncpu, | 
					
						
							|  |  |  |                         &c->icc_igrpen[GICV3_G1NS], false); | 
					
						
							|  |  |  |         kvm_gicc_access(s, ICC_PMR_EL1, ncpu, &c->icc_pmr_el1, false); | 
					
						
							|  |  |  |         kvm_gicc_access(s, ICC_BPR0_EL1, ncpu, &c->icc_bpr[GICV3_G0], false); | 
					
						
							|  |  |  |         kvm_gicc_access(s, ICC_BPR1_EL1, ncpu, &c->icc_bpr[GICV3_G1NS], false); | 
					
						
							|  |  |  |         num_pri_bits = ((c->icc_ctlr_el1[GICV3_NS] & | 
					
						
							|  |  |  |                         ICC_CTLR_EL1_PRIBITS_MASK) >> | 
					
						
							|  |  |  |                         ICC_CTLR_EL1_PRIBITS_SHIFT) + 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch (num_pri_bits) { | 
					
						
							|  |  |  |         case 7: | 
					
						
							|  |  |  |             kvm_gicc_access(s, ICC_AP0R_EL1(3), ncpu, ®64, false); | 
					
						
							|  |  |  |             c->icc_apr[GICV3_G0][3] = reg64; | 
					
						
							|  |  |  |             kvm_gicc_access(s, ICC_AP0R_EL1(2), ncpu, ®64, false); | 
					
						
							|  |  |  |             c->icc_apr[GICV3_G0][2] = reg64; | 
					
						
							| 
									
										
											  
											
												hw/intc/arm_gicv3_kvm: silence the compiler warnings
When using -Wimplicit-fallthrough in our CFLAGS, the compiler showed warning:
hw/intc/arm_gicv3_kvm.c: In function ‘kvm_arm_gicv3_put’:
hw/intc/arm_gicv3_kvm.c:484:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
             kvm_gicc_access(s, ICC_AP0R_EL1(1), ncpu, ®64, true);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw/intc/arm_gicv3_kvm.c:485:9: note: here
         default:
         ^~~~~~~
hw/intc/arm_gicv3_kvm.c:495:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
             kvm_gicc_access(s, ICC_AP1R_EL1(2), ncpu, ®64, true);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw/intc/arm_gicv3_kvm.c:496:9: note: here
         case 6:
         ^~~~
hw/intc/arm_gicv3_kvm.c:498:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
             kvm_gicc_access(s, ICC_AP1R_EL1(1), ncpu, ®64, true);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw/intc/arm_gicv3_kvm.c:499:9: note: here
         default:
         ^~~~~~~
hw/intc/arm_gicv3_kvm.c: In function ‘kvm_arm_gicv3_get’:
hw/intc/arm_gicv3_kvm.c:634:37: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G0][2] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:635:9: note: here
         case 6:
         ^~~~
hw/intc/arm_gicv3_kvm.c:637:37: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G0][1] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:638:9: note: here
         default:
         ^~~~~~~
hw/intc/arm_gicv3_kvm.c:648:39: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G1NS][2] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:649:9: note: here
         case 6:
         ^~~~
hw/intc/arm_gicv3_kvm.c:651:39: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G1NS][1] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:652:9: note: here
         default:
         ^~~~~~~
Reported-by: Euler Robot <euler.robot@huawei.com>
Signed-off-by: Chen Qun <kuhn.chenqun@huawei.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-Id: <20201211152426.350966-7-thuth@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
											
										 
											2020-12-11 16:24:20 +01:00
										 |  |  |             /* fall through */ | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  |         case 6: | 
					
						
							|  |  |  |             kvm_gicc_access(s, ICC_AP0R_EL1(1), ncpu, ®64, false); | 
					
						
							|  |  |  |             c->icc_apr[GICV3_G0][1] = reg64; | 
					
						
							| 
									
										
											  
											
												hw/intc/arm_gicv3_kvm: silence the compiler warnings
When using -Wimplicit-fallthrough in our CFLAGS, the compiler showed warning:
hw/intc/arm_gicv3_kvm.c: In function ‘kvm_arm_gicv3_put’:
hw/intc/arm_gicv3_kvm.c:484:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
             kvm_gicc_access(s, ICC_AP0R_EL1(1), ncpu, ®64, true);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw/intc/arm_gicv3_kvm.c:485:9: note: here
         default:
         ^~~~~~~
hw/intc/arm_gicv3_kvm.c:495:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
             kvm_gicc_access(s, ICC_AP1R_EL1(2), ncpu, ®64, true);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw/intc/arm_gicv3_kvm.c:496:9: note: here
         case 6:
         ^~~~
hw/intc/arm_gicv3_kvm.c:498:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
             kvm_gicc_access(s, ICC_AP1R_EL1(1), ncpu, ®64, true);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw/intc/arm_gicv3_kvm.c:499:9: note: here
         default:
         ^~~~~~~
hw/intc/arm_gicv3_kvm.c: In function ‘kvm_arm_gicv3_get’:
hw/intc/arm_gicv3_kvm.c:634:37: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G0][2] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:635:9: note: here
         case 6:
         ^~~~
hw/intc/arm_gicv3_kvm.c:637:37: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G0][1] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:638:9: note: here
         default:
         ^~~~~~~
hw/intc/arm_gicv3_kvm.c:648:39: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G1NS][2] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:649:9: note: here
         case 6:
         ^~~~
hw/intc/arm_gicv3_kvm.c:651:39: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G1NS][1] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:652:9: note: here
         default:
         ^~~~~~~
Reported-by: Euler Robot <euler.robot@huawei.com>
Signed-off-by: Chen Qun <kuhn.chenqun@huawei.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-Id: <20201211152426.350966-7-thuth@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
											
										 
											2020-12-11 16:24:20 +01:00
										 |  |  |             /* fall through */ | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  |         default: | 
					
						
							|  |  |  |             kvm_gicc_access(s, ICC_AP0R_EL1(0), ncpu, ®64, false); | 
					
						
							|  |  |  |             c->icc_apr[GICV3_G0][0] = reg64; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         switch (num_pri_bits) { | 
					
						
							|  |  |  |         case 7: | 
					
						
							|  |  |  |             kvm_gicc_access(s, ICC_AP1R_EL1(3), ncpu, ®64, false); | 
					
						
							|  |  |  |             c->icc_apr[GICV3_G1NS][3] = reg64; | 
					
						
							|  |  |  |             kvm_gicc_access(s, ICC_AP1R_EL1(2), ncpu, ®64, false); | 
					
						
							|  |  |  |             c->icc_apr[GICV3_G1NS][2] = reg64; | 
					
						
							| 
									
										
											  
											
												hw/intc/arm_gicv3_kvm: silence the compiler warnings
When using -Wimplicit-fallthrough in our CFLAGS, the compiler showed warning:
hw/intc/arm_gicv3_kvm.c: In function ‘kvm_arm_gicv3_put’:
hw/intc/arm_gicv3_kvm.c:484:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
             kvm_gicc_access(s, ICC_AP0R_EL1(1), ncpu, ®64, true);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw/intc/arm_gicv3_kvm.c:485:9: note: here
         default:
         ^~~~~~~
hw/intc/arm_gicv3_kvm.c:495:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
             kvm_gicc_access(s, ICC_AP1R_EL1(2), ncpu, ®64, true);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw/intc/arm_gicv3_kvm.c:496:9: note: here
         case 6:
         ^~~~
hw/intc/arm_gicv3_kvm.c:498:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
             kvm_gicc_access(s, ICC_AP1R_EL1(1), ncpu, ®64, true);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw/intc/arm_gicv3_kvm.c:499:9: note: here
         default:
         ^~~~~~~
hw/intc/arm_gicv3_kvm.c: In function ‘kvm_arm_gicv3_get’:
hw/intc/arm_gicv3_kvm.c:634:37: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G0][2] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:635:9: note: here
         case 6:
         ^~~~
hw/intc/arm_gicv3_kvm.c:637:37: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G0][1] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:638:9: note: here
         default:
         ^~~~~~~
hw/intc/arm_gicv3_kvm.c:648:39: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G1NS][2] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:649:9: note: here
         case 6:
         ^~~~
hw/intc/arm_gicv3_kvm.c:651:39: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G1NS][1] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:652:9: note: here
         default:
         ^~~~~~~
Reported-by: Euler Robot <euler.robot@huawei.com>
Signed-off-by: Chen Qun <kuhn.chenqun@huawei.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-Id: <20201211152426.350966-7-thuth@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
											
										 
											2020-12-11 16:24:20 +01:00
										 |  |  |             /* fall through */ | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  |         case 6: | 
					
						
							|  |  |  |             kvm_gicc_access(s, ICC_AP1R_EL1(1), ncpu, ®64, false); | 
					
						
							|  |  |  |             c->icc_apr[GICV3_G1NS][1] = reg64; | 
					
						
							| 
									
										
											  
											
												hw/intc/arm_gicv3_kvm: silence the compiler warnings
When using -Wimplicit-fallthrough in our CFLAGS, the compiler showed warning:
hw/intc/arm_gicv3_kvm.c: In function ‘kvm_arm_gicv3_put’:
hw/intc/arm_gicv3_kvm.c:484:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
             kvm_gicc_access(s, ICC_AP0R_EL1(1), ncpu, ®64, true);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw/intc/arm_gicv3_kvm.c:485:9: note: here
         default:
         ^~~~~~~
hw/intc/arm_gicv3_kvm.c:495:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
             kvm_gicc_access(s, ICC_AP1R_EL1(2), ncpu, ®64, true);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw/intc/arm_gicv3_kvm.c:496:9: note: here
         case 6:
         ^~~~
hw/intc/arm_gicv3_kvm.c:498:13: warning: this statement may fall through [-Wimplicit-fallthrough=]
             kvm_gicc_access(s, ICC_AP1R_EL1(1), ncpu, ®64, true);
             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hw/intc/arm_gicv3_kvm.c:499:9: note: here
         default:
         ^~~~~~~
hw/intc/arm_gicv3_kvm.c: In function ‘kvm_arm_gicv3_get’:
hw/intc/arm_gicv3_kvm.c:634:37: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G0][2] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:635:9: note: here
         case 6:
         ^~~~
hw/intc/arm_gicv3_kvm.c:637:37: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G0][1] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:638:9: note: here
         default:
         ^~~~~~~
hw/intc/arm_gicv3_kvm.c:648:39: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G1NS][2] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:649:9: note: here
         case 6:
         ^~~~
hw/intc/arm_gicv3_kvm.c:651:39: warning: this statement may fall through [-Wimplicit-fallthrough=]
             c->icc_apr[GICV3_G1NS][1] = reg64;
             ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
hw/intc/arm_gicv3_kvm.c:652:9: note: here
         default:
         ^~~~~~~
Reported-by: Euler Robot <euler.robot@huawei.com>
Signed-off-by: Chen Qun <kuhn.chenqun@huawei.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-Id: <20201211152426.350966-7-thuth@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
											
										 
											2020-12-11 16:24:20 +01:00
										 |  |  |             /* fall through */ | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  |         default: | 
					
						
							|  |  |  |             kvm_gicc_access(s, ICC_AP1R_EL1(0), ncpu, ®64, false); | 
					
						
							|  |  |  |             c->icc_apr[GICV3_G1NS][0] = reg64; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-09-24 01:29:37 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:13 +05:30
										 |  |  | static void arm_gicv3_icc_reset(CPUARMState *env, const ARMCPRegInfo *ri) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     GICv3State *s; | 
					
						
							|  |  |  |     GICv3CPUState *c; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     c = (GICv3CPUState *)env->gicv3state; | 
					
						
							|  |  |  |     s = c->gic; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     c->icc_pmr_el1 = 0; | 
					
						
							| 
									
										
										
										
											2022-05-12 16:14:54 +01:00
										 |  |  |     /*
 | 
					
						
							|  |  |  |      * Architecturally the reset value of the ICC_BPR registers | 
					
						
							|  |  |  |      * is UNKNOWN. We set them all to 0 here; when the kernel | 
					
						
							|  |  |  |      * uses these values to program the ICH_VMCR_EL2 fields that | 
					
						
							|  |  |  |      * determine the guest-visible ICC_BPR register values, the | 
					
						
							|  |  |  |      * hardware's "writing a value less than the minimum sets | 
					
						
							|  |  |  |      * the field to the minimum value" behaviour will result in | 
					
						
							|  |  |  |      * them effectively resetting to the correct minimum value | 
					
						
							|  |  |  |      * for the host GIC. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     c->icc_bpr[GICV3_G0] = 0; | 
					
						
							|  |  |  |     c->icc_bpr[GICV3_G1] = 0; | 
					
						
							|  |  |  |     c->icc_bpr[GICV3_G1NS] = 0; | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:13 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  |     c->icc_sre_el1 = 0x7; | 
					
						
							|  |  |  |     memset(c->icc_apr, 0, sizeof(c->icc_apr)); | 
					
						
							|  |  |  |     memset(c->icc_igrpen, 0, sizeof(c->icc_igrpen)); | 
					
						
							| 
									
										
										
										
											2017-03-28 19:20:40 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (s->migration_blocker) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* Initialize to actual HW supported configuration */ | 
					
						
							|  |  |  |     kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, | 
					
						
							| 
									
										
										
										
											2020-04-13 17:15:50 +08:00
										 |  |  |                       KVM_VGIC_ATTR(ICC_CTLR_EL1, c->gicr_typer), | 
					
						
							| 
									
										
										
										
											2017-06-13 14:57:00 +01:00
										 |  |  |                       &c->icc_ctlr_el1[GICV3_NS], false, &error_abort); | 
					
						
							| 
									
										
										
										
											2017-03-28 19:20:40 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     c->icc_ctlr_el1[GICV3_S] = c->icc_ctlr_el1[GICV3_NS]; | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:13 +05:30
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-24 01:29:37 +01:00
										 |  |  | static void kvm_arm_gicv3_reset(DeviceState *dev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     GICv3State *s = ARM_GICV3_COMMON(dev); | 
					
						
							|  |  |  |     KVMARMGICv3Class *kgc = KVM_ARM_GICV3_GET_CLASS(s); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     DPRINTF("Reset\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     kgc->parent_reset(dev); | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  |     if (s->migration_blocker) { | 
					
						
							|  |  |  |         DPRINTF("Cannot put kernel gic state, no kernel interface\n"); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-24 01:29:37 +01:00
										 |  |  |     kvm_arm_gicv3_put(s); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:13 +05:30
										 |  |  | /*
 | 
					
						
							|  |  |  |  * CPU interface registers of GIC needs to be reset on CPU reset. | 
					
						
							|  |  |  |  * For the calling arm_gicv3_icc_reset() on CPU reset, we register | 
					
						
							|  |  |  |  * below ARMCPRegInfo. As we reset the whole cpu interface under single | 
					
						
							|  |  |  |  * register reset, we define only one register of CPU interface instead | 
					
						
							|  |  |  |  * of defining all the registers. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static const ARMCPRegInfo gicv3_cpuif_reginfo[] = { | 
					
						
							|  |  |  |     { .name = "ICC_CTLR_EL1", .state = ARM_CP_STATE_BOTH, | 
					
						
							|  |  |  |       .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 12, .opc2 = 4, | 
					
						
							|  |  |  |       /*
 | 
					
						
							|  |  |  |        * If ARM_CP_NOP is used, resetfn is not called, | 
					
						
							|  |  |  |        * So ARM_CP_NO_RAW is appropriate type. | 
					
						
							|  |  |  |        */ | 
					
						
							|  |  |  |       .type = ARM_CP_NO_RAW, | 
					
						
							|  |  |  |       .access = PL1_RW, | 
					
						
							|  |  |  |       .readfn = arm_cp_read_zero, | 
					
						
							|  |  |  |       .writefn = arm_cp_write_ignore, | 
					
						
							|  |  |  |       /*
 | 
					
						
							|  |  |  |        * We hang the whole cpu interface reset routine off here | 
					
						
							|  |  |  |        * rather than parcelling it out into one little function | 
					
						
							|  |  |  |        * per register | 
					
						
							|  |  |  |        */ | 
					
						
							|  |  |  |       .resetfn = arm_gicv3_icc_reset, | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-13 14:57:00 +01:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * vm_change_state_handler - VM change state callback aiming at flushing | 
					
						
							|  |  |  |  * RDIST pending tables into guest RAM | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The tables get flushed to guest RAM whenever the VM gets stopped. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2021-01-11 16:20:20 +01:00
										 |  |  | static void vm_change_state_handler(void *opaque, bool running, | 
					
						
							| 
									
										
										
										
											2017-06-13 14:57:00 +01:00
										 |  |  |                                     RunState state) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     GICv3State *s = (GICv3State *)opaque; | 
					
						
							|  |  |  |     Error *err = NULL; | 
					
						
							|  |  |  |     int ret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (running) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ret = kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL, | 
					
						
							|  |  |  |                            KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES, | 
					
						
							|  |  |  |                            NULL, true, &err); | 
					
						
							|  |  |  |     if (err) { | 
					
						
							|  |  |  |         error_report_err(err); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (ret < 0 && ret != -EFAULT) { | 
					
						
							|  |  |  |         abort(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-24 01:29:37 +01:00
										 |  |  | static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     GICv3State *s = KVM_ARM_GICV3(dev); | 
					
						
							|  |  |  |     KVMARMGICv3Class *kgc = KVM_ARM_GICV3_GET_CLASS(s); | 
					
						
							| 
									
										
										
										
											2018-06-22 13:28:36 +01:00
										 |  |  |     bool multiple_redist_region_allowed; | 
					
						
							| 
									
										
										
										
											2015-09-24 01:29:37 +01:00
										 |  |  |     Error *local_err = NULL; | 
					
						
							| 
									
										
										
										
											2016-10-04 13:28:08 +01:00
										 |  |  |     int i; | 
					
						
							| 
									
										
										
										
											2015-09-24 01:29:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     DPRINTF("kvm_arm_gicv3_realize\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     kgc->parent_realize(dev, &local_err); | 
					
						
							|  |  |  |     if (local_err) { | 
					
						
							|  |  |  |         error_propagate(errp, local_err); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-08 15:15:47 +01:00
										 |  |  |     if (s->revision != 3) { | 
					
						
							|  |  |  |         error_setg(errp, "unsupported GIC revision %d for in-kernel GIC", | 
					
						
							|  |  |  |                    s->revision); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-24 01:29:37 +01:00
										 |  |  |     if (s->security_extn) { | 
					
						
							|  |  |  |         error_setg(errp, "the in-kernel VGICv3 does not implement the " | 
					
						
							|  |  |  |                    "security extensions"); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-30 16:08:40 +01:00
										 |  |  |     gicv3_init_irqs_and_mmio(s, kvm_arm_gicv3_set_irq, NULL); | 
					
						
							| 
									
										
										
										
											2015-09-24 01:29:37 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:13 +05:30
										 |  |  |     for (i = 0; i < s->num_cpu; i++) { | 
					
						
							|  |  |  |         ARMCPU *cpu = ARM_CPU(qemu_get_cpu(i)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         define_arm_cp_regs(cpu, gicv3_cpuif_reginfo); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-24 01:29:37 +01:00
										 |  |  |     /* Try to create the device via the device control API */ | 
					
						
							|  |  |  |     s->dev_fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_V3, false); | 
					
						
							|  |  |  |     if (s->dev_fd < 0) { | 
					
						
							|  |  |  |         error_setg_errno(errp, -s->dev_fd, "error creating in-kernel VGIC"); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-22 13:28:36 +01:00
										 |  |  |     multiple_redist_region_allowed = | 
					
						
							|  |  |  |         kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ADDR, | 
					
						
							|  |  |  |                               KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!multiple_redist_region_allowed && s->nb_redist_regions > 1) { | 
					
						
							|  |  |  |         error_setg(errp, "Multiple VGICv3 redistributor regions are not " | 
					
						
							|  |  |  |                    "supported by this host kernel"); | 
					
						
							|  |  |  |         error_append_hint(errp, "A maximum of %d VCPUs can be used", | 
					
						
							|  |  |  |                           s->redist_region_count[0]); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-24 01:29:37 +01:00
										 |  |  |     kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, | 
					
						
							| 
									
										
										
										
											2017-06-13 14:57:00 +01:00
										 |  |  |                       0, &s->num_irq, true, &error_abort); | 
					
						
							| 
									
										
										
										
											2015-09-24 01:29:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Tell the kernel to complete VGIC initialization now */ | 
					
						
							|  |  |  |     kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL, | 
					
						
							| 
									
										
										
										
											2017-06-13 14:57:00 +01:00
										 |  |  |                       KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true, &error_abort); | 
					
						
							| 
									
										
										
										
											2015-09-24 01:29:37 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     kvm_arm_register_device(&s->iomem_dist, -1, KVM_DEV_ARM_VGIC_GRP_ADDR, | 
					
						
							| 
									
										
										
										
											2018-06-22 13:28:35 +01:00
										 |  |  |                             KVM_VGIC_V3_ADDR_TYPE_DIST, s->dev_fd, 0); | 
					
						
							| 
									
										
										
										
											2018-06-22 13:28:36 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (!multiple_redist_region_allowed) { | 
					
						
							| 
									
										
										
										
											2021-09-30 16:08:42 +01:00
										 |  |  |         kvm_arm_register_device(&s->redist_regions[0].iomem, -1, | 
					
						
							| 
									
										
										
										
											2018-06-22 13:28:36 +01:00
										 |  |  |                                 KVM_DEV_ARM_VGIC_GRP_ADDR, | 
					
						
							|  |  |  |                                 KVM_VGIC_V3_ADDR_TYPE_REDIST, s->dev_fd, 0); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         /* we register regions in reverse order as "devices" are inserted at
 | 
					
						
							|  |  |  |          * the head of a QSLIST and the list is then popped from the head | 
					
						
							|  |  |  |          * onwards by kvm_arm_machine_init_done() | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         for (i = s->nb_redist_regions - 1; i >= 0; i--) { | 
					
						
							|  |  |  |             /* Address mask made of the rdist region index and count */ | 
					
						
							|  |  |  |             uint64_t addr_ormask = | 
					
						
							|  |  |  |                         i | ((uint64_t)s->redist_region_count[i] << 52); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-30 16:08:42 +01:00
										 |  |  |             kvm_arm_register_device(&s->redist_regions[i].iomem, -1, | 
					
						
							| 
									
										
										
										
											2018-06-22 13:28:36 +01:00
										 |  |  |                                     KVM_DEV_ARM_VGIC_GRP_ADDR, | 
					
						
							|  |  |  |                                     KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, | 
					
						
							|  |  |  |                                     s->dev_fd, addr_ormask); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-06-17 15:23:46 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-04 13:28:08 +01:00
										 |  |  |     if (kvm_has_gsi_routing()) { | 
					
						
							|  |  |  |         /* set up irq routing */ | 
					
						
							|  |  |  |         for (i = 0; i < s->num_irq - GIC_INTERNAL; ++i) { | 
					
						
							|  |  |  |             kvm_irqchip_add_irq_route(kvm_state, i, 0, i); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         kvm_gsi_routing_allowed = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         kvm_irqchip_commit_routes(kvm_state); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  |     if (!kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS, | 
					
						
							|  |  |  |                                GICD_CTLR)) { | 
					
						
							|  |  |  |         error_setg(&s->migration_blocker, "This operating system kernel does " | 
					
						
							|  |  |  |                                           "not support vGICv3 migration"); | 
					
						
							| 
									
										
											  
											
												error: Avoid error_propagate() after migrate_add_blocker()
When migrate_add_blocker(blocker, &errp) is followed by
error_propagate(errp, err), we can often just as well do
migrate_add_blocker(..., errp).
Do that with this Coccinelle script:
    @@
    expression blocker, err, errp;
    expression ret;
    @@
    -    ret = migrate_add_blocker(blocker, &err);
    -    if (err) {
    +    ret = migrate_add_blocker(blocker, errp);
    +    if (ret < 0) {
             ... when != err;
    -        error_propagate(errp, err);
             ...
         }
    @@
    expression blocker, err, errp;
    @@
    -    migrate_add_blocker(blocker, &err);
    -    if (err) {
    +    if (migrate_add_blocker(blocker, errp) < 0) {
             ... when != err;
    -        error_propagate(errp, err);
             ...
         }
Double-check @err is not used afterwards.  Dereferencing it would be
use after free, but checking whether it's null would be legitimate.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Message-Id: <20200707160613.848843-43-armbru@redhat.com>
											
										 
											2020-07-07 18:06:10 +02:00
										 |  |  |         if (migrate_add_blocker(s->migration_blocker, errp) < 0) { | 
					
						
							| 
									
										
										
										
											2017-02-23 17:21:11 +05:30
										 |  |  |             error_free(s->migration_blocker); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-06-13 14:57:00 +01:00
										 |  |  |     if (kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL, | 
					
						
							|  |  |  |                               KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES)) { | 
					
						
							|  |  |  |         qemu_add_vm_change_state_handler(vm_change_state_handler, s); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2015-09-24 01:29:37 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void kvm_arm_gicv3_class_init(ObjectClass *klass, void *data) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     DeviceClass *dc = DEVICE_CLASS(klass); | 
					
						
							|  |  |  |     ARMGICv3CommonClass *agcc = ARM_GICV3_COMMON_CLASS(klass); | 
					
						
							|  |  |  |     KVMARMGICv3Class *kgc = KVM_ARM_GICV3_CLASS(klass); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     agcc->pre_save = kvm_arm_gicv3_get; | 
					
						
							|  |  |  |     agcc->post_load = kvm_arm_gicv3_put; | 
					
						
							| 
									
										
										
										
											2018-01-13 23:04:12 -03:00
										 |  |  |     device_class_set_parent_realize(dc, kvm_arm_gicv3_realize, | 
					
						
							|  |  |  |                                     &kgc->parent_realize); | 
					
						
							|  |  |  |     device_class_set_parent_reset(dc, kvm_arm_gicv3_reset, &kgc->parent_reset); | 
					
						
							| 
									
										
										
										
											2015-09-24 01:29:37 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const TypeInfo kvm_arm_gicv3_info = { | 
					
						
							|  |  |  |     .name = TYPE_KVM_ARM_GICV3, | 
					
						
							|  |  |  |     .parent = TYPE_ARM_GICV3_COMMON, | 
					
						
							|  |  |  |     .instance_size = sizeof(GICv3State), | 
					
						
							|  |  |  |     .class_init = kvm_arm_gicv3_class_init, | 
					
						
							|  |  |  |     .class_size = sizeof(KVMARMGICv3Class), | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void kvm_arm_gicv3_register_types(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     type_register_static(&kvm_arm_gicv3_info); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type_init(kvm_arm_gicv3_register_types) |