1/* 2 * Copyright (c) 2018 Metempsy Technology Consulting 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer; --- 20 unchanged lines hidden (view full) --- 29 */ 30 31#include "dev/arm/gic_v3_redistributor.hh" 32 33#include "arch/arm/utility.hh" 34#include "debug/GIC.hh" 35#include "dev/arm/gic_v3_cpu_interface.hh" 36#include "dev/arm/gic_v3_distributor.hh" |
37#include "mem/fs_translating_port_proxy.hh" |
38 39const AddrRange Gicv3Redistributor::GICR_IPRIORITYR(SGI_base + 0x0400, 40 SGI_base + 0x041f); 41 42Gicv3Redistributor::Gicv3Redistributor(Gicv3 * gic, uint32_t cpu_id) 43 : gic(gic), 44 distributor(nullptr), 45 cpuInterface(nullptr), --- 41 unchanged lines hidden (view full) --- 87 irqConfig[int_id] = Gicv3::INT_EDGE_TRIGGERED; 88 } 89 90 std::fill(irqGrpmod.begin(), irqGrpmod.end(), 0); 91 std::fill(irqNsacr.begin(), irqNsacr.end(), 0); 92 DPG1S = false; 93 DPG1NS = false; 94 DPG0 = false; |
95 EnableLPIs = false; 96 lpiConfigurationTablePtr = 0; 97 lpiIDBits = 0; 98 lpiPendingTablePtr = 0; |
99} 100 101uint64_t 102Gicv3Redistributor::read(Addr addr, size_t size, bool is_secure_access) 103{ 104 if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers 105 uint64_t value = 0; 106 int first_intid = addr - GICR_IPRIORITYR.start(); --- 28 unchanged lines hidden (view full) --- 135 if (DPG1NS) { 136 value |= GICR_CTLR_DPG1NS; 137 } 138 139 if (DPG0) { 140 value |= GICR_CTLR_DPG0; 141 } 142 |
143 if (EnableLPIs) { 144 value |= GICR_CTLR_ENABLE_LPIS; 145 } 146 |
147 return value; 148 } 149 150 case GICR_IIDR: // Implementer Identification Register 151 //return 0x43b; // r0p0 GIC-500 152 return 0; 153 154 case GICR_TYPER: { // Type Register --- 5 unchanged lines hidden (view full) --- 160 * LPI Configuration table) 161 * Processor_Number [23:8] == X 162 * (A unique identifier for the PE) 163 * DPGS [5] == 1 164 * (GICR_CTLR.DPG* bits are supported) 165 * Last [4] == X 166 * (This Redistributor is the highest-numbered Redistributor in 167 * a series of contiguous Redistributor pages) |
168 * DirectLPI [3] == 1 169 * (direct injection of LPIs supported) |
170 * VLPIS [1] == 0 171 * (virtual LPIs not supported) |
172 * PLPIS [0] == 1 173 * (physical LPIs supported) |
174 */ 175 uint64_t affinity = getAffinity(); 176 int last = cpuId == (gic->getSystem()->numContexts() - 1); 177 return (affinity << 32) | (1 << 24) | (cpuId << 8) | |
178 (1 << 5) | (last << 4) | (1 << 3) | (1 << 0); |
179 } 180 181 case GICR_WAKER: // Wake Register 182 if (!distributor->DS && !is_secure_access) { 183 // RAZ/WI for non-secure accesses 184 return 0; 185 } 186 --- 163 unchanged lines hidden (view full) --- 350 value |= irqNsacr[int_id] << i; 351 } 352 } 353 } 354 355 return value; 356 } 357 |
358 case GICR_PROPBASER: // Redistributor Properties Base Address Register 359 // OuterCache, bits [58:56] 360 // 000 Memory type defined in InnerCache field 361 // Physical_Address, bits [51:12] 362 // Bits [51:12] of the physical address containing the LPI 363 // Configuration table 364 // Shareability, bits [11:10] 365 // 00 Non-shareable 366 // InnerCache, bits [9:7] 367 // 000 Device-nGnRnE 368 // IDbits, bits [4:0] 369 // limited by GICD_TYPER.IDbits 370 return lpiConfigurationTablePtr | lpiIDBits; 371 372 // Redistributor LPI Pending Table Base Address Register 373 case GICR_PENDBASER: 374 // PTZ, bit [62] 375 // Pending Table Zero 376 // OuterCache, bits [58:56] 377 // 000 Memory type defined in InnerCache field 378 // Physical_Address, bits [51:16] 379 // Bits [51:16] of the physical address containing the LPI Pending 380 // table 381 // Shareability, bits [11:10] 382 // 00 Non-shareable 383 // InnerCache, bits [9:7] 384 // 000 Device-nGnRnE 385 return lpiPendingTablePtr; 386 387 // Redistributor Synchronize Register 388 case GICR_SYNCR: 389 return 0; 390 |
391 default: 392 panic("Gicv3Redistributor::read(): invalid offset %#x\n", addr); 393 break; 394 } 395} 396 397void 398Gicv3Redistributor::write(Addr addr, uint64_t data, size_t size, --- 20 unchanged lines hidden (view full) --- 419 "int_id %d priority %d\n", int_id, irqPriority[int_id]); 420 } 421 422 return; 423 } 424 425 switch (addr) { 426 case GICR_CTLR: { |
427 // GICR_TYPER.LPIS is 0 so EnableLPIs is RES0 428 EnableLPIs = data & GICR_CTLR_ENABLE_LPIS; |
429 DPG1S = data & GICR_CTLR_DPG1S; 430 DPG1NS = data & GICR_CTLR_DPG1NS; 431 DPG0 = data & GICR_CTLR_DPG0; 432 break; 433 } 434 435 case GICR_WAKER: // Wake Register 436 if (!distributor->DS && !is_secure_access) { --- 207 unchanged lines hidden (view full) --- 644 irqNsacr[int_id] = (data >> i) & 0x3; 645 } 646 } 647 } 648 649 break; 650 } 651 |
652 case GICR_SETLPIR: // Set LPI Pending Register 653 setClrLPI(data, true); 654 break; 655 656 case GICR_CLRLPIR: // Clear LPI Pending Register 657 setClrLPI(data, false); 658 break; 659 660 case GICR_PROPBASER: { // Redistributor Properties Base Address Register 661 // OuterCache, bits [58:56] 662 // 000 Memory type defined in InnerCache field 663 // Physical_Address, bits [51:12] 664 // Bits [51:12] of the physical address containing the LPI 665 // Configuration table 666 // Shareability, bits [11:10] 667 // 00 Non-shareable 668 // InnerCache, bits [9:7] 669 // 000 Device-nGnRnE 670 // IDbits, bits [4:0] 671 // limited by GICD_TYPER.IDbits (= 0xf) 672 lpiConfigurationTablePtr = data & 0xFFFFFFFFFF000; 673 lpiIDBits = data & 0x1f; 674 675 // 0xf here matches the value of GICD_TYPER.IDbits. 676 // TODO - make GICD_TYPER.IDbits a parameter instead of a hardcoded 677 // value 678 if (lpiIDBits > 0xf) { 679 lpiIDBits = 0xf; 680 } 681 682 uint32_t largest_lpi_id = 2 ^ (lpiIDBits + 1); 683 uint32_t number_lpis = largest_lpi_id - SMALLEST_LPI_ID + 1; 684 lpiConfigurationTable.resize(number_lpis); 685 break; 686 } 687 688 // Redistributor LPI Pending Table Base Address Register 689 case GICR_PENDBASER: 690 // PTZ, bit [62] 691 // Pending Table Zero 692 // OuterCache, bits [58:56] 693 // 000 Memory type defined in InnerCache field 694 // Physical_Address, bits [51:16] 695 // Bits [51:16] of the physical address containing the LPI Pending 696 // table 697 // Shareability, bits [11:10] 698 // 00 Non-shareable 699 // InnerCache, bits [9:7] 700 // 000 Device-nGnRnE 701 lpiPendingTablePtr = data & 0xFFFFFFFFF0000; 702 break; 703 704 case GICR_INVLPIR: { // Redistributor Invalidate LPI Register 705 uint32_t lpi_id = data & 0xffffffff; 706 uint32_t largest_lpi_id = 2 ^ (lpiIDBits + 1); 707 708 if (lpi_id > largest_lpi_id) { 709 return; 710 } 711 712 uint32_t lpi_table_entry_index = lpi_id - SMALLEST_LPI_ID; 713 invalLpiConfig(lpi_table_entry_index); 714 break; 715 } 716 717 case GICR_INVALLR: { // Redistributor Invalidate All Register 718 for (int lpi_table_entry_index = 0; 719 lpi_table_entry_index < lpiConfigurationTable.size(); 720 lpi_table_entry_index++) { 721 invalLpiConfig(lpi_table_entry_index); 722 } 723 724 break; 725 } 726 |
727 default: 728 panic("Gicv3Redistributor::write(): invalid offset %#x\n", addr); 729 break; 730 } 731} 732 733void |
734Gicv3Redistributor::invalLpiConfig(uint32_t lpi_entry_index) 735{ 736 Addr lpi_table_entry_ptr = lpiConfigurationTablePtr + 737 lpi_entry_index * sizeof(LPIConfigurationTableEntry); 738 ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId); 739 tc->getVirtProxy().readBlob(lpi_table_entry_ptr, 740 (uint8_t*) &lpiConfigurationTable[lpi_entry_index], 741 sizeof(LPIConfigurationTableEntry)); 742} 743 744void |
745Gicv3Redistributor::sendPPInt(uint32_t int_id) 746{ 747 assert((int_id >= Gicv3::SGI_MAX) && 748 (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX)); 749 irqPending[int_id] = true; 750 DPRINTF(GIC, "Gicv3Redistributor::sendPPInt(): " 751 "int_id %d (PPI) pending bit set\n", int_id); 752 updateAndInformCPUInterface(); --- 75 unchanged lines hidden (view full) --- 828 cpuInterface->hppi.intid = int_id; 829 cpuInterface->hppi.prio = irqPriority[int_id]; 830 cpuInterface->hppi.group = int_group; 831 new_hppi = true; 832 } 833 } 834 } 835 |
836 // Check LPIs 837 uint32_t largest_lpi_id = 2 ^ (lpiIDBits + 1); 838 char lpi_pending_table[largest_lpi_id / 8]; 839 ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId); 840 tc->getVirtProxy().readBlob(lpiPendingTablePtr, 841 (uint8_t *) lpi_pending_table, 842 sizeof(lpi_pending_table)); 843 for (int lpi_id = SMALLEST_LPI_ID; lpi_id < largest_lpi_id; 844 largest_lpi_id++) { 845 uint32_t lpi_pending_entry_byte = lpi_id / 8; 846 uint8_t lpi_pending_entry_bit_position = lpi_id % 8; 847 bool lpi_is_pending = lpi_pending_table[lpi_pending_entry_byte] & 848 1 << lpi_pending_entry_bit_position; 849 uint32_t lpi_configuration_entry_index = lpi_id - SMALLEST_LPI_ID; 850 bool lpi_is_enable = 851 lpiConfigurationTable[lpi_configuration_entry_index].enable; 852 // LPIs are always Non-secure Group 1 interrupts, 853 // in a system where two Security states are enabled. 854 Gicv3::GroupId lpi_group = Gicv3::G1NS; 855 bool group_enabled = distributor->groupEnabled(lpi_group); 856 857 if (lpi_is_pending && lpi_is_enable && group_enabled) { 858 uint8_t lpi_priority = 859 lpiConfigurationTable[lpi_configuration_entry_index].priority; 860 861 if ((lpi_priority < cpuInterface->hppi.prio) || 862 (lpi_priority == cpuInterface->hppi.prio && 863 lpi_id < cpuInterface->hppi.intid)) { 864 cpuInterface->hppi.intid = lpi_id; 865 cpuInterface->hppi.prio = lpi_priority; 866 cpuInterface->hppi.group = lpi_group; 867 new_hppi = true; 868 } 869 } 870 } 871 |
872 if (!new_hppi && cpuInterface->hppi.prio != 0xff && 873 cpuInterface->hppi.intid < Gicv3::SGI_MAX + Gicv3::PPI_MAX) { 874 distributor->fullUpdate(); 875 } 876} 877 878void |
879Gicv3Redistributor::setClrLPI(uint64_t data, bool set) 880{ 881 if (!EnableLPIs) { 882 // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if 883 // GICR_CTLR.EnableLPIs == 0. 884 return; 885 } 886 887 uint32_t lpi_id = data & 0xffffffff; 888 uint32_t largest_lpi_id = 2 ^ (lpiIDBits + 1); 889 890 if (lpi_id > largest_lpi_id) { 891 // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if 892 // pINTID value specifies an unimplemented LPI. 893 return; 894 } 895 896 Addr lpi_pending_entry_ptr = lpiPendingTablePtr + (lpi_id / 8); 897 uint8_t lpi_pending_entry; 898 ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId); 899 tc->getVirtProxy().readBlob(lpi_pending_entry_ptr, 900 (uint8_t*) &lpi_pending_entry, 901 sizeof(lpi_pending_entry)); 902 uint8_t lpi_pending_entry_bit_position = lpi_id % 8; 903 bool is_set = lpi_pending_entry & (1 << lpi_pending_entry_bit_position); 904 905 if (set) { 906 if (is_set) { 907 // Writes to GICR_SETLPIR have not effect if the pINTID field 908 // corresponds to an LPI that is already pending. 909 return; 910 } 911 912 lpi_pending_entry |= 1 << (lpi_pending_entry_bit_position); 913 } else { 914 if (!is_set) { 915 // Writes to GICR_SETLPIR have not effect if the pINTID field 916 // corresponds to an LPI that is not pending. 917 return; 918 } 919 920 lpi_pending_entry &= ~(1 << (lpi_pending_entry_bit_position)); 921 } 922 923 tc->getVirtProxy().writeBlob(lpi_pending_entry_ptr, 924 (uint8_t*) &lpi_pending_entry, 925 sizeof(lpi_pending_entry)); 926 updateAndInformCPUInterface(); 927} 928 929void |
930Gicv3Redistributor::updateAndInformCPUInterface() 931{ 932 update(); 933 cpuInterface->update(); 934} 935 936Gicv3::GroupId 937Gicv3Redistributor::getIntGroup(int int_id) --- 87 unchanged lines hidden (view full) --- 1025 SERIALIZE_CONTAINER(irqActive); 1026 SERIALIZE_CONTAINER(irqPriority); 1027 SERIALIZE_CONTAINER(irqConfig); 1028 SERIALIZE_CONTAINER(irqGrpmod); 1029 SERIALIZE_CONTAINER(irqNsacr); 1030 SERIALIZE_SCALAR(DPG1S); 1031 SERIALIZE_SCALAR(DPG1NS); 1032 SERIALIZE_SCALAR(DPG0); |
1033 SERIALIZE_SCALAR(EnableLPIs); 1034 SERIALIZE_SCALAR(lpiConfigurationTablePtr); 1035 SERIALIZE_SCALAR(lpiIDBits); 1036 SERIALIZE_SCALAR(lpiPendingTablePtr); |
1037} 1038 1039void 1040Gicv3Redistributor::unserialize(CheckpointIn & cp) 1041{ 1042 UNSERIALIZE_SCALAR(peInLowPowerState); 1043 UNSERIALIZE_CONTAINER(irqGroup); 1044 UNSERIALIZE_CONTAINER(irqEnabled); 1045 UNSERIALIZE_CONTAINER(irqPending); 1046 UNSERIALIZE_CONTAINER(irqActive); 1047 UNSERIALIZE_CONTAINER(irqPriority); 1048 UNSERIALIZE_CONTAINER(irqConfig); 1049 UNSERIALIZE_CONTAINER(irqGrpmod); 1050 UNSERIALIZE_CONTAINER(irqNsacr); 1051 UNSERIALIZE_SCALAR(DPG1S); 1052 UNSERIALIZE_SCALAR(DPG1NS); 1053 UNSERIALIZE_SCALAR(DPG0); |
1054 UNSERIALIZE_SCALAR(EnableLPIs); 1055 UNSERIALIZE_SCALAR(lpiConfigurationTablePtr); 1056 UNSERIALIZE_SCALAR(lpiIDBits); 1057 UNSERIALIZE_SCALAR(lpiPendingTablePtr); |
1058} |