summaryrefslogtreecommitdiffstats
path: root/src/lib/syscall_mm.C
blob: fee40232526398a304b73cd617604c5d65f8f5cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/lib/syscall_mm.C $                                        */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2011,2018                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#include <sys/syscall.h>
#include <sys/mm.h>
#include <arch/ppc.H>
#include <kernel/vmmmgr.H>
#include <kernel/task.H>


using namespace Systemcalls;

/**
 * System call to allocate a block of virtual memory within the base segment
 */
int mm_alloc_block(msg_q_t mq,void* va,uint64_t size)
{
    return (int64_t)_syscall3(MM_ALLOC_BLOCK, mq, va, (void*)size);
}

/**
 * System call to remove page(s) by a specified operation
 */
int mm_remove_pages(PAGE_REMOVAL_OPS i_op, void* i_vaddr, uint64_t i_size)
{
    return (int64_t)_syscall3(MM_REMOVE_PAGES, (void*)i_op, i_vaddr,
                              (void*)i_size);
}

/*
 * Call to flush out the instruction cache
 * From the PowerPC ISA book II, section 1.8
 *     Instruction Storage
 */
void mm_icache_invalidate(void * i_addr, size_t i_cpu_word_count)
{
    // Make sure 8 byte boundary
    uint64_t addr = (uint64_t)i_addr  & ~0x7ull;
    uint64_t * dest = (uint64_t*)addr;

    for(size_t i = 0; i < i_cpu_word_count; i += getCacheLineWords())
    {
        dcbst(dest);
        dest += getCacheLineWords();
    }

    lwsync();

    // According to core design team we only need to do a single icbi,
    // since the i-cache is kept coherent with the d-cache.  The single
    // icbi invalidates the "scoreboard" in the core which, in combination
    // with the isync, causes the core to go back out to l2-cache for any
    // instructions past this.
    icbi(reinterpret_cast<void*>(addr));
    isync();
}


/**
 * System call update permissions on a page for a given virtual address
 */
int mm_set_permission(void* va, uint64_t size, uint64_t access_type)
{
    return (int64_t)_syscall3(MM_SET_PERMISSION, va, (void*)size,  (void*)access_type);
}


/**
 * System call to return the physical address backing a virtual address
 */
uint64_t mm_virt_to_phys( void* i_vaddr )
{
    return (uint64_t) _syscall1(MM_VIRT_TO_PHYS,i_vaddr);
}

/**
 * System call to extend Memory to VMM_MEMORY_SIZE..
 */
int mm_extend(MM_EXTEND_SIZE i_size)
{
    return (int64_t)_syscall1(MM_EXTEND, reinterpret_cast<void*>(i_size));
}


/**
 * System call to create a block of memory at a specific physical address
 */
int mm_linear_map(void *i_paddr, uint64_t i_size)
{
    return (int64_t)_syscall2(MM_LINEAR_MAP, i_paddr, (void*)i_size);
}

/**
 * mm_tolerate_ue.  Update task state and do appropriate synchronization.
 */
void mm_tolerate_ue(uint64_t i_state)
{
    // Get task structure.
    register task_t* task;
    asm volatile("mr %0, 13" : "=r"(task));

    // Update task state.
    task->tolerate_ue = (i_state != 0);

    // Note: We do not need any sort of synchronization instructions here
    //       because the state is only used by the local HW thread which
    //       might be handling the machine check due to memory UE.  Any
    //       exception is a context synchronizing event which ensures
    //       that all preceding instructions have completed, so there
    //       are no visible effects of instruction reordering with respect
    //       to this state change.
}

/**
 * System call to map an arbitrary physical address into the VMM.
 */
void* mm_block_map(void* i_paddr, uint64_t i_size)
{
    return _syscall4(DEV_MAP, i_paddr, (void*)i_size, (void*)1, (void*)0);
}

/**
 * System call to map an arbitrary physical address into the VMM with guarded
 *     permissions to prevent out-of-order access to instructions and data
 */
void* mm_guarded_block_map(void* i_paddr, uint64_t i_size)
{
    return _syscall4(DEV_MAP, i_paddr, (void*)i_size, (void*)1, (void*)1);
}

/**
 * System call to unmap a previous mm_block_map.
 */
int mm_block_unmap(void* i_vaddr)
{
    return (int64_t) _syscall1(DEV_UNMAP, i_vaddr);
}
OpenPOWER on IntegriCloud