1// Copyright 2018 The Fuchsia Authors 2// 3// Use of this source code is governed by a MIT-style 4// license that can be found in the LICENSE file or at 5// https://opensource.org/licenses/MIT 6 7#include <dev/interrupt/arm_gic_hw_interface.h> 8#include <vm/pmm.h> 9#include <arch/arm64/hypervisor/gic/gicv2.h> 10#include <dev/interrupt/arm_gicv2_regs.h> 11 12// Representation of GICH registers. For details please refer to ARM Generic Interrupt 13// Controller Architecture Specification Version 2, 5.3 GIC virtual interface control 14// registers. 15typedef struct Gich { 16 uint32_t hcr; 17 uint32_t vtr; 18 uint32_t vmcr; 19 uint32_t reserved0; 20 uint32_t misr; 21 uint32_t reserved1[3]; 22 uint64_t eisr; 23 uint32_t reserved2[2]; 24 uint64_t elrsr; 25 uint32_t reserved3[46]; 26 uint32_t apr; 27 uint32_t reserved4[3]; 28 uint32_t lr[64]; 29} __attribute__((__packed__)) Gich; 30 31static_assert(__offsetof(Gich, hcr) == 0x00, ""); 32static_assert(__offsetof(Gich, vtr) == 0x04, ""); 33static_assert(__offsetof(Gich, vmcr) == 0x08, ""); 34static_assert(__offsetof(Gich, misr) == 0x10, ""); 35static_assert(__offsetof(Gich, eisr) == 0x20, ""); 36static_assert(__offsetof(Gich, elrsr) == 0x30, ""); 37static_assert(__offsetof(Gich, apr) == 0xf0, ""); 38static_assert(__offsetof(Gich, lr) == 0x100, ""); 39 40static volatile Gich* gich = NULL; 41 42static uint32_t gicv2_read_gich_hcr() { 43 return gich->hcr; 44} 45 46static void gicv2_write_gich_hcr(uint32_t val) { 47 gich->hcr = val; 48} 49 50static uint32_t gicv2_read_gich_vtr() { 51 return gich->vtr; 52} 53 54static uint32_t gicv2_default_gich_vmcr() { 55 return GICH_VMCR_VPMR_MASK | GICH_VMCR_VENG0; 56} 57 58static uint32_t gicv2_read_gich_vmcr() { 59 return gich->vmcr; 60} 61 62static void gicv2_write_gich_vmcr(uint32_t val) { 63 gich->vmcr = val; 64} 65 66static uint32_t gicv2_read_gich_misr() { 67 return gich->misr; 68} 69 70static uint64_t gicv2_read_gich_elrsr() { 71 return gich->elrsr; 72} 73 74static uint32_t gicv2_read_gich_apr() { 75 return gich->apr; 76} 77 78static void gicv2_write_gich_apr(uint32_t val) { 79 gich->apr = val; 80} 81 82static uint64_t gicv2_read_gich_lr(uint32_t idx) { 83 return gich->lr[idx]; 84} 85 86static void gicv2_write_gich_lr(uint32_t idx, uint64_t val) { 87 gich->lr[idx] = static_cast<uint32_t>(val); 88} 89 90static zx_status_t gicv2_get_gicv(paddr_t* gicv_paddr) { 91 // Check for presence of GICv2 virtualisation extensions. 92 if (GICV_OFFSET == 0) 93 return ZX_ERR_NOT_SUPPORTED; 94 *gicv_paddr = vaddr_to_paddr(reinterpret_cast<void*>(GICV_ADDRESS)); 95 return ZX_OK; 96} 97 98static uint64_t gicv2_get_lr_from_vector(uint32_t vector) { 99 return (vector & GICH_LR_VIRTUAL_ID_MASK) | GICH_LR_PENDING; 100} 101 102static uint32_t gicv2_get_vector_from_lr(uint64_t lr) { 103 return lr & GICH_LR_VIRTUAL_ID_MASK; 104} 105 106static uint32_t gicv2_get_num_lrs() { 107 return (gicv2_read_gich_vtr() & GICH_VTR_LIST_REGS_MASK) + 1; 108} 109 110static const struct arm_gic_hw_interface_ops gic_hw_register_ops = { 111 .read_gich_hcr = gicv2_read_gich_hcr, 112 .write_gich_hcr = gicv2_write_gich_hcr, 113 .read_gich_vtr = gicv2_read_gich_vtr, 114 .default_gich_vmcr = gicv2_default_gich_vmcr, 115 .read_gich_vmcr = gicv2_read_gich_vmcr, 116 .write_gich_vmcr = gicv2_write_gich_vmcr, 117 .read_gich_misr = gicv2_read_gich_misr, 118 .read_gich_elrsr = gicv2_read_gich_elrsr, 119 .read_gich_apr = gicv2_read_gich_apr, 120 .write_gich_apr = gicv2_write_gich_apr, 121 .read_gich_lr = gicv2_read_gich_lr, 122 .write_gich_lr = gicv2_write_gich_lr, 123 .get_gicv = gicv2_get_gicv, 124 .get_lr_from_vector = gicv2_get_lr_from_vector, 125 .get_vector_from_lr = gicv2_get_vector_from_lr, 126 .get_num_lrs = gicv2_get_num_lrs, 127}; 128 129void gicv2_hw_interface_register() { 130 // Populate GICH 131 gich = reinterpret_cast<volatile Gich*>(GICH_ADDRESS); 132 arm_gic_hw_interface_register(&gic_hw_register_ops); 133} 134