1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#include "mos/mm/paging/table_ops/do_copy.h"
4
5#include "mos/mm/paging/pml_types.h"
6#include "mos/mm/paging/pmlx/pml1.h"
7#include "mos/mm/paging/pmlx/pml2.h"
8#include "mos/mm/paging/pmlx/pml3.h"
9#include "mos/mm/paging/pmlx/pml4.h"
10#include "mos/platform/platform.h"
11
12#include <mos/mos_global.h>
13#include <mos_string.h>
14
15static void pml1e_do_copy_callback(pml1_t pml1, pml1e_t *src_e, ptr_t vaddr, void *data)
16{
17 MOS_UNUSED(pml1);
18 struct pagetable_do_copy_data *copy_data = data;
19 copy_data->dest_pml1e = pml1_entry(pml1: copy_data->dest_pml1, vaddr);
20
21 const pfn_t old_pfn = platform_pml1e_get_present(pml1: copy_data->dest_pml1e) ? platform_pml1e_get_pfn(pml1: copy_data->dest_pml1e) : 0;
22
23 if (platform_pml1e_get_present(pml1: src_e))
24 {
25 pmm_ref_one(platform_pml1e_get_pfn(src_e));
26 copy_data->dest_pml1e->content = src_e->content;
27 }
28 else
29 {
30 pmlxe_destroy(copy_data->dest_pml1e);
31 }
32
33 if (old_pfn)
34 pmm_unref_one(old_pfn);
35}
36
37static void pml2e_do_copy_callback(pml2_t pml2, pml2e_t *e, ptr_t vaddr, void *data)
38{
39 MOS_UNUSED(pml2);
40 struct pagetable_do_copy_data *copy_data = data;
41 copy_data->dest_pml2e = pml2_entry(pml2: copy_data->dest_pml2, vaddr);
42 copy_data->dest_pml1 = pml2e_get_or_create_pml1(pml2e: copy_data->dest_pml2e);
43
44 platform_pml2e_set_flags(pml2: copy_data->dest_pml2e, flags: platform_pml2e_get_flags(pml2e: e));
45}
46
47static void pml3e_do_copy_callback(pml3_t pml3, pml3e_t *e, ptr_t vaddr, void *data)
48{
49 MOS_UNUSED(pml3);
50 struct pagetable_do_copy_data *copy_data = data;
51 copy_data->dest_pml3e = pml3_entry(pml3: copy_data->dest_pml3, vaddr);
52 copy_data->dest_pml2 = pml3e_get_or_create_pml2(pml3e: copy_data->dest_pml3e);
53
54 platform_pml3e_set_flags(pml3: copy_data->dest_pml3e, flags: platform_pml3e_get_flags(pml3e: e));
55}
56
57static void pml4e_do_copy_callback(pml4_t pml4, pml4e_t *e, ptr_t vaddr, void *data)
58{
59 MOS_UNUSED(pml4);
60 struct pagetable_do_copy_data *copy_data = data;
61 copy_data->dest_pml4e = pml4_entry(pml4: copy_data->dest_pml4, vaddr);
62 copy_data->dest_pml3 = pml4e_get_or_create_pml3(pml4e: copy_data->dest_pml4e);
63
64 platform_pml4e_set_flags(pml4: copy_data->dest_pml4e, flags: platform_pml4e_get_flags(pml4e: e));
65}
66
67const pagetable_walk_options_t pagetable_do_copy_callbacks = {
68 .pml1e_callback = pml1e_do_copy_callback,
69 .pml2e_pre_traverse = pml2e_do_copy_callback,
70 .pml3e_pre_traverse = pml3e_do_copy_callback,
71 .pml4e_pre_traverse = pml4e_do_copy_callback,
72};
73