M7350v1_en_gpl

This commit is contained in:
T
2024-09-09 08:52:07 +00:00
commit f9cc65cfda
65988 changed files with 26357421 additions and 0 deletions
+16
View File
@@ -0,0 +1,16 @@
TARGETS = breakpoints vm
all:
for TARGET in $(TARGETS); do \
make -C $$TARGET; \
done;
run_tests: all
for TARGET in $(TARGETS); do \
make -C $$TARGET run_tests; \
done;
clean:
for TARGET in $(TARGETS); do \
make -C $$TARGET clean; \
done;
@@ -0,0 +1,23 @@
# Taken from perf makefile
uname_M := $(shell uname -m 2>/dev/null || echo not)
ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/)
ifeq ($(ARCH),i386)
ARCH := x86
endif
ifeq ($(ARCH),x86_64)
ARCH := x86
endif
all:
ifeq ($(ARCH),x86)
gcc breakpoint_test.c -o breakpoint_test
else
echo "Not an x86 target, can't build breakpoints selftests"
endif
run_tests:
./breakpoint_test
clean:
rm -fr breakpoint_test
@@ -0,0 +1,394 @@
/*
* Copyright (C) 2011 Red Hat, Inc., Frederic Weisbecker <fweisbec@redhat.com>
*
* Licensed under the terms of the GNU GPL License version 2
*
* Selftests for breakpoints (and more generally the do_debug() path) in x86.
*/
#include <sys/ptrace.h>
#include <unistd.h>
#include <stddef.h>
#include <sys/user.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
/* Breakpoint access modes */
enum {
BP_X = 1,
BP_RW = 2,
BP_W = 4,
};
static pid_t child_pid;
/*
* Ensures the child and parent are always "talking" about
* the same test sequence. (ie: that we haven't forgotten
* to call check_trapped() somewhere).
*/
static int nr_tests;
static void set_breakpoint_addr(void *addr, int n)
{
int ret;
ret = ptrace(PTRACE_POKEUSER, child_pid,
offsetof(struct user, u_debugreg[n]), addr);
if (ret) {
perror("Can't set breakpoint addr\n");
exit(-1);
}
}
static void toggle_breakpoint(int n, int type, int len,
int local, int global, int set)
{
int ret;
int xtype, xlen;
unsigned long vdr7, dr7;
switch (type) {
case BP_X:
xtype = 0;
break;
case BP_W:
xtype = 1;
break;
case BP_RW:
xtype = 3;
break;
}
switch (len) {
case 1:
xlen = 0;
break;
case 2:
xlen = 4;
break;
case 4:
xlen = 0xc;
break;
case 8:
xlen = 8;
break;
}
dr7 = ptrace(PTRACE_PEEKUSER, child_pid,
offsetof(struct user, u_debugreg[7]), 0);
vdr7 = (xlen | xtype) << 16;
vdr7 <<= 4 * n;
if (local) {
vdr7 |= 1 << (2 * n);
vdr7 |= 1 << 8;
}
if (global) {
vdr7 |= 2 << (2 * n);
vdr7 |= 1 << 9;
}
if (set)
dr7 |= vdr7;
else
dr7 &= ~vdr7;
ret = ptrace(PTRACE_POKEUSER, child_pid,
offsetof(struct user, u_debugreg[7]), dr7);
if (ret) {
perror("Can't set dr7");
exit(-1);
}
}
/* Dummy variables to test read/write accesses */
static unsigned long long dummy_var[4];
/* Dummy functions to test execution accesses */
static void dummy_func(void) { }
static void dummy_func1(void) { }
static void dummy_func2(void) { }
static void dummy_func3(void) { }
static void (*dummy_funcs[])(void) = {
dummy_func,
dummy_func1,
dummy_func2,
dummy_func3,
};
static int trapped;
static void check_trapped(void)
{
/*
* If we haven't trapped, wake up the parent
* so that it notices the failure.
*/
if (!trapped)
kill(getpid(), SIGUSR1);
trapped = 0;
nr_tests++;
}
static void write_var(int len)
{
char *pcval; short *psval; int *pival; long long *plval;
int i;
for (i = 0; i < 4; i++) {
switch (len) {
case 1:
pcval = (char *)&dummy_var[i];
*pcval = 0xff;
break;
case 2:
psval = (short *)&dummy_var[i];
*psval = 0xffff;
break;
case 4:
pival = (int *)&dummy_var[i];
*pival = 0xffffffff;
break;
case 8:
plval = (long long *)&dummy_var[i];
*plval = 0xffffffffffffffffLL;
break;
}
check_trapped();
}
}
static void read_var(int len)
{
char cval; short sval; int ival; long long lval;
int i;
for (i = 0; i < 4; i++) {
switch (len) {
case 1:
cval = *(char *)&dummy_var[i];
break;
case 2:
sval = *(short *)&dummy_var[i];
break;
case 4:
ival = *(int *)&dummy_var[i];
break;
case 8:
lval = *(long long *)&dummy_var[i];
break;
}
check_trapped();
}
}
/*
* Do the r/w/x accesses to trigger the breakpoints. And run
* the usual traps.
*/
static void trigger_tests(void)
{
int len, local, global, i;
char val;
int ret;
ret = ptrace(PTRACE_TRACEME, 0, NULL, 0);
if (ret) {
perror("Can't be traced?\n");
return;
}
/* Wake up father so that it sets up the first test */
kill(getpid(), SIGUSR1);
/* Test instruction breakpoints */
for (local = 0; local < 2; local++) {
for (global = 0; global < 2; global++) {
if (!local && !global)
continue;
for (i = 0; i < 4; i++) {
dummy_funcs[i]();
check_trapped();
}
}
}
/* Test write watchpoints */
for (len = 1; len <= sizeof(long); len <<= 1) {
for (local = 0; local < 2; local++) {
for (global = 0; global < 2; global++) {
if (!local && !global)
continue;
write_var(len);
}
}
}
/* Test read/write watchpoints (on read accesses) */
for (len = 1; len <= sizeof(long); len <<= 1) {
for (local = 0; local < 2; local++) {
for (global = 0; global < 2; global++) {
if (!local && !global)
continue;
read_var(len);
}
}
}
/* Icebp trap */
asm(".byte 0xf1\n");
check_trapped();
/* Int 3 trap */
asm("int $3\n");
check_trapped();
kill(getpid(), SIGUSR1);
}
static void check_success(const char *msg)
{
const char *msg2;
int child_nr_tests;
int status;
/* Wait for the child to SIGTRAP */
wait(&status);
msg2 = "Failed";
if (WSTOPSIG(status) == SIGTRAP) {
child_nr_tests = ptrace(PTRACE_PEEKDATA, child_pid,
&nr_tests, 0);
if (child_nr_tests == nr_tests)
msg2 = "Ok";
if (ptrace(PTRACE_POKEDATA, child_pid, &trapped, 1)) {
perror("Can't poke\n");
exit(-1);
}
}
nr_tests++;
printf("%s [%s]\n", msg, msg2);
}
static void launch_instruction_breakpoints(char *buf, int local, int global)
{
int i;
for (i = 0; i < 4; i++) {
set_breakpoint_addr(dummy_funcs[i], i);
toggle_breakpoint(i, BP_X, 1, local, global, 1);
ptrace(PTRACE_CONT, child_pid, NULL, 0);
sprintf(buf, "Test breakpoint %d with local: %d global: %d",
i, local, global);
check_success(buf);
toggle_breakpoint(i, BP_X, 1, local, global, 0);
}
}
static void launch_watchpoints(char *buf, int mode, int len,
int local, int global)
{
const char *mode_str;
int i;
if (mode == BP_W)
mode_str = "write";
else
mode_str = "read";
for (i = 0; i < 4; i++) {
set_breakpoint_addr(&dummy_var[i], i);
toggle_breakpoint(i, mode, len, local, global, 1);
ptrace(PTRACE_CONT, child_pid, NULL, 0);
sprintf(buf, "Test %s watchpoint %d with len: %d local: "
"%d global: %d", mode_str, i, len, local, global);
check_success(buf);
toggle_breakpoint(i, mode, len, local, global, 0);
}
}
/* Set the breakpoints and check the child successfully trigger them */
static void launch_tests(void)
{
char buf[1024];
int len, local, global, i;
/* Instruction breakpoints */
for (local = 0; local < 2; local++) {
for (global = 0; global < 2; global++) {
if (!local && !global)
continue;
launch_instruction_breakpoints(buf, local, global);
}
}
/* Write watchpoint */
for (len = 1; len <= sizeof(long); len <<= 1) {
for (local = 0; local < 2; local++) {
for (global = 0; global < 2; global++) {
if (!local && !global)
continue;
launch_watchpoints(buf, BP_W, len,
local, global);
}
}
}
/* Read-Write watchpoint */
for (len = 1; len <= sizeof(long); len <<= 1) {
for (local = 0; local < 2; local++) {
for (global = 0; global < 2; global++) {
if (!local && !global)
continue;
launch_watchpoints(buf, BP_RW, len,
local, global);
}
}
}
/* Icebp traps */
ptrace(PTRACE_CONT, child_pid, NULL, 0);
check_success("Test icebp");
/* Int 3 traps */
ptrace(PTRACE_CONT, child_pid, NULL, 0);
check_success("Test int 3 trap");
ptrace(PTRACE_CONT, child_pid, NULL, 0);
}
int main(int argc, char **argv)
{
pid_t pid;
int ret;
pid = fork();
if (!pid) {
trigger_tests();
return 0;
}
child_pid = pid;
wait(NULL);
launch_tests();
wait(NULL);
return 0;
}
@@ -0,0 +1,14 @@
# Makefile for vm selftests
CC = $(CROSS_COMPILE)gcc
CFLAGS = -Wall -Wextra
all: hugepage-mmap hugepage-shm map_hugetlb
%: %.c
$(CC) $(CFLAGS) -o $@ $^
run_tests: all
/bin/sh ./run_vmtests
clean:
$(RM) hugepage-mmap hugepage-shm map_hugetlb
@@ -0,0 +1,92 @@
/*
* hugepage-mmap:
*
* Example of using huge page memory in a user application using the mmap
* system call. Before running this application, make sure that the
* administrator has mounted the hugetlbfs filesystem (on some directory
* like /mnt) using the command mount -t hugetlbfs nodev /mnt. In this
* example, the app is requesting memory of size 256MB that is backed by
* huge pages.
*
* For the ia64 architecture, the Linux kernel reserves Region number 4 for
* huge pages. That means that if one requires a fixed address, a huge page
* aligned address starting with 0x800000... will be required. If a fixed
* address is not required, the kernel will select an address in the proper
* range.
* Other architectures, such as ppc64, i386 or x86_64 are not so constrained.
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#define FILE_NAME "huge/hugepagefile"
#define LENGTH (256UL*1024*1024)
#define PROTECTION (PROT_READ | PROT_WRITE)
/* Only ia64 requires this */
#ifdef __ia64__
#define ADDR (void *)(0x8000000000000000UL)
#define FLAGS (MAP_SHARED | MAP_FIXED)
#else
#define ADDR (void *)(0x0UL)
#define FLAGS (MAP_SHARED)
#endif
static void check_bytes(char *addr)
{
printf("First hex is %x\n", *((unsigned int *)addr));
}
static void write_bytes(char *addr)
{
unsigned long i;
for (i = 0; i < LENGTH; i++)
*(addr + i) = (char)i;
}
static int read_bytes(char *addr)
{
unsigned long i;
check_bytes(addr);
for (i = 0; i < LENGTH; i++)
if (*(addr + i) != (char)i) {
printf("Mismatch at %lu\n", i);
return 1;
}
return 0;
}
int main(void)
{
void *addr;
int fd, ret;
fd = open(FILE_NAME, O_CREAT | O_RDWR, 0755);
if (fd < 0) {
perror("Open failed");
exit(1);
}
addr = mmap(ADDR, LENGTH, PROTECTION, FLAGS, fd, 0);
if (addr == MAP_FAILED) {
perror("mmap");
unlink(FILE_NAME);
exit(1);
}
printf("Returned address is %p\n", addr);
check_bytes(addr);
write_bytes(addr);
ret = read_bytes(addr);
munmap(addr, LENGTH);
close(fd);
unlink(FILE_NAME);
return ret;
}
@@ -0,0 +1,100 @@
/*
* hugepage-shm:
*
* Example of using huge page memory in a user application using Sys V shared
* memory system calls. In this example the app is requesting 256MB of
* memory that is backed by huge pages. The application uses the flag
* SHM_HUGETLB in the shmget system call to inform the kernel that it is
* requesting huge pages.
*
* For the ia64 architecture, the Linux kernel reserves Region number 4 for
* huge pages. That means that if one requires a fixed address, a huge page
* aligned address starting with 0x800000... will be required. If a fixed
* address is not required, the kernel will select an address in the proper
* range.
* Other architectures, such as ppc64, i386 or x86_64 are not so constrained.
*
* Note: The default shared memory limit is quite low on many kernels,
* you may need to increase it via:
*
* echo 268435456 > /proc/sys/kernel/shmmax
*
* This will increase the maximum size per shared memory segment to 256MB.
* The other limit that you will hit eventually is shmall which is the
* total amount of shared memory in pages. To set it to 16GB on a system
* with a 4kB pagesize do:
*
* echo 4194304 > /proc/sys/kernel/shmall
*/
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/mman.h>
#ifndef SHM_HUGETLB
#define SHM_HUGETLB 04000
#endif
#define LENGTH (256UL*1024*1024)
#define dprintf(x) printf(x)
/* Only ia64 requires this */
#ifdef __ia64__
#define ADDR (void *)(0x8000000000000000UL)
#define SHMAT_FLAGS (SHM_RND)
#else
#define ADDR (void *)(0x0UL)
#define SHMAT_FLAGS (0)
#endif
int main(void)
{
int shmid;
unsigned long i;
char *shmaddr;
shmid = shmget(2, LENGTH, SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W);
if (shmid < 0) {
perror("shmget");
exit(1);
}
printf("shmid: 0x%x\n", shmid);
shmaddr = shmat(shmid, ADDR, SHMAT_FLAGS);
if (shmaddr == (char *)-1) {
perror("Shared memory attach failure");
shmctl(shmid, IPC_RMID, NULL);
exit(2);
}
printf("shmaddr: %p\n", shmaddr);
dprintf("Starting the writes:\n");
for (i = 0; i < LENGTH; i++) {
shmaddr[i] = (char)(i);
if (!(i % (1024 * 1024)))
dprintf(".");
}
dprintf("\n");
dprintf("Starting the Check...");
for (i = 0; i < LENGTH; i++)
if (shmaddr[i] != (char)i) {
printf("\nIndex %lu mismatched\n", i);
exit(3);
}
dprintf("Done.\n");
if (shmdt((const void *)shmaddr) != 0) {
perror("Detach failure");
shmctl(shmid, IPC_RMID, NULL);
exit(4);
}
shmctl(shmid, IPC_RMID, NULL);
return 0;
}
@@ -0,0 +1,79 @@
/*
* Example of using hugepage memory in a user application using the mmap
* system call with MAP_HUGETLB flag. Before running this program make
* sure the administrator has allocated enough default sized huge pages
* to cover the 256 MB allocation.
*
* For ia64 architecture, Linux kernel reserves Region number 4 for hugepages.
* That means the addresses starting with 0x800000... will need to be
* specified. Specifying a fixed address is not required on ppc64, i386
* or x86_64.
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#define LENGTH (256UL*1024*1024)
#define PROTECTION (PROT_READ | PROT_WRITE)
#ifndef MAP_HUGETLB
#define MAP_HUGETLB 0x40000 /* arch specific */
#endif
/* Only ia64 requires this */
#ifdef __ia64__
#define ADDR (void *)(0x8000000000000000UL)
#define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_FIXED)
#else
#define ADDR (void *)(0x0UL)
#define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB)
#endif
static void check_bytes(char *addr)
{
printf("First hex is %x\n", *((unsigned int *)addr));
}
static void write_bytes(char *addr)
{
unsigned long i;
for (i = 0; i < LENGTH; i++)
*(addr + i) = (char)i;
}
static int read_bytes(char *addr)
{
unsigned long i;
check_bytes(addr);
for (i = 0; i < LENGTH; i++)
if (*(addr + i) != (char)i) {
printf("Mismatch at %lu\n", i);
return 1;
}
return 0;
}
int main(void)
{
void *addr;
int ret;
addr = mmap(ADDR, LENGTH, PROTECTION, FLAGS, 0, 0);
if (addr == MAP_FAILED) {
perror("mmap");
exit(1);
}
printf("Returned address is %p\n", addr);
check_bytes(addr);
write_bytes(addr);
ret = read_bytes(addr);
munmap(addr, LENGTH);
return ret;
}
@@ -0,0 +1,77 @@
#!/bin/bash
#please run as root
#we need 256M, below is the size in kB
needmem=262144
mnt=./huge
#get pagesize and freepages from /proc/meminfo
while read name size unit; do
if [ "$name" = "HugePages_Free:" ]; then
freepgs=$size
fi
if [ "$name" = "Hugepagesize:" ]; then
pgsize=$size
fi
done < /proc/meminfo
#set proper nr_hugepages
if [ -n "$freepgs" ] && [ -n "$pgsize" ]; then
nr_hugepgs=`cat /proc/sys/vm/nr_hugepages`
needpgs=`expr $needmem / $pgsize`
if [ $freepgs -lt $needpgs ]; then
lackpgs=$(( $needpgs - $freepgs ))
echo $(( $lackpgs + $nr_hugepgs )) > /proc/sys/vm/nr_hugepages
if [ $? -ne 0 ]; then
echo "Please run this test as root"
exit 1
fi
fi
else
echo "no hugetlbfs support in kernel?"
exit 1
fi
mkdir $mnt
mount -t hugetlbfs none $mnt
echo "--------------------"
echo "runing hugepage-mmap"
echo "--------------------"
./hugepage-mmap
if [ $? -ne 0 ]; then
echo "[FAIL]"
else
echo "[PASS]"
fi
shmmax=`cat /proc/sys/kernel/shmmax`
shmall=`cat /proc/sys/kernel/shmall`
echo 268435456 > /proc/sys/kernel/shmmax
echo 4194304 > /proc/sys/kernel/shmall
echo "--------------------"
echo "runing hugepage-shm"
echo "--------------------"
./hugepage-shm
if [ $? -ne 0 ]; then
echo "[FAIL]"
else
echo "[PASS]"
fi
echo $shmmax > /proc/sys/kernel/shmmax
echo $shmall > /proc/sys/kernel/shmall
echo "--------------------"
echo "runing map_hugetlb"
echo "--------------------"
./map_hugetlb
if [ $? -ne 0 ]; then
echo "[FAIL]"
else
echo "[PASS]"
fi
#cleanup
umount $mnt
rm -rf $mnt
echo $nr_hugepgs > /proc/sys/vm/nr_hugepages