1111#include <platform_defs.h>
1212#include <objpool.h>
1313#include <config.h>
14+ #include <arch/mpu.h>
1415
1516struct shared_region {
1617 enum AS_TYPE as_type ;
@@ -38,6 +39,25 @@ static inline struct mpe* mem_vmpu_get_entry(struct addr_space* as, mpid_t mpid)
3839 return NULL ;
3940}
4041
42+ static int vmpu_node_cmp (node_t * _n1 , node_t * _n2 )
43+ {
44+ struct mpe * n1 = (struct mpe * )_n1 ;
45+ struct mpe * n2 = (struct mpe * )_n2 ;
46+ struct mp_region r1 ;
47+ struct mp_region r2 ;
48+
49+ r1 = n1 -> region ;
50+ r2 = n2 -> region ;
51+
52+ if (r1 .base > r2 .base ) {
53+ return 1 ;
54+ } else if (r1 .base < r2 .base ) {
55+ return -1 ;
56+ } else {
57+ return 0 ;
58+ }
59+ }
60+
4161static void mem_vmpu_set_entry (struct addr_space * as , mpid_t mpid , struct mp_region * mpr )
4262{
4363 struct mpe * mpe = mem_vmpu_get_entry (as , mpid );
@@ -360,6 +380,51 @@ static mpid_t mem_vmpu_find_overlapping_region(struct addr_space* as, struct mp_
360380 return mpid ;
361381}
362382
383+ void mem_vmpu_coalesce_contiguous (struct addr_space * as , bool broadcast )
384+ {
385+ while (true) {
386+ bool merge = false;
387+ mpid_t cur_mpid = INVALID_MPID ;
388+ mpid_t prev_mpid = INVALID_MPID ;
389+ struct mpe * prev_reg ;
390+ struct mpe * cur_reg ;
391+ list_foreach_tail (cpu ()-> as .vmpu .ordered_list , struct mpe , cur , prev )
392+ {
393+ if (prev == NULL ) {
394+ continue ;
395+ }
396+ cur_reg = mem_vmpu_get_entry (as , cur -> mpid );
397+ prev_reg = mem_vmpu_get_entry (as , prev -> mpid );
398+
399+ bool contigous = prev_reg -> region .base + prev_reg -> region .size == cur_reg -> region .base ;
400+ bool perms_compatible =
401+ mpu_perms_comptible (prev_reg -> region .mem_flags .raw , cur_reg -> region .mem_flags .raw );
402+ if (contigous && perms_compatible ) {
403+ cur_mpid = cur -> mpid ;
404+ prev_mpid = prev -> mpid ;
405+ merge = true;
406+ break ;
407+ }
408+ }
409+
410+ if (merge ) {
411+ mem_vmpu_remove_region (as , cur_mpid , broadcast );
412+ mem_vmpu_remove_region (as , prev_mpid , broadcast );
413+ struct mp_region merged_reg = {
414+ .base = prev_reg -> region .base ,
415+ .size = prev_reg -> region .size + cur_reg -> region .size ,
416+ .mem_flags = cur_reg -> region .mem_flags ,
417+ };
418+ mpid_t mpid = mem_vmpu_allocate_entry (as );
419+ if (mpid != INVALID_MPID ) {
420+ mem_vmpu_insert_region (as , mpid , & merged_reg , broadcast );
421+ }
422+ } else {
423+ break ;
424+ }
425+ }
426+ }
427+
363428bool mem_map (struct addr_space * as , struct mp_region * mpr , bool broadcast )
364429{
365430 bool mapped = false;
@@ -383,6 +448,10 @@ bool mem_map(struct addr_space* as, struct mp_region* mpr, bool broadcast)
383448 }
384449 }
385450
451+ if (mapped ) {
452+ mem_vmpu_coalesce_contiguous (as , broadcast );
453+ }
454+
386455 spin_unlock (& as -> lock );
387456
388457 return mapped ;
0 commit comments