1711d51d8SMatt Spinler /**
2711d51d8SMatt Spinler  * Copyright © 2019 IBM Corporation
3711d51d8SMatt Spinler  *
4711d51d8SMatt Spinler  * Licensed under the Apache License, Version 2.0 (the "License");
5711d51d8SMatt Spinler  * you may not use this file except in compliance with the License.
6711d51d8SMatt Spinler  * You may obtain a copy of the License at
7711d51d8SMatt Spinler  *
8711d51d8SMatt Spinler  *     http://www.apache.org/licenses/LICENSE-2.0
9711d51d8SMatt Spinler  *
10711d51d8SMatt Spinler  * Unless required by applicable law or agreed to in writing, software
11711d51d8SMatt Spinler  * distributed under the License is distributed on an "AS IS" BASIS,
12711d51d8SMatt Spinler  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13711d51d8SMatt Spinler  * See the License for the specific language governing permissions and
14711d51d8SMatt Spinler  * limitations under the License.
15711d51d8SMatt Spinler  */
1690b4a0a0SMatt Spinler #include "mru.hpp"
1790b4a0a0SMatt Spinler 
18*5bc26533SArya K Padman #include <phosphor-logging/lg2.hpp>
1990b4a0a0SMatt Spinler 
2090b4a0a0SMatt Spinler namespace openpower
2190b4a0a0SMatt Spinler {
2290b4a0a0SMatt Spinler namespace pels
2390b4a0a0SMatt Spinler {
2490b4a0a0SMatt Spinler namespace src
2590b4a0a0SMatt Spinler {
2690b4a0a0SMatt Spinler 
275ab39978SMatt Spinler // The MRU substructure supports up to 15 MRUs.
285ab39978SMatt Spinler static constexpr size_t maxMRUs = 15;
295ab39978SMatt Spinler 
MRU(Stream & pel)3090b4a0a0SMatt Spinler MRU::MRU(Stream& pel)
3190b4a0a0SMatt Spinler {
3290b4a0a0SMatt Spinler     pel >> _type >> _size >> _flags >> _reserved4B;
3390b4a0a0SMatt Spinler 
3490b4a0a0SMatt Spinler     size_t numMRUs = _flags & 0xF;
3590b4a0a0SMatt Spinler 
3690b4a0a0SMatt Spinler     for (size_t i = 0; i < numMRUs; i++)
3790b4a0a0SMatt Spinler     {
3890b4a0a0SMatt Spinler         MRUCallout mru;
3990b4a0a0SMatt Spinler         pel >> mru.priority;
4090b4a0a0SMatt Spinler         pel >> mru.id;
4190b4a0a0SMatt Spinler         _mrus.push_back(std::move(mru));
4290b4a0a0SMatt Spinler     }
4390b4a0a0SMatt Spinler 
4490b4a0a0SMatt Spinler     size_t actualSize = sizeof(_type) + sizeof(_size) + sizeof(_flags) +
4590b4a0a0SMatt Spinler                         sizeof(_reserved4B) +
4690b4a0a0SMatt Spinler                         (sizeof(MRUCallout) * _mrus.size());
4790b4a0a0SMatt Spinler     if (_size != actualSize)
4890b4a0a0SMatt Spinler     {
49*5bc26533SArya K Padman         lg2::warning(
50*5bc26533SArya K Padman             "MRU callout section in PEL with {NUM_MRUS} MRUs has listed size "
51*5bc26533SArya K Padman             "{SUBSTRUCTURE_SIZE} that doesn't match the actual size "
52*5bc26533SArya K Padman             "{ACTUAL_SIZE}",
53*5bc26533SArya K Padman             "SUBSTRUCTURE_SIZE", _size, "NUM_MRUS", _mrus.size(), "ACTUAL_SIZE",
54*5bc26533SArya K Padman             actualSize);
5590b4a0a0SMatt Spinler     }
5690b4a0a0SMatt Spinler }
5790b4a0a0SMatt Spinler 
MRU(const std::vector<MRUCallout> & mrus)585ab39978SMatt Spinler MRU::MRU(const std::vector<MRUCallout>& mrus)
595ab39978SMatt Spinler {
605ab39978SMatt Spinler     if (mrus.empty())
615ab39978SMatt Spinler     {
62*5bc26533SArya K Padman         lg2::error("Trying to create a MRU section with no MRUs");
635ab39978SMatt Spinler         throw std::runtime_error{"Trying to create a MRU section with no MRUs"};
645ab39978SMatt Spinler     }
655ab39978SMatt Spinler 
665ab39978SMatt Spinler     _mrus = mrus;
675ab39978SMatt Spinler     if (_mrus.size() > maxMRUs)
685ab39978SMatt Spinler     {
695ab39978SMatt Spinler         _mrus.resize(maxMRUs);
705ab39978SMatt Spinler     }
715ab39978SMatt Spinler 
725ab39978SMatt Spinler     _type = substructureType;
735ab39978SMatt Spinler     _size = sizeof(_type) + sizeof(_size) + sizeof(_flags) +
745ab39978SMatt Spinler             sizeof(_reserved4B) + (sizeof(MRUCallout) * _mrus.size());
755ab39978SMatt Spinler     _flags = _mrus.size();
765ab39978SMatt Spinler     _reserved4B = 0;
775ab39978SMatt Spinler }
785ab39978SMatt Spinler 
flatten(Stream & pel) const79724d0d8cSMatt Spinler void MRU::flatten(Stream& pel) const
8090b4a0a0SMatt Spinler {
8190b4a0a0SMatt Spinler     pel << _type << _size << _flags << _reserved4B;
8290b4a0a0SMatt Spinler 
8390b4a0a0SMatt Spinler     for (auto& mru : _mrus)
8490b4a0a0SMatt Spinler     {
8590b4a0a0SMatt Spinler         pel << mru.priority;
8690b4a0a0SMatt Spinler         pel << mru.id;
8790b4a0a0SMatt Spinler     }
8890b4a0a0SMatt Spinler }
8990b4a0a0SMatt Spinler } // namespace src
9090b4a0a0SMatt Spinler } // namespace pels
9190b4a0a0SMatt Spinler } // namespace openpower
92