Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags   |
// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/mman.h>
#include <longjmp.h>
#ifdef __i386__
static jmp_buf buf;
static void segfault(int sig)
{
<------>longjmp(buf, 1);
}
static int page_ok(unsigned long page)
{
<------>unsigned long *address = (unsigned long *) (page << UM_KERN_PAGE_SHIFT);
<------>unsigned long n = ~0UL;
<------>void *mapped = NULL;
<------>int ok = 0;
<------>/*
<------> * First see if the page is readable. If it is, it may still
<------> * be a VDSO, so we go on to see if it's writable. If not
<------> * then try mapping memory there. If that fails, then we're
<------> * still in the kernel area. As a sanity check, we'll fail if
<------> * the mmap succeeds, but gives us an address different from
<------> * what we wanted.
<------> */
<------>if (setjmp(buf) == 0)
<------><------>n = *address;
<------>else {
<------><------>mapped = mmap(address, UM_KERN_PAGE_SIZE,
<------><------><------> PROT_READ | PROT_WRITE,
<------><------><------> MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
<------><------>if (mapped == MAP_FAILED)
<------><------><------>return 0;
<------><------>if (mapped != address)
<------><------><------>goto out;
<------>}
<------>/*
<------> * Now, is it writeable? If so, then we're in user address
<------> * space. If not, then try mprotecting it and try the write
<------> * again.
<------> */
<------>if (setjmp(buf) == 0) {
<------><------>*address = n;
<------><------>ok = 1;
<------><------>goto out;
<------>} else if (mprotect(address, UM_KERN_PAGE_SIZE,
<------><------><------> PROT_READ | PROT_WRITE) != 0)
<------><------>goto out;
<------>if (setjmp(buf) == 0) {
<------><------>*address = n;
<------><------>ok = 1;
<------>}
out:
<------>if (mapped != NULL)
<------><------>munmap(mapped, UM_KERN_PAGE_SIZE);
<------>return ok;
}
unsigned long os_get_top_address(void)
{
<------>struct sigaction sa, old;
<------>unsigned long bottom = 0;
<------>/*
<------> * A 32-bit UML on a 64-bit host gets confused about the VDSO at
<------> * 0xffffe000. It is mapped, is readable, can be reprotected writeable
<------> * and written. However, exec discovers later that it can't be
<------> * unmapped. So, just set the highest address to be checked to just
<------> * below it. This might waste some address space on 4G/4G 32-bit
<------> * hosts, but shouldn't hurt otherwise.
<------> */
<------>unsigned long top = 0xffffd000 >> UM_KERN_PAGE_SHIFT;
<------>unsigned long test, original;
<------>printf("Locating the bottom of the address space ... ");
<------>fflush(stdout);
<------>/*
<------> * We're going to be longjmping out of the signal handler, so
<------> * SA_DEFER needs to be set.
<------> */
<------>sa.sa_handler = segfault;
<------>sigemptyset(&sa.sa_mask);
<------>sa.sa_flags = SA_NODEFER;
<------>if (sigaction(SIGSEGV, &sa, &old)) {
<------><------>perror("os_get_top_address");
<------><------>exit(1);
<------>}
<------>/* Manually scan the address space, bottom-up, until we find
<------> * the first valid page (or run out of them).
<------> */
<------>for (bottom = 0; bottom < top; bottom++) {
<------><------>if (page_ok(bottom))
<------><------><------>break;
<------>}
<------>/* If we've got this far, we ran out of pages. */
<------>if (bottom == top) {
<------><------>fprintf(stderr, "Unable to determine bottom of address "
<------><------><------>"space.\n");
<------><------>exit(1);
<------>}
<------>printf("0x%lx\n", bottom << UM_KERN_PAGE_SHIFT);
<------>printf("Locating the top of the address space ... ");
<------>fflush(stdout);
<------>original = bottom;
<------>/* This could happen with a 4G/4G split */
<------>if (page_ok(top))
<------><------>goto out;
<------>do {
<------><------>test = bottom + (top - bottom) / 2;
<------><------>if (page_ok(test))
<------><------><------>bottom = test;
<------><------>else
<------><------><------>top = test;
<------>} while (top - bottom > 1);
out:
<------>/* Restore the old SIGSEGV handling */
<------>if (sigaction(SIGSEGV, &old, NULL)) {
<------><------>perror("os_get_top_address");
<------><------>exit(1);
<------>}
<------>top <<= UM_KERN_PAGE_SHIFT;
<------>printf("0x%lx\n", top);
<------>return top;
}
#else
unsigned long os_get_top_address(void)
{
<------>/* The old value of CONFIG_TOP_ADDR */
<------>return 0x7fc0000000;
}
#endif