gic_v3_redistributor.cc (13531:e6f1bf55d038) gic_v3_redistributor.cc (13690:284050bbec68)
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"
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"
37
38const AddrRange Gicv3Redistributor::GICR_IPRIORITYR(SGI_base + 0x0400,
39 SGI_base + 0x041f);
40
41Gicv3Redistributor::Gicv3Redistributor(Gicv3 * gic, uint32_t cpu_id)
42 : gic(gic),
43 distributor(nullptr),
44 cpuInterface(nullptr),

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

86 irqConfig[int_id] = Gicv3::INT_EDGE_TRIGGERED;
87 }
88
89 std::fill(irqGrpmod.begin(), irqGrpmod.end(), 0);
90 std::fill(irqNsacr.begin(), irqNsacr.end(), 0);
91 DPG1S = false;
92 DPG1NS = false;
93 DPG0 = false;
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;
94}
95
96uint64_t
97Gicv3Redistributor::read(Addr addr, size_t size, bool is_secure_access)
98{
99 if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
100 uint64_t value = 0;
101 int first_intid = addr - GICR_IPRIORITYR.start();

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

130 if (DPG1NS) {
131 value |= GICR_CTLR_DPG1NS;
132 }
133
134 if (DPG0) {
135 value |= GICR_CTLR_DPG0;
136 }
137
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
138 return value;
139 }
140
141 case GICR_IIDR: // Implementer Identification Register
142 //return 0x43b; // r0p0 GIC-500
143 return 0;
144
145 case GICR_TYPER: { // Type Register

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

151 * LPI Configuration table)
152 * Processor_Number [23:8] == X
153 * (A unique identifier for the PE)
154 * DPGS [5] == 1
155 * (GICR_CTLR.DPG* bits are supported)
156 * Last [4] == X
157 * (This Redistributor is the highest-numbered Redistributor in
158 * a series of contiguous Redistributor pages)
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)
159 * DirectLPI [3] == 0
160 * (direct injection of LPIs not supported)
168 * DirectLPI [3] == 1
169 * (direct injection of LPIs supported)
161 * VLPIS [1] == 0
162 * (virtual LPIs not supported)
170 * VLPIS [1] == 0
171 * (virtual LPIs not supported)
163 * PLPIS [0] == 0
164 * (physical LPIs not supported)
172 * PLPIS [0] == 1
173 * (physical LPIs supported)
165 */
166 uint64_t affinity = getAffinity();
167 int last = cpuId == (gic->getSystem()->numContexts() - 1);
168 return (affinity << 32) | (1 << 24) | (cpuId << 8) |
174 */
175 uint64_t affinity = getAffinity();
176 int last = cpuId == (gic->getSystem()->numContexts() - 1);
177 return (affinity << 32) | (1 << 24) | (cpuId << 8) |
169 (1 << 5) | (last << 4);
178 (1 << 5) | (last << 4) | (1 << 3) | (1 << 0);
170 }
171
172 case GICR_WAKER: // Wake Register
173 if (!distributor->DS && !is_secure_access) {
174 // RAZ/WI for non-secure accesses
175 return 0;
176 }
177

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

341 value |= irqNsacr[int_id] << i;
342 }
343 }
344 }
345
346 return value;
347 }
348
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
349 default:
350 panic("Gicv3Redistributor::read(): invalid offset %#x\n", addr);
351 break;
352 }
353}
354
355void
356Gicv3Redistributor::write(Addr addr, uint64_t data, size_t size,

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

377 "int_id %d priority %d\n", int_id, irqPriority[int_id]);
378 }
379
380 return;
381 }
382
383 switch (addr) {
384 case GICR_CTLR: {
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: {
385 // GICR_TYPER.LPIS is 0 so Enable_LPIs is RES0
427 // GICR_TYPER.LPIS is 0 so EnableLPIs is RES0
428 EnableLPIs = data & GICR_CTLR_ENABLE_LPIS;
386 DPG1S = data & GICR_CTLR_DPG1S;
387 DPG1NS = data & GICR_CTLR_DPG1NS;
388 DPG0 = data & GICR_CTLR_DPG0;
389 break;
390 }
391
392 case GICR_WAKER: // Wake Register
393 if (!distributor->DS && !is_secure_access) {

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

601 irqNsacr[int_id] = (data >> i) & 0x3;
602 }
603 }
604 }
605
606 break;
607 }
608
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
609 default:
610 panic("Gicv3Redistributor::write(): invalid offset %#x\n", addr);
611 break;
612 }
613}
614
615void
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
616Gicv3Redistributor::sendPPInt(uint32_t int_id)
617{
618 assert((int_id >= Gicv3::SGI_MAX) &&
619 (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX));
620 irqPending[int_id] = true;
621 DPRINTF(GIC, "Gicv3Redistributor::sendPPInt(): "
622 "int_id %d (PPI) pending bit set\n", int_id);
623 updateAndInformCPUInterface();

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

699 cpuInterface->hppi.intid = int_id;
700 cpuInterface->hppi.prio = irqPriority[int_id];
701 cpuInterface->hppi.group = int_group;
702 new_hppi = true;
703 }
704 }
705 }
706
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
707 if (!new_hppi && cpuInterface->hppi.prio != 0xff &&
708 cpuInterface->hppi.intid < Gicv3::SGI_MAX + Gicv3::PPI_MAX) {
709 distributor->fullUpdate();
710 }
711}
712
713void
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
714Gicv3Redistributor::updateAndInformCPUInterface()
715{
716 update();
717 cpuInterface->update();
718}
719
720Gicv3::GroupId
721Gicv3Redistributor::getIntGroup(int int_id)

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

809 SERIALIZE_CONTAINER(irqActive);
810 SERIALIZE_CONTAINER(irqPriority);
811 SERIALIZE_CONTAINER(irqConfig);
812 SERIALIZE_CONTAINER(irqGrpmod);
813 SERIALIZE_CONTAINER(irqNsacr);
814 SERIALIZE_SCALAR(DPG1S);
815 SERIALIZE_SCALAR(DPG1NS);
816 SERIALIZE_SCALAR(DPG0);
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);
817}
818
819void
820Gicv3Redistributor::unserialize(CheckpointIn & cp)
821{
822 UNSERIALIZE_SCALAR(peInLowPowerState);
823 UNSERIALIZE_CONTAINER(irqGroup);
824 UNSERIALIZE_CONTAINER(irqEnabled);
825 UNSERIALIZE_CONTAINER(irqPending);
826 UNSERIALIZE_CONTAINER(irqActive);
827 UNSERIALIZE_CONTAINER(irqPriority);
828 UNSERIALIZE_CONTAINER(irqConfig);
829 UNSERIALIZE_CONTAINER(irqGrpmod);
830 UNSERIALIZE_CONTAINER(irqNsacr);
831 UNSERIALIZE_SCALAR(DPG1S);
832 UNSERIALIZE_SCALAR(DPG1NS);
833 UNSERIALIZE_SCALAR(DPG0);
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);
834}
1058}