1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (C) 2018 Alexandru Elisei <alexandru.elisei@gmail.com> 5 * Copyright (C) 2020-2022 Andrew Turner 6 * Copyright (C) 2023 Arm Ltd 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #ifndef _VGIC_INTERNAL_H_ 31 #define _VGIC_INTERNAL_H_ 32 33 struct vgic_v3_irq { 34 /* List of IRQs that are active or pending */ 35 TAILQ_ENTRY(vgic_v3_irq) act_pend_list; 36 struct mtx irq_spinmtx; 37 uint64_t mpidr; 38 int target_vcpu; 39 uint32_t irq; 40 bool active; 41 bool pending; 42 bool enabled; 43 bool level; 44 bool on_aplist; 45 uint8_t priority; 46 uint8_t config; 47 #define VGIC_CONFIG_MASK 0x2 48 #define VGIC_CONFIG_LEVEL 0x0 49 #define VGIC_CONFIG_EDGE 0x2 50 }; 51 52 /* Global data not needed by EL2 */ 53 struct vgic_v3 { 54 struct mtx dist_mtx; 55 uint64_t dist_start; 56 size_t dist_end; 57 58 uint64_t redist_start; 59 size_t redist_end; 60 61 uint32_t gicd_ctlr; /* Distributor Control Register */ 62 63 struct vgic_v3_irq *irqs; 64 }; 65 66 /* Per-CPU data not needed by EL2 */ 67 struct vgic_v3_cpu { 68 /* 69 * We need a mutex for accessing the list registers because they are 70 * modified asynchronously by the virtual timer. 71 * 72 * Note that the mutex *MUST* be a spin mutex because an interrupt can 73 * be injected by a callout callback function, thereby modifying the 74 * list registers from a context where sleeping is forbidden. 75 */ 76 struct mtx lr_mtx; 77 78 struct vgic_v3_irq *private_irqs; 79 TAILQ_HEAD(, vgic_v3_irq) irq_act_pend; 80 u_int ich_lr_used; 81 }; 82 83 typedef void (register_read)(struct hypctx *, u_int, uint64_t *, void *); 84 typedef void (register_write)(struct hypctx *, u_int, u_int, u_int, 85 uint64_t, void *); 86 87 register_read vgic_zero_read; 88 register_write vgic_ignore_write; 89 90 #define VGIC_8_BIT (1 << 0) 91 /* (1 << 1) is reserved for 16 bit accesses */ 92 #define VGIC_32_BIT (1 << 2) 93 #define VGIC_64_BIT (1 << 3) 94 95 struct vgic_register { 96 u_int start; /* Start within a memory region */ 97 u_int end; 98 u_int size; 99 u_int flags; 100 register_read *read; 101 register_write *write; 102 }; 103 104 #define VGIC_REGISTER_RANGE(reg_start, reg_end, reg_size, reg_flags, readf, \ 105 writef) \ 106 { \ 107 .start = (reg_start), \ 108 .end = (reg_end), \ 109 .size = (reg_size), \ 110 .flags = (reg_flags), \ 111 .read = (readf), \ 112 .write = (writef), \ 113 } 114 115 #define VGIC_REGISTER_RANGE_RAZ_WI(reg_start, reg_end, reg_size, reg_flags) \ 116 VGIC_REGISTER_RANGE(reg_start, reg_end, reg_size, reg_flags, \ 117 vgic_zero_read, vgic_ignore_write) 118 119 #define VGIC_REGISTER(start_addr, reg_size, reg_flags, readf, writef) \ 120 VGIC_REGISTER_RANGE(start_addr, (start_addr) + (reg_size), \ 121 reg_size, reg_flags, readf, writef) 122 123 #define VGIC_REGISTER_RAZ_WI(start_addr, reg_size, reg_flags) \ 124 VGIC_REGISTER_RANGE_RAZ_WI(start_addr, \ 125 (start_addr) + (reg_size), reg_size, reg_flags) 126 127 bool vgic_register_read(struct hypctx *, struct vgic_register *, u_int, u_int, 128 u_int, uint64_t *, void *); 129 bool vgic_register_write(struct hypctx *, struct vgic_register *, u_int, u_int, 130 u_int, uint64_t, void *); 131 132 #endif /* _VGIC_INTERNAL_H_ */ 133