After the re-organization of the code related to uvm hotplug into a separate file uvm_physseg.c, the exposed API via uvm_physseg.h and the introduction of a handle uvm_physseg_t which is used to access data structure that keeps physical segment information, we came across a failing ATF test case in the static array implementation which was working as expected in the RB tree implementation. For the static array implementation we were using the VM_PSTRAT_BSEARCH strategy.

The specific test case in question is uvm_physseg_get_prev which had the segements being inserted into the system out-of-order, this meant that the page frames of the segments that were inserted in chunks were not in a sorted order. So the first chunk may be in the 256 to 512 range and the second chunk was in the 0 to 256 range. The same chunks if inserted in sorted order resulted in a passing test.

After some amount of debugging we found out why this rather seemingly trivial change in the order of insertion was causing the tests to fail, this was a consequence of changing the way the segment was being referenced in the underlying data structure from static array implementation to RB Tree implementation.

So in the static array implementation the reference to a segment was done via the index of the array. For example, in the above example the first segment regardless of the address range of the segment would be inserted in index 0 of the array. Now the handle of the inserted segment will be the index of the array and this is the important distinction.

Now let us insert a second segment into the above said array, and depending on if the address range is greater or lesser than the current segement at 0 it would end up either on the right or left of the given segment respectively. This is done to maintain sorted order during insertion of segments to comply with the VM_PSTRAT_BSEARCH strategy. Now whenever an insert occurs, it means shifting contents of the array to the left or right to make room for the new segment, hence in the example above inserting left implies you are shifting index of the first segment by one effectively making it 1 and the new segment is inserted at 0

For an external caller of the API, this is how it looks.

upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
            VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);

Now upm points to the segment that was inserted by uvm_page_physload() and at this point it is 0.

Let us do a second insert,

uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
      VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);

NOTE: This insertion is done in such a way the second segement is in a lesser address range than the first one which was interested. Also I do not assign the handle returned by the call to any variable.

So what does upm handle point to now? My expectation (since the tests were written agnostic to the backing data structure) was that upm will still point to the first one inserted. But in the case of static array implementation, this will not be true, since the position of the first segment was shifted to make space for the second one.

So the question arises, should the handle be mutable when you do inserts / deletes on the backing data structure? In my opinion “No”, a handle to a given segment should always point to that segment and should not matter if the position of the segment has changed in the backing data structure.

RB Tree, does not suffer from this issue since the handle to the segment is the physical address of struct uvm_physseg in the system.

In order to separately identifiy this property of mutability we added a new test case in ATF uvm_physseg_handle_immutable which should always fail for static array implementation.