1/* 2 * Copyright (c) 2019 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software --- 624 unchanged lines hidden (view full) --- 633 634 if (pending) { 635 DPRINTF(GIC, "Gicv3Distributor::write() (GICD_ISPENDR): " 636 "int_id %d (SPI) pending bit set\n", int_id); 637 irqPending[int_id] = true; 638 } 639 } 640 |
641 update(); |
642 return; 643 } else if (GICD_ICPENDR.contains(addr)) { 644 // Interrupt Clear-Pending Registers 645 int first_intid = (addr - GICD_ICPENDR.start()) * 8; 646 647 if (isNotSPI(first_intid)) { 648 return; 649 } --- 8 unchanged lines hidden (view full) --- 658 continue; 659 } 660 } 661 662 bool clear = data & (1 << i) ? 1 : 0; 663 664 if (clear) { 665 irqPending[int_id] = false; |
666 clearIrqCpuInterface(int_id); |
667 } 668 } 669 |
670 update(); |
671 return; 672 } else if (GICD_ISACTIVER.contains(addr)) { 673 // Interrupt Set-Active Registers 674 int first_intid = (addr - GICD_ISACTIVER.start()) * 8; 675 676 if (isNotSPI(first_intid)) { 677 return; 678 } --- 264 unchanged lines hidden (view full) --- 943void 944Gicv3Distributor::sendInt(uint32_t int_id) 945{ 946 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 947 panic_if(int_id > itLines, "Invalid SPI!"); 948 irqPending[int_id] = true; 949 DPRINTF(GIC, "Gicv3Distributor::sendInt(): " 950 "int_id %d (SPI) pending bit set\n", int_id); |
951 update(); |
952} 953 954void 955Gicv3Distributor::deassertSPI(uint32_t int_id) 956{ 957 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 958 panic_if(int_id > itLines, "Invalid SPI!"); 959 irqPending[int_id] = false; |
960 clearIrqCpuInterface(int_id); 961 962 update(); |
963} 964 |
965Gicv3CPUInterface* 966Gicv3Distributor::route(uint32_t int_id) |
967{ |
968 IROUTER affinity_routing = irqAffinityRouting[int_id]; 969 Gicv3Redistributor * target_redistributor = nullptr; |
970 |
971 const Gicv3::GroupId int_group = getIntGroup(int_id); 972 973 if (affinity_routing.IRM) { 974 // Interrupts routed to any PE defined as a participating node 975 for (int i = 0; i < gic->getSystem()->numContexts(); i++) { 976 Gicv3Redistributor * redistributor_i = 977 gic->getRedistributor(i); 978 979 if (redistributor_i-> 980 canBeSelectedFor1toNInterrupt(int_group)) { 981 target_redistributor = redistributor_i; 982 break; 983 } 984 } 985 } else { 986 uint32_t affinity = (affinity_routing.Aff3 << 24) | 987 (affinity_routing.Aff2 << 16) | 988 (affinity_routing.Aff1 << 8) | 989 (affinity_routing.Aff0 << 0); 990 target_redistributor = 991 gic->getRedistributorByAffinity(affinity); |
992 } |
993 994 if (!target_redistributor) { 995 // Interrrupts targeting not present cpus must remain pending 996 return nullptr; 997 } else { 998 return target_redistributor->getCPUInterface(); 999 } |
1000} 1001 1002void |
1003Gicv3Distributor::clearIrqCpuInterface(uint32_t int_id) |
1004{ |
1005 auto cpu_interface = route(int_id); 1006 if (cpu_interface) 1007 cpu_interface->hppi.prio = 0xff; |
1008} 1009 1010void 1011Gicv3Distributor::update() 1012{ |
1013 // Find the highest priority pending SPI 1014 for (int int_id = Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id < itLines; 1015 int_id++) { 1016 Gicv3::GroupId int_group = getIntGroup(int_id); 1017 bool group_enabled = groupEnabled(int_group); 1018 1019 if (irqPending[int_id] && irqEnabled[int_id] && 1020 !irqActive[int_id] && group_enabled) { |
1021 |
1022 // Find the cpu interface where to route the interrupt 1023 Gicv3CPUInterface *target_cpu_interface = route(int_id); |
1024 |
1025 // Invalid routing 1026 if (!target_cpu_interface) continue; |
1027 |
1028 if ((irqPriority[int_id] < target_cpu_interface->hppi.prio) || |
1029 (irqPriority[int_id] == target_cpu_interface->hppi.prio && 1030 int_id < target_cpu_interface->hppi.intid)) { |
1031 |
1032 target_cpu_interface->hppi.intid = int_id; 1033 target_cpu_interface->hppi.prio = irqPriority[int_id]; 1034 target_cpu_interface->hppi.group = int_group; |
1035 } 1036 } 1037 } 1038 |
1039 // Update all redistributors |
1040 for (int i = 0; i < gic->getSystem()->numContexts(); i++) { |
1041 gic->getRedistributor(i)->update(); |
1042 } 1043} 1044 1045Gicv3::IntStatus 1046Gicv3Distributor::intStatus(uint32_t int_id) const 1047{ 1048 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 1049 panic_if(int_id > itLines, "Invalid SPI!"); --- 91 unchanged lines hidden --- |