diff --git a/projects/rocr-runtime/src/events.c b/projects/rocr-runtime/src/events.c index 6de79903c7..392d0b4cf8 100644 --- a/projects/rocr-runtime/src/events.c +++ b/projects/rocr-runtime/src/events.c @@ -36,6 +36,11 @@ static HSAuint64 *events_page = NULL; +void clear_events_page(void) +{ + events_page = NULL; +} + static bool IsSystemEventType(HSA_EVENTTYPE type) { // Debug events behave as signal events. diff --git a/projects/rocr-runtime/src/fmm.c b/projects/rocr-runtime/src/fmm.c index 67e1f6f8be..0fd0320432 100644 --- a/projects/rocr-runtime/src/fmm.c +++ b/projects/rocr-runtime/src/fmm.c @@ -2928,3 +2928,67 @@ HSAKMT_STATUS fmm_set_mem_user_data(const void *mem, void *usr_data) vm_obj->user_data = usr_data; return HSAKMT_STATUS_SUCCESS; } + +static void fmm_clear_aperture(manageble_aperture_t *app) +{ + while (app->vm_objects) + vm_remove_object(app, app->vm_objects); + + while (app->vm_ranges) + vm_remove_area(app, app->vm_ranges); + +} + +/* This is a special funcion that should be called only from the child process + * after a fork(). This will clear all vm_objects and mmaps duplicated from + * the parent. + */ +void fmm_clear_all_mem(void) +{ + uint32_t i; + void *map_addr; + + /* Nothing is initialized. */ + if (!gpu_mem) + return; + + fmm_clear_aperture(&cpuvm_aperture); + + for (i = 0; i < gpu_mem_count; i++) { + fmm_clear_aperture(&gpu_mem[i].gpuvm_aperture); + fmm_clear_aperture(&gpu_mem[i].scratch_aperture); + fmm_clear_aperture(&gpu_mem[i].scratch_physical); + } + + if (is_dgpu_mem_init) { + fmm_clear_aperture(&svm.dgpu_aperture); + fmm_clear_aperture(&svm.dgpu_alt_aperture); + + /* Use the same dgpu range as the parent. If failed, then set + * is_dgpu_mem_init to false. Later on dgpu_mem_init will try + * to get a new range + */ + map_addr = mmap(dgpu_shared_aperture_base, (HSAuint64)(dgpu_shared_aperture_limit)- + (HSAuint64)(dgpu_shared_aperture_base) + 1, PROT_NONE, + MAP_ANONYMOUS | MAP_NORESERVE | MAP_PRIVATE | MAP_FIXED, -1, 0); + + if (map_addr == MAP_FAILED) { + munmap(dgpu_shared_aperture_base, + (HSAuint64)(dgpu_shared_aperture_limit) - + (HSAuint64)(dgpu_shared_aperture_base) + 1); + + dgpu_shared_aperture_base = NULL; + dgpu_shared_aperture_limit = NULL; + is_dgpu_mem_init = false; + } + } + + if (all_gpu_id_array) + free(all_gpu_id_array); + + all_gpu_id_array_size = 0; + all_gpu_id_array = NULL; + + gpu_mem_count = 0; + free(gpu_mem); +} diff --git a/projects/rocr-runtime/src/libhsakmt.h b/projects/rocr-runtime/src/libhsakmt.h index 2243521df1..e3b07dc90a 100644 --- a/projects/rocr-runtime/src/libhsakmt.h +++ b/projects/rocr-runtime/src/libhsakmt.h @@ -95,4 +95,7 @@ extern int kmtIoctl(int fd, unsigned long request, void *arg); #define VOID_PTR_SUB(ptr,n) (void*)((uint8_t*)(ptr) - n)/*ptr - offset*/ #define VOID_PTRS_SUB(ptr1,ptr2) (uint64_t)((uint8_t*)(ptr1) - (uint8_t*)(ptr2)) /*ptr1 - ptr2*/ +void clear_events_page(void); +void fmm_clear_all_mem(void); +void clear_process_doorbells(void); #endif diff --git a/projects/rocr-runtime/src/openclose.c b/projects/rocr-runtime/src/openclose.c index 5a55a3a50b..8901cffcdc 100644 --- a/projects/rocr-runtime/src/openclose.c +++ b/projects/rocr-runtime/src/openclose.c @@ -36,20 +36,39 @@ static const char kfd_device_name[] = "/dev/kfd"; static const char tmp_file[] = "/var/lock/.amd_hsa_thunk_lock"; int amd_hsa_thunk_lock_fd = 0; +static pid_t parent_pid = -1; + static bool is_forked_child(void) { - static pid_t open_pid = -1; - pid_t my_pid = getpid(); + pid_t cur_pid = getpid(); - if (open_pid == -1 || open_pid != my_pid) { - open_pid = my_pid; - return true; + if (parent_pid == -1) { + parent_pid = cur_pid; + return false; } + if (parent_pid != cur_pid) + return true; + return false; } +/* Call this from the child process after fork. This will clear all + * data that is duplicated from the parent process, that is not valid + * in the child. + * The topology information is duplicated from the parent is valid + * in the child process so it is not cleared + */ +static void clear_after_fork(void) +{ + clear_process_doorbells(); + clear_events_page(); + fmm_clear_all_mem(); + destroy_device_debugging_memory(); + kfd_open_count = 0; +} + HSAKMT_STATUS HSAKMTAPI hsaKmtOpenKFD(void) @@ -65,7 +84,7 @@ hsaKmtOpenKFD(void) * belong to the parent */ if (is_forked_child()) - kfd_open_count = 0; + clear_after_fork(); if (kfd_open_count == 0) { diff --git a/projects/rocr-runtime/src/queues.c b/projects/rocr-runtime/src/queues.c index e4e383c08c..a2ddb535a8 100644 --- a/projects/rocr-runtime/src/queues.c +++ b/projects/rocr-runtime/src/queues.c @@ -257,6 +257,29 @@ void destroy_process_doorbells(void) num_doorbells = 0; } +/* This is a special funcion that should be called only from the child process + * after a fork(). This will clear doorbells duplicated from the parent. + */ +void clear_process_doorbells(void) +{ + unsigned int i; + + if (!doorbells) + return; + + for (i = 0; i < num_doorbells; i++) { + if (doorbells[i].need_mmap) + continue; + + if (!use_gpuvm_doorbell(get_device_id_by_node(i))) + munmap(doorbells[i].doorbells, DOORBELLS_PAGE_SIZE); + } + + free(doorbells); + doorbells = NULL; + num_doorbells = 0; +} + static HSAKMT_STATUS map_doorbell_apu(HSAuint32 NodeId, HSAuint32 gpu_id, HSAuint64 doorbell_offset) {