Merge branch 'linus' into perf/core, to pick up fixes

Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
Ingo Molnar 2017-03-16 09:50:50 +01:00
commit 2b95bd7d58
586 changed files with 7737 additions and 3452 deletions

View file

@ -0,0 +1,18 @@
/* Copyright (c) 2016 Facebook
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*/
#ifndef _UAPI__LINUX_BPF_PERF_EVENT_H__
#define _UAPI__LINUX_BPF_PERF_EVENT_H__
#include <linux/types.h>
#include <linux/ptrace.h>
struct bpf_perf_event_data {
struct pt_regs regs;
__u64 sample_period;
};
#endif /* _UAPI__LINUX_BPF_PERF_EVENT_H__ */

View file

@ -1387,7 +1387,7 @@ static bool pci_data_iowrite(u16 port, u32 mask, u32 val)
/* Allow writing to any other BAR, or expansion ROM */
iowrite(portoff, val, mask, &d->config_words[reg]);
return true;
/* We let them overide latency timer and cacheline size */
/* We let them override latency timer and cacheline size */
} else if (&d->config_words[reg] == (void *)&d->config.cacheline_size) {
/* Only let them change the first two fields. */
if (mask == 0xFFFFFFFF)

View file

@ -132,7 +132,7 @@ else
Q = @
endif
# Disable command line variables (CFLAGS) overide from top
# Disable command line variables (CFLAGS) override from top
# level Makefile (perf), otherwise build Makefile will get
# the same command line setup.
MAKEOVERRIDES=

View file

@ -135,7 +135,7 @@ else
Q = @
endif
# Disable command line variables (CFLAGS) overide from top
# Disable command line variables (CFLAGS) override from top
# level Makefile (perf), otherwise build Makefile will get
# the same command line setup.
MAKEOVERRIDES=

View file

@ -140,7 +140,7 @@ struct pevent_plugin_option {
* struct pevent_plugin_option PEVENT_PLUGIN_OPTIONS[] = {
* {
* .name = "option-name",
* .plugin_alias = "overide-file-name", (optional)
* .plugin_alias = "override-file-name", (optional)
* .description = "description of option to show users",
* },
* {

View file

@ -805,11 +805,20 @@ static struct rela *find_switch_table(struct objtool_file *file,
insn->jump_dest->offset > orig_insn->offset))
break;
/* look for a relocation which references .rodata */
text_rela = find_rela_by_dest_range(insn->sec, insn->offset,
insn->len);
if (text_rela && text_rela->sym == file->rodata->sym)
return find_rela_by_dest(file->rodata,
text_rela->addend);
if (!text_rela || text_rela->sym != file->rodata->sym)
continue;
/*
* Make sure the .rodata address isn't associated with a
* symbol. gcc jump tables are anonymous data.
*/
if (find_symbol_containing(file->rodata, text_rela->addend))
continue;
return find_rela_by_dest(file->rodata, text_rela->addend);
}
return NULL;

View file

@ -85,6 +85,18 @@ struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset)
return NULL;
}
struct symbol *find_symbol_containing(struct section *sec, unsigned long offset)
{
struct symbol *sym;
list_for_each_entry(sym, &sec->symbol_list, list)
if (sym->type != STT_SECTION &&
offset >= sym->offset && offset < sym->offset + sym->len)
return sym;
return NULL;
}
struct rela *find_rela_by_dest_range(struct section *sec, unsigned long offset,
unsigned int len)
{

View file

@ -79,6 +79,7 @@ struct elf {
struct elf *elf_open(const char *name);
struct section *find_section_by_name(struct elf *elf, const char *name);
struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset);
struct symbol *find_symbol_containing(struct section *sec, unsigned long offset);
struct rela *find_rela_by_dest(struct section *sec, unsigned long offset);
struct rela *find_rela_by_dest_range(struct section *sec, unsigned long offset,
unsigned int len);

View file

@ -31,7 +31,7 @@
#error Instruction buffer size too small
#endif
/* Based on branch_type() from perf_event_intel_lbr.c */
/* Based on branch_type() from arch/x86/events/intel/lbr.c */
static void intel_pt_insn_decoder(struct insn *insn,
struct intel_pt_insn *intel_pt_insn)
{

View file

@ -1880,6 +1880,7 @@ sub get_grub_index {
sub wait_for_input
{
my ($fp, $time) = @_;
my $start_time;
my $rin;
my $rout;
my $nr;
@ -1895,17 +1896,22 @@ sub wait_for_input
vec($rin, fileno($fp), 1) = 1;
vec($rin, fileno(\*STDIN), 1) = 1;
$start_time = time;
while (1) {
$nr = select($rout=$rin, undef, undef, $time);
if ($nr <= 0) {
return undef;
}
last if ($nr <= 0);
# copy data from stdin to the console
if (vec($rout, fileno(\*STDIN), 1) == 1) {
sysread(\*STDIN, $buf, 1000);
syswrite($fp, $buf, 1000);
$nr = sysread(\*STDIN, $buf, 1000);
syswrite($fp, $buf, $nr) if ($nr > 0);
}
# The timeout is based on time waiting for the fp data
if (vec($rout, fileno($fp), 1) != 1) {
last if (defined($time) && (time - $start_time > $time));
next;
}
@ -1917,12 +1923,11 @@ sub wait_for_input
last if ($ch eq "\n");
}
if (!length($line)) {
return undef;
}
last if (!length($line));
return $line;
}
return undef;
}
sub reboot_to {

View file

@ -1,6 +1,7 @@
CFLAGS += -I. -I../../include -g -O2 -Wall -D_LGPL_SOURCE -fsanitize=address
LDFLAGS += -lpthread -lurcu
LDFLAGS += -fsanitize=address
LDLIBS+= -lpthread -lurcu
TARGETS = main idr-test multiorder
CORE_OFILES := radix-tree.o idr.o linux.o test.o find_bit.o
OFILES = main.o $(CORE_OFILES) regression1.o regression2.o regression3.o \
@ -10,23 +11,25 @@ ifndef SHIFT
SHIFT=3
endif
ifeq ($(BUILD), 32)
CFLAGS += -m32
LDFLAGS += -m32
endif
targets: mapshift $(TARGETS)
main: $(OFILES)
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o main
idr-test: idr-test.o $(CORE_OFILES)
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o idr-test
multiorder: multiorder.o $(CORE_OFILES)
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o multiorder
clean:
$(RM) $(TARGETS) *.o radix-tree.c idr.c generated/map-shift.h
vpath %.c ../../lib
$(OFILES): *.h */*.h generated/map-shift.h \
$(OFILES): Makefile *.h */*.h generated/map-shift.h \
../../include/linux/*.h \
../../include/asm/*.h \
../../../include/linux/radix-tree.h \
@ -41,7 +44,7 @@ idr.c: ../../../lib/idr.c
.PHONY: mapshift
mapshift:
@if ! grep -qw $(SHIFT) generated/map-shift.h; then \
@if ! grep -qws $(SHIFT) generated/map-shift.h; then \
echo "#define RADIX_TREE_MAP_SHIFT $(SHIFT)" > \
generated/map-shift.h; \
fi

View file

@ -17,6 +17,9 @@
#include <time.h>
#include "test.h"
#define for_each_index(i, base, order) \
for (i = base; i < base + (1 << order); i++)
#define NSEC_PER_SEC 1000000000L
static long long benchmark_iter(struct radix_tree_root *root, bool tagged)
@ -57,27 +60,176 @@ again:
return nsec;
}
static void benchmark_insert(struct radix_tree_root *root,
unsigned long size, unsigned long step, int order)
{
struct timespec start, finish;
unsigned long index;
long long nsec;
clock_gettime(CLOCK_MONOTONIC, &start);
for (index = 0 ; index < size ; index += step)
item_insert_order(root, index, order);
clock_gettime(CLOCK_MONOTONIC, &finish);
nsec = (finish.tv_sec - start.tv_sec) * NSEC_PER_SEC +
(finish.tv_nsec - start.tv_nsec);
printv(2, "Size: %8ld, step: %8ld, order: %d, insertion: %15lld ns\n",
size, step, order, nsec);
}
static void benchmark_tagging(struct radix_tree_root *root,
unsigned long size, unsigned long step, int order)
{
struct timespec start, finish;
unsigned long index;
long long nsec;
clock_gettime(CLOCK_MONOTONIC, &start);
for (index = 0 ; index < size ; index += step)
radix_tree_tag_set(root, index, 0);
clock_gettime(CLOCK_MONOTONIC, &finish);
nsec = (finish.tv_sec - start.tv_sec) * NSEC_PER_SEC +
(finish.tv_nsec - start.tv_nsec);
printv(2, "Size: %8ld, step: %8ld, order: %d, tagging: %17lld ns\n",
size, step, order, nsec);
}
static void benchmark_delete(struct radix_tree_root *root,
unsigned long size, unsigned long step, int order)
{
struct timespec start, finish;
unsigned long index, i;
long long nsec;
clock_gettime(CLOCK_MONOTONIC, &start);
for (index = 0 ; index < size ; index += step)
for_each_index(i, index, order)
item_delete(root, i);
clock_gettime(CLOCK_MONOTONIC, &finish);
nsec = (finish.tv_sec - start.tv_sec) * NSEC_PER_SEC +
(finish.tv_nsec - start.tv_nsec);
printv(2, "Size: %8ld, step: %8ld, order: %d, deletion: %16lld ns\n",
size, step, order, nsec);
}
static void benchmark_size(unsigned long size, unsigned long step, int order)
{
RADIX_TREE(tree, GFP_KERNEL);
long long normal, tagged;
unsigned long index;
for (index = 0 ; index < size ; index += step) {
item_insert_order(&tree, index, order);
radix_tree_tag_set(&tree, index, 0);
}
benchmark_insert(&tree, size, step, order);
benchmark_tagging(&tree, size, step, order);
tagged = benchmark_iter(&tree, true);
normal = benchmark_iter(&tree, false);
printv(2, "Size %ld, step %6ld, order %d tagged %10lld ns, normal %10lld ns\n",
size, step, order, tagged, normal);
printv(2, "Size: %8ld, step: %8ld, order: %d, tagged iteration: %8lld ns\n",
size, step, order, tagged);
printv(2, "Size: %8ld, step: %8ld, order: %d, normal iteration: %8lld ns\n",
size, step, order, normal);
benchmark_delete(&tree, size, step, order);
item_kill_tree(&tree);
rcu_barrier();
}
static long long __benchmark_split(unsigned long index,
int old_order, int new_order)
{
struct timespec start, finish;
long long nsec;
RADIX_TREE(tree, GFP_ATOMIC);
item_insert_order(&tree, index, old_order);
clock_gettime(CLOCK_MONOTONIC, &start);
radix_tree_split(&tree, index, new_order);
clock_gettime(CLOCK_MONOTONIC, &finish);
nsec = (finish.tv_sec - start.tv_sec) * NSEC_PER_SEC +
(finish.tv_nsec - start.tv_nsec);
item_kill_tree(&tree);
return nsec;
}
static void benchmark_split(unsigned long size, unsigned long step)
{
int i, j, idx;
long long nsec = 0;
for (idx = 0; idx < size; idx += step) {
for (i = 3; i < 11; i++) {
for (j = 0; j < i; j++) {
nsec += __benchmark_split(idx, i, j);
}
}
}
printv(2, "Size %8ld, step %8ld, split time %10lld ns\n",
size, step, nsec);
}
static long long __benchmark_join(unsigned long index,
unsigned order1, unsigned order2)
{
unsigned long loc;
struct timespec start, finish;
long long nsec;
void *item, *item2 = item_create(index + 1, order1);
RADIX_TREE(tree, GFP_KERNEL);
item_insert_order(&tree, index, order2);
item = radix_tree_lookup(&tree, index);
clock_gettime(CLOCK_MONOTONIC, &start);
radix_tree_join(&tree, index + 1, order1, item2);
clock_gettime(CLOCK_MONOTONIC, &finish);
nsec = (finish.tv_sec - start.tv_sec) * NSEC_PER_SEC +
(finish.tv_nsec - start.tv_nsec);
loc = find_item(&tree, item);
if (loc == -1)
free(item);
item_kill_tree(&tree);
return nsec;
}
static void benchmark_join(unsigned long step)
{
int i, j, idx;
long long nsec = 0;
for (idx = 0; idx < 1 << 10; idx += step) {
for (i = 1; i < 15; i++) {
for (j = 0; j < i; j++) {
nsec += __benchmark_join(idx, i, j);
}
}
}
printv(2, "Size %8d, step %8ld, join time %10lld ns\n",
1 << 10, step, nsec);
}
void benchmark(void)
{
unsigned long size[] = {1 << 10, 1 << 20, 0};
@ -95,4 +247,11 @@ void benchmark(void)
for (c = 0; size[c]; c++)
for (s = 0; step[s]; s++)
benchmark_size(size[c], step[s] << 9, 9);
for (c = 0; size[c]; c++)
for (s = 0; step[s]; s++)
benchmark_split(size[c], step[s]);
for (s = 0; step[s]; s++)
benchmark_join(step[s]);
}

View file

@ -153,6 +153,30 @@ void idr_nowait_test(void)
idr_destroy(&idr);
}
void idr_get_next_test(void)
{
unsigned long i;
int nextid;
DEFINE_IDR(idr);
int indices[] = {4, 7, 9, 15, 65, 128, 1000, 99999, 0};
for(i = 0; indices[i]; i++) {
struct item *item = item_create(indices[i], 0);
assert(idr_alloc(&idr, item, indices[i], indices[i+1],
GFP_KERNEL) == indices[i]);
}
for(i = 0, nextid = 0; indices[i]; i++) {
idr_get_next(&idr, &nextid);
assert(nextid == indices[i]);
nextid++;
}
idr_for_each(&idr, item_idr_free, &idr);
idr_destroy(&idr);
}
void idr_checks(void)
{
unsigned long i;
@ -202,6 +226,7 @@ void idr_checks(void)
idr_alloc_test();
idr_null_test();
idr_nowait_test();
idr_get_next_test();
}
/*
@ -338,7 +363,7 @@ void ida_check_random(void)
{
DEFINE_IDA(ida);
DECLARE_BITMAP(bitmap, 2048);
int id;
int id, err;
unsigned int i;
time_t s = time(NULL);
@ -352,8 +377,11 @@ void ida_check_random(void)
ida_remove(&ida, bit);
} else {
__set_bit(bit, bitmap);
ida_pre_get(&ida, GFP_KERNEL);
assert(!ida_get_new_above(&ida, bit, &id));
do {
ida_pre_get(&ida, GFP_KERNEL);
err = ida_get_new_above(&ida, bit, &id);
} while (err == -ENOMEM);
assert(!err);
assert(id == bit);
}
}
@ -362,6 +390,24 @@ void ida_check_random(void)
goto repeat;
}
void ida_simple_get_remove_test(void)
{
DEFINE_IDA(ida);
unsigned long i;
for (i = 0; i < 10000; i++) {
assert(ida_simple_get(&ida, 0, 20000, GFP_KERNEL) == i);
}
assert(ida_simple_get(&ida, 5, 30, GFP_KERNEL) < 0);
for (i = 0; i < 10000; i++) {
ida_simple_remove(&ida, i);
}
assert(ida_is_empty(&ida));
ida_destroy(&ida);
}
void ida_checks(void)
{
DEFINE_IDA(ida);
@ -428,15 +474,41 @@ void ida_checks(void)
ida_check_max();
ida_check_conv();
ida_check_random();
ida_simple_get_remove_test();
radix_tree_cpu_dead(1);
}
static void *ida_random_fn(void *arg)
{
rcu_register_thread();
ida_check_random();
rcu_unregister_thread();
return NULL;
}
void ida_thread_tests(void)
{
pthread_t threads[10];
int i;
for (i = 0; i < ARRAY_SIZE(threads); i++)
if (pthread_create(&threads[i], NULL, ida_random_fn, NULL)) {
perror("creating ida thread");
exit(1);
}
while (i--)
pthread_join(threads[i], NULL);
}
int __weak main(void)
{
radix_tree_init();
idr_checks();
ida_checks();
ida_thread_tests();
radix_tree_cpu_dead(1);
rcu_barrier();
if (nr_allocated)
printf("nr_allocated = %d\n", nr_allocated);

View file

@ -368,6 +368,7 @@ int main(int argc, char **argv)
iteration_test(0, 10 + 90 * long_run);
iteration_test(7, 10 + 90 * long_run);
single_thread_tests(long_run);
ida_thread_tests();
/* Free any remaining preallocated nodes */
radix_tree_cpu_dead(0);

View file

@ -330,6 +330,34 @@ static void single_check(void)
item_kill_tree(&tree);
}
void radix_tree_clear_tags_test(void)
{
unsigned long index;
struct radix_tree_node *node;
struct radix_tree_iter iter;
void **slot;
RADIX_TREE(tree, GFP_KERNEL);
item_insert(&tree, 0);
item_tag_set(&tree, 0, 0);
__radix_tree_lookup(&tree, 0, &node, &slot);
radix_tree_clear_tags(&tree, node, slot);
assert(item_tag_get(&tree, 0, 0) == 0);
for (index = 0; index < 1000; index++) {
item_insert(&tree, index);
item_tag_set(&tree, index, 0);
}
radix_tree_for_each_slot(slot, &tree, &iter, 0) {
radix_tree_clear_tags(&tree, iter.node, slot);
assert(item_tag_get(&tree, iter.index, 0) == 0);
}
item_kill_tree(&tree);
}
void tag_check(void)
{
single_check();
@ -347,4 +375,5 @@ void tag_check(void)
thrash_tags();
rcu_barrier();
printv(2, "after thrash_tags: %d allocated\n", nr_allocated);
radix_tree_clear_tags_test();
}

View file

@ -36,6 +36,7 @@ void iteration_test(unsigned order, unsigned duration);
void benchmark(void);
void idr_checks(void);
void ida_checks(void);
void ida_thread_tests(void);
struct item *
item_tag_set(struct radix_tree_root *root, unsigned long index, int tag);

View file

@ -1,12 +1,14 @@
LIBDIR := ../../../lib
BPFOBJ := $(LIBDIR)/bpf/bpf.o
CFLAGS += -Wall -O2 -lcap -I../../../include/uapi -I$(LIBDIR)
CFLAGS += -Wall -O2 -lcap -I../../../include/uapi -I$(LIBDIR) $(BPFOBJ)
TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map
TEST_PROGS := test_kmod.sh
all: $(TEST_GEN_PROGS)
.PHONY: all clean force
# force a rebuild of BPFOBJ when its dependencies are updated

View file

@ -8,6 +8,8 @@
* License as published by the Free Software Foundation.
*/
#include <asm/types.h>
#include <linux/types.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@ -4583,10 +4585,12 @@ static bool is_admin(void)
cap_flag_value_t sysadmin = CAP_CLEAR;
const cap_value_t cap_val = CAP_SYS_ADMIN;
#ifdef CAP_IS_SUPPORTED
if (!CAP_IS_SUPPORTED(CAP_SETFCAP)) {
perror("cap_get_flag");
return false;
}
#endif
caps = cap_get_proc();
if (!caps) {
perror("cap_get_proc");

View file

@ -114,9 +114,11 @@ int test_harness(int (test_function)(void), char *name)
rc = run_test(test_function, name);
if (rc == MAGIC_SKIP_RETURN_VALUE)
if (rc == MAGIC_SKIP_RETURN_VALUE) {
test_skip(name);
else
/* so that skipped test is not marked as failed */
rc = 0;
} else
test_finish(name, rc);
return rc;

View file

@ -16,56 +16,56 @@
*/
FUNC_START(load_vsx)
li r5,0
lxvx vs20,r5,r3
lxvd2x vs20,r5,r3
addi r5,r5,16
lxvx vs21,r5,r3
lxvd2x vs21,r5,r3
addi r5,r5,16
lxvx vs22,r5,r3
lxvd2x vs22,r5,r3
addi r5,r5,16
lxvx vs23,r5,r3
lxvd2x vs23,r5,r3
addi r5,r5,16
lxvx vs24,r5,r3
lxvd2x vs24,r5,r3
addi r5,r5,16
lxvx vs25,r5,r3
lxvd2x vs25,r5,r3
addi r5,r5,16
lxvx vs26,r5,r3
lxvd2x vs26,r5,r3
addi r5,r5,16
lxvx vs27,r5,r3
lxvd2x vs27,r5,r3
addi r5,r5,16
lxvx vs28,r5,r3
lxvd2x vs28,r5,r3
addi r5,r5,16
lxvx vs29,r5,r3
lxvd2x vs29,r5,r3
addi r5,r5,16
lxvx vs30,r5,r3
lxvd2x vs30,r5,r3
addi r5,r5,16
lxvx vs31,r5,r3
lxvd2x vs31,r5,r3
blr
FUNC_END(load_vsx)
FUNC_START(store_vsx)
li r5,0
stxvx vs20,r5,r3
stxvd2x vs20,r5,r3
addi r5,r5,16
stxvx vs21,r5,r3
stxvd2x vs21,r5,r3
addi r5,r5,16
stxvx vs22,r5,r3
stxvd2x vs22,r5,r3
addi r5,r5,16
stxvx vs23,r5,r3
stxvd2x vs23,r5,r3
addi r5,r5,16
stxvx vs24,r5,r3
stxvd2x vs24,r5,r3
addi r5,r5,16
stxvx vs25,r5,r3
stxvd2x vs25,r5,r3
addi r5,r5,16
stxvx vs26,r5,r3
stxvd2x vs26,r5,r3
addi r5,r5,16
stxvx vs27,r5,r3
stxvd2x vs27,r5,r3
addi r5,r5,16
stxvx vs28,r5,r3
stxvd2x vs28,r5,r3
addi r5,r5,16
stxvx vs29,r5,r3
stxvd2x vs29,r5,r3
addi r5,r5,16
stxvx vs30,r5,r3
stxvd2x vs30,r5,r3
addi r5,r5,16
stxvx vs31,r5,r3
stxvd2x vs31,r5,r3
blr
FUNC_END(store_vsx)

View file

@ -1,5 +1,9 @@
# Makefile for vm selftests
ifndef OUTPUT
OUTPUT := $(shell pwd)
endif
CFLAGS = -Wall -I ../../../../usr/include $(EXTRA_CFLAGS)
LDLIBS = -lrt
TEST_GEN_FILES = compaction_test

View file

@ -245,7 +245,7 @@ void do_unexpected_base(void)
long ret;
asm volatile ("int $0x80"
: "=a" (ret) : "a" (243), "b" (low_desc)
: "flags");
: "r8", "r9", "r10", "r11");
memcpy(&desc, low_desc, sizeof(desc));
munmap(low_desc, sizeof(desc));

View file

@ -45,6 +45,12 @@
#define AR_DB (1 << 22)
#define AR_G (1 << 23)
#ifdef __x86_64__
# define INT80_CLOBBERS "r8", "r9", "r10", "r11"
#else
# define INT80_CLOBBERS
#endif
static int nerrs;
/* Points to an array of 1024 ints, each holding its own index. */
@ -588,7 +594,7 @@ static int invoke_set_thread_area(void)
asm volatile ("int $0x80"
: "=a" (ret), "+m" (low_user_desc) :
"a" (243), "b" (low_user_desc)
: "flags");
: INT80_CLOBBERS);
return ret;
}
@ -657,7 +663,7 @@ static void test_gdt_invalidation(void)
"+a" (eax)
: "m" (low_user_desc_clear),
[arg1] "r" ((unsigned int)(unsigned long)low_user_desc_clear)
: "flags");
: INT80_CLOBBERS);
if (sel != 0) {
result = "FAIL";
@ -688,7 +694,7 @@ static void test_gdt_invalidation(void)
"+a" (eax)
: "m" (low_user_desc_clear),
[arg1] "r" ((unsigned int)(unsigned long)low_user_desc_clear)
: "flags");
: INT80_CLOBBERS);
if (sel != 0) {
result = "FAIL";
@ -721,7 +727,7 @@ static void test_gdt_invalidation(void)
"+a" (eax)
: "m" (low_user_desc_clear),
[arg1] "r" ((unsigned int)(unsigned long)low_user_desc_clear)
: "flags");
: INT80_CLOBBERS);
#ifdef __x86_64__
syscall(SYS_arch_prctl, ARCH_GET_FS, &new_base);
@ -774,7 +780,7 @@ static void test_gdt_invalidation(void)
"+a" (eax)
: "m" (low_user_desc_clear),
[arg1] "r" ((unsigned int)(unsigned long)low_user_desc_clear)
: "flags");
: INT80_CLOBBERS);
#ifdef __x86_64__
syscall(SYS_arch_prctl, ARCH_GET_GS, &new_base);

View file

@ -58,7 +58,8 @@ static void do_full_int80(struct syscall_args32 *args)
asm volatile ("int $0x80"
: "+a" (args->nr),
"+b" (args->arg0), "+c" (args->arg1), "+d" (args->arg2),
"+S" (args->arg3), "+D" (args->arg4), "+r" (bp));
"+S" (args->arg3), "+D" (args->arg4), "+r" (bp)
: : "r8", "r9", "r10", "r11");
args->arg5 = bp;
#else
sys32_helper(args, int80_and_ret);

View file

@ -56,9 +56,11 @@ static volatile sig_atomic_t sig_traps;
#ifdef __x86_64__
# define REG_IP REG_RIP
# define WIDTH "q"
# define INT80_CLOBBERS "r8", "r9", "r10", "r11"
#else
# define REG_IP REG_EIP
# define WIDTH "l"
# define INT80_CLOBBERS
#endif
static unsigned long get_eflags(void)
@ -140,7 +142,8 @@ int main()
printf("[RUN]\tSet TF and check int80\n");
set_eflags(get_eflags() | X86_EFLAGS_TF);
asm volatile ("int $0x80" : "=a" (tmp) : "a" (SYS_getpid));
asm volatile ("int $0x80" : "=a" (tmp) : "a" (SYS_getpid)
: INT80_CLOBBERS);
check_result();
/*