blob: c2ef1129f553dff3e91162f5dcb22ac6032873de [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* 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.
*/
#include <syscall.h>
#include <heap.h>
typedef uintptr_t (*UserspaceCbkF)(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
static uintptr_t doUserspaceCall(uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4, UserspaceCbkF cbk);
struct UserspaceCallback
{
UserspaceCbkF f;
uintptr_t p1;
uintptr_t p2;
uintptr_t p3;
uintptr_t p4;
};
struct UserspaceCallback* syscallUserspaceCallbackAlloc(void *func, uintptr_t param1, uintptr_t param2, uintptr_t param3, uintptr_t param4)
{
struct UserspaceCallback *ucbk = heapAlloc(sizeof(struct UserspaceCallback));
if (ucbk) {
ucbk->f = (UserspaceCbkF)func;
ucbk->p1 = param1;
ucbk->p2 = param2;
ucbk->p3 = param3;
ucbk->p4 = param4;
}
return ucbk;
}
void syscallUserspaceCallbackFree(struct UserspaceCallback *ucbk)
{
heapFree(ucbk);
}
uintptr_t syscallUserspaceCallbackCall(struct UserspaceCallback *ucbk, const uintptr_t *overrideParam1P, const uintptr_t *overrideParam2P, const uintptr_t *overrideParam3P, const uintptr_t *overrideParam4P)
{
uintptr_t p1 = overrideParam1P ? *overrideParam1P : ucbk->p1;
uintptr_t p2 = overrideParam1P ? *overrideParam2P : ucbk->p2;
uintptr_t p3 = overrideParam1P ? *overrideParam3P : ucbk->p3;
uintptr_t p4 = overrideParam1P ? *overrideParam4P : ucbk->p4;
return doUserspaceCall(p1, p2, p3, p4, ucbk->f);
}
/* soon this will be a behemoth of a function, dealing with context switches and all, for now it is simple */
static uintptr_t __attribute__((naked)) doUserspaceCall(uintptr_t p1, uintptr_t p2, uintptr_t p3, uintptr_t p4, UserspaceCbkF cbk)
{
asm volatile (
"ldr pc, [sp] \n"
);
/* not reached, just here to make gcc happy */
return 0;
}