@@ -452,6 +452,49 @@ static mpid_t mem_vmpu_find_overlapping_region(struct addr_space* as, struct mp_
452452 return mpid ;
453453}
454454
455+ static void mem_vmpu_coalesce_contiguous (struct addr_space * as , bool broadcast )
456+ {
457+ while (true) {
458+ bool merge = false;
459+ mpid_t cur_mpid = INVALID_MPID ;
460+ mpid_t prev_mpid = INVALID_MPID ;
461+ struct mpe * prev_reg ;
462+ struct mpe * cur_reg ;
463+ list_foreach_tail (as -> vmpu .ordered_list , struct mpe , cur , prev )
464+ {
465+ if (prev == NULL ) {
466+ continue ;
467+ }
468+ cur_reg = mem_vmpu_get_entry (as , cur -> mpid );
469+ prev_reg = mem_vmpu_get_entry (as , prev -> mpid );
470+
471+ bool contiguous = prev_reg -> region .base + prev_reg -> region .size == cur_reg -> region .base ;
472+ bool perms_compatible =
473+ mpu_perms_compatible (prev_reg -> region .mem_flags .raw , cur_reg -> region .mem_flags .raw );
474+ bool lock_compatible = !prev_reg -> lock && !cur_reg -> lock ;
475+ if (contiguous && perms_compatible && lock_compatible ) {
476+ cur_mpid = cur -> mpid ;
477+ prev_mpid = prev -> mpid ;
478+ merge = true;
479+ break ;
480+ }
481+ }
482+
483+ if (merge ) {
484+ struct mp_region merged_reg = {
485+ .base = prev_reg -> region .base ,
486+ .size = prev_reg -> region .size + cur_reg -> region .size ,
487+ .mem_flags = cur_reg -> region .mem_flags ,
488+ };
489+ if (mem_vmpu_update_region (as , prev_mpid , merged_reg , broadcast , prev_reg -> lock )) {
490+ mem_vmpu_remove_region (as , cur_mpid , broadcast );
491+ }
492+ } else {
493+ break ;
494+ }
495+ }
496+ }
497+
455498bool mem_map (struct addr_space * as , struct mp_region * mpr , bool broadcast , bool locked )
456499{
457500 bool mapped = false;
@@ -474,6 +517,10 @@ bool mem_map(struct addr_space* as, struct mp_region* mpr, bool broadcast, bool
474517 }
475518 }
476519
520+ if (mapped && !locked ) {
521+ mem_vmpu_coalesce_contiguous (as , broadcast );
522+ }
523+
477524 spin_unlock (& as -> lock );
478525
479526 return mapped ;
0 commit comments