Deleted Added
sdiff udiff text old ( 14230:94c9f25c59ae ) new ( 14231:222f6512335e )
full compact
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 updateAndInformCPUInterfaces();
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 }
667 }
668
669 updateAndInformCPUInterfaces();
670 return;
671 } else if (GICD_ISACTIVER.contains(addr)) {
672 // Interrupt Set-Active Registers
673 int first_intid = (addr - GICD_ISACTIVER.start()) * 8;
674
675 if (isNotSPI(first_intid)) {
676 return;
677 }

--- 264 unchanged lines hidden (view full) ---

942void
943Gicv3Distributor::sendInt(uint32_t int_id)
944{
945 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
946 panic_if(int_id > itLines, "Invalid SPI!");
947 irqPending[int_id] = true;
948 DPRINTF(GIC, "Gicv3Distributor::sendInt(): "
949 "int_id %d (SPI) pending bit set\n", int_id);
950 updateAndInformCPUInterfaces();
951}
952
953void
954Gicv3Distributor::deassertSPI(uint32_t int_id)
955{
956 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
957 panic_if(int_id > itLines, "Invalid SPI!");
958 irqPending[int_id] = false;
959 updateAndInformCPUInterfaces();
960}
961
962void
963Gicv3Distributor::updateAndInformCPUInterfaces()
964{
965 update();
966
967 for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
968 gic->getCPUInterface(i)->update();
969 }
970}
971
972void
973Gicv3Distributor::fullUpdate()
974{
975 for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
976 Gicv3CPUInterface * cpu_interface_i = gic->getCPUInterface(i);
977 cpu_interface_i->hppi.prio = 0xff;
978 }
979
980 update();
981
982 for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
983 Gicv3Redistributor * redistributor_i = gic->getRedistributor(i);
984 redistributor_i->update();
985 }
986}
987
988void
989Gicv3Distributor::update()
990{
991 std::vector<bool> new_hppi(gic->getSystem()->numContexts(), false);
992
993 // Find the highest priority pending SPI
994 for (int int_id = Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id < itLines;
995 int_id++) {
996 Gicv3::GroupId int_group = getIntGroup(int_id);
997 bool group_enabled = groupEnabled(int_group);
998
999 if (irqPending[int_id] && irqEnabled[int_id] &&
1000 !irqActive[int_id] && group_enabled) {
1001 IROUTER affinity_routing = irqAffinityRouting[int_id];
1002 Gicv3Redistributor * target_redistributor = nullptr;
1003
1004 if (affinity_routing.IRM) {
1005 // Interrupts routed to any PE defined as a participating node
1006 for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
1007 Gicv3Redistributor * redistributor_i =
1008 gic->getRedistributor(i);
1009
1010 if (redistributor_i->
1011 canBeSelectedFor1toNInterrupt(int_group)) {
1012 target_redistributor = redistributor_i;
1013 break;
1014 }
1015 }
1016 } else {
1017 uint32_t affinity = (affinity_routing.Aff3 << 24) |
1018 (affinity_routing.Aff3 << 16) |
1019 (affinity_routing.Aff1 << 8) |
1020 (affinity_routing.Aff0 << 0);
1021 target_redistributor =
1022 gic->getRedistributorByAffinity(affinity);
1023 }
1024
1025 if (!target_redistributor) {
1026 // Interrrupts targeting not present cpus must remain pending
1027 return;
1028 }
1029
1030 Gicv3CPUInterface * target_cpu_interface =
1031 target_redistributor->getCPUInterface();
1032 uint32_t target_cpu = target_redistributor->cpuId;
1033
1034 if ((irqPriority[int_id] < target_cpu_interface->hppi.prio) ||
1035 /*
1036 * Multiple pending ints with same priority.
1037 * Implementation choice which one to signal.
1038 * Our implementation selects the one with the lower id.
1039 */
1040 (irqPriority[int_id] == target_cpu_interface->hppi.prio &&
1041 int_id < target_cpu_interface->hppi.intid)) {
1042 target_cpu_interface->hppi.intid = int_id;
1043 target_cpu_interface->hppi.prio = irqPriority[int_id];
1044 target_cpu_interface->hppi.group = int_group;
1045 new_hppi[target_cpu] = true;
1046 }
1047 }
1048 }
1049
1050 for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
1051 Gicv3Redistributor * redistributor_i = gic->getRedistributor(i);
1052 Gicv3CPUInterface * cpu_interface_i =
1053 redistributor_i->getCPUInterface();
1054
1055 if (!new_hppi[i] && cpu_interface_i->hppi.prio != 0xff &&
1056 cpu_interface_i->hppi.intid >= (Gicv3::SGI_MAX + Gicv3::PPI_MAX) &&
1057 cpu_interface_i->hppi.intid < Gicv3::INTID_SECURE) {
1058 fullUpdate();
1059 }
1060 }
1061}
1062
1063Gicv3::IntStatus
1064Gicv3Distributor::intStatus(uint32_t int_id) const
1065{
1066 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
1067 panic_if(int_id > itLines, "Invalid SPI!");

--- 91 unchanged lines hidden ---