gic_v3_distributor.cc (14230:94c9f25c59ae) | gic_v3_distributor.cc (14231:222f6512335e) |
---|---|
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 | 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(); | 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; | 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); |
|
666 } 667 } 668 | 667 } 668 } 669 |
669 updateAndInformCPUInterfaces(); | 670 update(); |
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); | 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); |
950 updateAndInformCPUInterfaces(); | 951 update(); |
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; | 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; |
959 updateAndInformCPUInterfaces(); | 960 clearIrqCpuInterface(int_id); 961 962 update(); |
960} 961 | 963} 964 |
962void 963Gicv3Distributor::updateAndInformCPUInterfaces() | 965Gicv3CPUInterface* 966Gicv3Distributor::route(uint32_t int_id) |
964{ | 967{ |
965 update(); | 968 IROUTER affinity_routing = irqAffinityRouting[int_id]; 969 Gicv3Redistributor * target_redistributor = nullptr; |
966 | 970 |
967 for (int i = 0; i < gic->getSystem()->numContexts(); i++) { 968 gic->getCPUInterface(i)->update(); | 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); |
969 } | 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 } |
|
970} 971 972void | 1000} 1001 1002void |
973Gicv3Distributor::fullUpdate() | 1003Gicv3Distributor::clearIrqCpuInterface(uint32_t int_id) |
974{ | 1004{ |
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 } | 1005 auto cpu_interface = route(int_id); 1006 if (cpu_interface) 1007 cpu_interface->hppi.prio = 0xff; |
986} 987 988void 989Gicv3Distributor::update() 990{ | 1008} 1009 1010void 1011Gicv3Distributor::update() 1012{ |
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) { | 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) { |
1001 IROUTER affinity_routing = irqAffinityRouting[int_id]; 1002 Gicv3Redistributor * target_redistributor = nullptr; | |
1003 | 1021 |
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); | 1022 // Find the cpu interface where to route the interrupt 1023 Gicv3CPUInterface *target_cpu_interface = route(int_id); |
1009 | 1024 |
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 } | 1025 // Invalid routing 1026 if (!target_cpu_interface) continue; |
1024 | 1027 |
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) || | 1028 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)) { | 1029 (irqPriority[int_id] == target_cpu_interface->hppi.prio && 1030 int_id < target_cpu_interface->hppi.intid)) { |
1031 |
|
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; | 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; |
1045 new_hppi[target_cpu] = true; | |
1046 } 1047 } 1048 } 1049 | 1035 } 1036 } 1037 } 1038 |
1039 // Update all redistributors |
|
1050 for (int i = 0; i < gic->getSystem()->numContexts(); i++) { | 1040 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 } | 1041 gic->getRedistributor(i)->update(); |
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 --- | 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 --- |