Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
@@ -66,7 +66,6 @@ def isolate_kunit_output(kernel_output):
|
||||
def raw_output(kernel_output):
|
||||
for line in kernel_output:
|
||||
print(line)
|
||||
yield line
|
||||
|
||||
DIVIDER = '=' * 60
|
||||
|
||||
@@ -242,7 +241,7 @@ def parse_test_suite(lines: List[str], expected_suite_index: int) -> TestSuite:
|
||||
return None
|
||||
test_suite.name = name
|
||||
expected_test_case_num = parse_subtest_plan(lines)
|
||||
if not expected_test_case_num:
|
||||
if expected_test_case_num is None:
|
||||
return None
|
||||
while expected_test_case_num > 0:
|
||||
test_case = parse_test_case(lines)
|
||||
|
||||
@@ -179,7 +179,7 @@ class KUnitParserTest(unittest.TestCase):
|
||||
print_mock = mock.patch('builtins.print').start()
|
||||
result = kunit_parser.parse_run_tests(
|
||||
kunit_parser.isolate_kunit_output(file.readlines()))
|
||||
print_mock.assert_any_call(StrContains("no kunit output detected"))
|
||||
print_mock.assert_any_call(StrContains('no tests run!'))
|
||||
print_mock.stop()
|
||||
file.close()
|
||||
|
||||
@@ -198,39 +198,57 @@ class KUnitParserTest(unittest.TestCase):
|
||||
'test_data/test_config_printk_time.log')
|
||||
with open(prefix_log) as file:
|
||||
result = kunit_parser.parse_run_tests(file.readlines())
|
||||
self.assertEqual('kunit-resource-test', result.suites[0].name)
|
||||
self.assertEqual(
|
||||
kunit_parser.TestStatus.SUCCESS,
|
||||
result.status)
|
||||
self.assertEqual('kunit-resource-test', result.suites[0].name)
|
||||
|
||||
def test_ignores_multiple_prefixes(self):
|
||||
prefix_log = get_absolute_path(
|
||||
'test_data/test_multiple_prefixes.log')
|
||||
with open(prefix_log) as file:
|
||||
result = kunit_parser.parse_run_tests(file.readlines())
|
||||
self.assertEqual('kunit-resource-test', result.suites[0].name)
|
||||
self.assertEqual(
|
||||
kunit_parser.TestStatus.SUCCESS,
|
||||
result.status)
|
||||
self.assertEqual('kunit-resource-test', result.suites[0].name)
|
||||
|
||||
def test_prefix_mixed_kernel_output(self):
|
||||
mixed_prefix_log = get_absolute_path(
|
||||
'test_data/test_interrupted_tap_output.log')
|
||||
with open(mixed_prefix_log) as file:
|
||||
result = kunit_parser.parse_run_tests(file.readlines())
|
||||
self.assertEqual('kunit-resource-test', result.suites[0].name)
|
||||
self.assertEqual(
|
||||
kunit_parser.TestStatus.SUCCESS,
|
||||
result.status)
|
||||
self.assertEqual('kunit-resource-test', result.suites[0].name)
|
||||
|
||||
def test_prefix_poundsign(self):
|
||||
pound_log = get_absolute_path('test_data/test_pound_sign.log')
|
||||
with open(pound_log) as file:
|
||||
result = kunit_parser.parse_run_tests(file.readlines())
|
||||
self.assertEqual('kunit-resource-test', result.suites[0].name)
|
||||
self.assertEqual(
|
||||
kunit_parser.TestStatus.SUCCESS,
|
||||
result.status)
|
||||
self.assertEqual('kunit-resource-test', result.suites[0].name)
|
||||
|
||||
def test_kernel_panic_end(self):
|
||||
panic_log = get_absolute_path('test_data/test_kernel_panic_interrupt.log')
|
||||
with open(panic_log) as file:
|
||||
result = kunit_parser.parse_run_tests(file.readlines())
|
||||
self.assertEqual('kunit-resource-test', result.suites[0].name)
|
||||
self.assertEqual(
|
||||
kunit_parser.TestStatus.TEST_CRASHED,
|
||||
result.status)
|
||||
self.assertEqual('kunit-resource-test', result.suites[0].name)
|
||||
|
||||
def test_pound_no_prefix(self):
|
||||
pound_log = get_absolute_path('test_data/test_pound_no_prefix.log')
|
||||
with open(pound_log) as file:
|
||||
result = kunit_parser.parse_run_tests(file.readlines())
|
||||
self.assertEqual('kunit-resource-test', result.suites[0].name)
|
||||
self.assertEqual(
|
||||
kunit_parser.TestStatus.SUCCESS,
|
||||
result.status)
|
||||
self.assertEqual('kunit-resource-test', result.suites[0].name)
|
||||
|
||||
class KUnitJsonTest(unittest.TestCase):
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
[ 0.060000] printk: console [mc-1] enabled
|
||||
[ 0.060000] random: get_random_bytes called from init_oops_id+0x35/0x40 with crng_init=0
|
||||
[ 0.060000] TAP version 14
|
||||
[ 0.060000] 1..3
|
||||
[ 0.060000] # Subtest: kunit-resource-test
|
||||
[ 0.060000] 1..5
|
||||
[ 0.060000] ok 1 - kunit_resource_test_init_resources
|
||||
@@ -28,4 +29,4 @@
|
||||
[ 0.060000] Stack:
|
||||
[ 0.060000] 602086f8 601bc260 705c0000 705c0000
|
||||
[ 0.060000] 602086f8 6005fcec 705c0000 6002c6ab
|
||||
[ 0.060000] 6005fcec 601bc260 705c0000 3000000010
|
||||
[ 0.060000] 6005fcec 601bc260 705c0000 3000000010
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
[ 0.060000] printk: console [mc-1] enabled
|
||||
[ 0.060000] random: get_random_bytes called from init_oops_id+0x35/0x40 with crng_init=0
|
||||
[ 0.060000] TAP version 14
|
||||
[ 0.060000] 1..3
|
||||
[ 0.060000] # Subtest: kunit-resource-test
|
||||
[ 0.060000] 1..5
|
||||
[ 0.060000] ok 1 - kunit_resource_test_init_resources
|
||||
@@ -34,4 +35,4 @@
|
||||
[ 0.060000] Stack:
|
||||
[ 0.060000] 602086f8 601bc260 705c0000 705c0000
|
||||
[ 0.060000] 602086f8 6005fcec 705c0000 6002c6ab
|
||||
[ 0.060000] 6005fcec 601bc260 705c0000 3000000010
|
||||
[ 0.060000] 6005fcec 601bc260 705c0000 3000000010
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
[ 0.060000] printk: console [mc-1] enabled
|
||||
[ 0.060000] random: get_random_bytes called from init_oops_id+0x35/0x40 with crng_init=0
|
||||
[ 0.060000] TAP version 14
|
||||
[ 0.060000] 1..3
|
||||
[ 0.060000] # Subtest: kunit-resource-test
|
||||
[ 0.060000] 1..5
|
||||
[ 0.060000] ok 1 - kunit_resource_test_init_resources
|
||||
@@ -22,4 +23,4 @@
|
||||
[ 0.060000] Stack:
|
||||
[ 0.060000] 602086f8 601bc260 705c0000 705c0000
|
||||
[ 0.060000] 602086f8 6005fcec 705c0000 6002c6ab
|
||||
[ 0.060000] 6005fcec 601bc260 705c0000 3000000010
|
||||
[ 0.060000] 6005fcec 601bc260 705c0000 3000000010
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
[ 0.060000][ T1] printk: console [mc-1] enabled
|
||||
[ 0.060000][ T1] random: get_random_bytes called from init_oops_id+0x35/0x40 with crng_init=0
|
||||
[ 0.060000][ T1] TAP version 14
|
||||
[ 0.060000][ T1] 1..3
|
||||
[ 0.060000][ T1] # Subtest: kunit-resource-test
|
||||
[ 0.060000][ T1] 1..5
|
||||
[ 0.060000][ T1] ok 1 - kunit_resource_test_init_resources
|
||||
@@ -28,4 +29,4 @@
|
||||
[ 0.060000][ T1] Stack:
|
||||
[ 0.060000][ T1] 602086f8 601bc260 705c0000 705c0000
|
||||
[ 0.060000][ T1] 602086f8 6005fcec 705c0000 6002c6ab
|
||||
[ 0.060000][ T1] 6005fcec 601bc260 705c0000 3000000010
|
||||
[ 0.060000][ T1] 6005fcec 601bc260 705c0000 3000000010
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
printk: console [mc-1] enabled
|
||||
random: get_random_bytes called from init_oops_id+0x35/0x40 with crng_init=0
|
||||
TAP version 14
|
||||
1..3
|
||||
# Subtest: kunit-resource-test
|
||||
1..5
|
||||
ok 1 - kunit_resource_test_init_resources
|
||||
@@ -30,4 +31,4 @@
|
||||
Stack:
|
||||
602086f8 601bc260 705c0000 705c0000
|
||||
602086f8 6005fcec 705c0000 6002c6ab
|
||||
6005fcec 601bc260 705c0000 3000000010
|
||||
6005fcec 601bc260 705c0000 3000000010
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
[ 0.060000] printk: console [mc-1] enabled
|
||||
[ 0.060000] random: get_random_bytes called from init_oops_id+0x35/0x40 with crng_init=0
|
||||
[ 0.060000] TAP version 14
|
||||
[ 0.060000] 1..3
|
||||
[ 0.060000] # Subtest: kunit-resource-test
|
||||
[ 0.060000] 1..5
|
||||
[ 0.060000] ok 1 - kunit_resource_test_init_resources
|
||||
|
||||
@@ -417,6 +417,9 @@ int main(int argc, char *argv[])
|
||||
/* Register SIGSEGV handler */
|
||||
mte_register_signal(SIGSEGV, mte_default_handler);
|
||||
|
||||
/* Set test plan */
|
||||
ksft_set_plan(20);
|
||||
|
||||
/* Buffer by byte tests */
|
||||
evaluate_test(check_buffer_by_byte(USE_MMAP, MTE_SYNC_ERR),
|
||||
"Check buffer correctness by byte with sync err mode and mmap memory\n");
|
||||
|
||||
@@ -163,6 +163,9 @@ int main(int argc, char *argv[])
|
||||
mte_register_signal(SIGSEGV, mte_default_handler);
|
||||
mte_register_signal(SIGBUS, mte_default_handler);
|
||||
|
||||
/* Set test plan */
|
||||
ksft_set_plan(12);
|
||||
|
||||
evaluate_test(check_child_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE),
|
||||
"Check child anonymous memory with private mapping, precise mode and mmap memory\n");
|
||||
evaluate_test(check_child_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_SHARED),
|
||||
|
||||
@@ -140,6 +140,10 @@ int main(int argc, char *argv[])
|
||||
/* Register signal handlers */
|
||||
mte_register_signal(SIGBUS, mte_default_handler);
|
||||
mte_register_signal(SIGSEGV, mte_default_handler);
|
||||
|
||||
/* Set test plan */
|
||||
ksft_set_plan(4);
|
||||
|
||||
/* Enable KSM */
|
||||
mte_ksm_setup();
|
||||
|
||||
|
||||
@@ -205,7 +205,11 @@ int main(int argc, char *argv[])
|
||||
mte_register_signal(SIGBUS, mte_default_handler);
|
||||
mte_register_signal(SIGSEGV, mte_default_handler);
|
||||
|
||||
/* Set test plan */
|
||||
ksft_set_plan(22);
|
||||
|
||||
mte_enable_pstate_tco();
|
||||
|
||||
evaluate_test(check_anonymous_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE, TAG_CHECK_OFF),
|
||||
"Check anonymous memory with private mapping, sync error mode, mmap memory and tag check off\n");
|
||||
evaluate_test(check_file_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_PRIVATE, TAG_CHECK_OFF),
|
||||
|
||||
@@ -170,6 +170,9 @@ int main(int argc, char *argv[])
|
||||
/* Register SIGSEGV handler */
|
||||
mte_register_signal(SIGSEGV, mte_default_handler);
|
||||
|
||||
/* Set test plan */
|
||||
ksft_set_plan(4);
|
||||
|
||||
evaluate_test(check_single_included_tags(USE_MMAP, MTE_SYNC_ERR),
|
||||
"Check an included tag value with sync mode\n");
|
||||
evaluate_test(check_multiple_included_tags(USE_MMAP, MTE_SYNC_ERR),
|
||||
|
||||
@@ -92,9 +92,13 @@ int main(int argc, char *argv[])
|
||||
err = mte_default_setup();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Register signal handlers */
|
||||
mte_register_signal(SIGSEGV, mte_default_handler);
|
||||
|
||||
/* Set test plan */
|
||||
ksft_set_plan(4);
|
||||
|
||||
evaluate_test(check_usermem_access_fault(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE),
|
||||
"Check memory access from kernel in sync mode, private mapping and mmap memory\n");
|
||||
evaluate_test(check_usermem_access_fault(USE_MMAP, MTE_SYNC_ERR, MAP_SHARED),
|
||||
|
||||
@@ -3282,4 +3282,99 @@ TEST(epoll60)
|
||||
close(ctx.epfd);
|
||||
}
|
||||
|
||||
struct epoll61_ctx {
|
||||
int epfd;
|
||||
int evfd;
|
||||
};
|
||||
|
||||
static void *epoll61_write_eventfd(void *ctx_)
|
||||
{
|
||||
struct epoll61_ctx *ctx = ctx_;
|
||||
int64_t l = 1;
|
||||
|
||||
usleep(10950);
|
||||
write(ctx->evfd, &l, sizeof(l));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *epoll61_epoll_with_timeout(void *ctx_)
|
||||
{
|
||||
struct epoll61_ctx *ctx = ctx_;
|
||||
struct epoll_event events[1];
|
||||
int n;
|
||||
|
||||
n = epoll_wait(ctx->epfd, events, 1, 11);
|
||||
/*
|
||||
* If epoll returned the eventfd, write on the eventfd to wake up the
|
||||
* blocking poller.
|
||||
*/
|
||||
if (n == 1) {
|
||||
int64_t l = 1;
|
||||
|
||||
write(ctx->evfd, &l, sizeof(l));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *epoll61_blocking_epoll(void *ctx_)
|
||||
{
|
||||
struct epoll61_ctx *ctx = ctx_;
|
||||
struct epoll_event events[1];
|
||||
|
||||
epoll_wait(ctx->epfd, events, 1, -1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TEST(epoll61)
|
||||
{
|
||||
struct epoll61_ctx ctx;
|
||||
struct epoll_event ev;
|
||||
int i, r;
|
||||
|
||||
ctx.epfd = epoll_create1(0);
|
||||
ASSERT_GE(ctx.epfd, 0);
|
||||
ctx.evfd = eventfd(0, EFD_NONBLOCK);
|
||||
ASSERT_GE(ctx.evfd, 0);
|
||||
|
||||
ev.events = EPOLLIN | EPOLLET | EPOLLERR | EPOLLHUP;
|
||||
ev.data.ptr = NULL;
|
||||
r = epoll_ctl(ctx.epfd, EPOLL_CTL_ADD, ctx.evfd, &ev);
|
||||
ASSERT_EQ(r, 0);
|
||||
|
||||
/*
|
||||
* We are testing a race. Repeat the test case 1000 times to make it
|
||||
* more likely to fail in case of a bug.
|
||||
*/
|
||||
for (i = 0; i < 1000; i++) {
|
||||
pthread_t threads[3];
|
||||
int n;
|
||||
|
||||
/*
|
||||
* Start 3 threads:
|
||||
* Thread 1 sleeps for 10.9ms and writes to the evenfd.
|
||||
* Thread 2 calls epoll with a timeout of 11ms.
|
||||
* Thread 3 calls epoll with a timeout of -1.
|
||||
*
|
||||
* The eventfd write by Thread 1 should either wakeup Thread 2
|
||||
* or Thread 3. If it wakes up Thread 2, Thread 2 writes on the
|
||||
* eventfd to wake up Thread 3.
|
||||
*
|
||||
* If no events are missed, all three threads should eventually
|
||||
* be joinable.
|
||||
*/
|
||||
ASSERT_EQ(pthread_create(&threads[0], NULL,
|
||||
epoll61_write_eventfd, &ctx), 0);
|
||||
ASSERT_EQ(pthread_create(&threads[1], NULL,
|
||||
epoll61_epoll_with_timeout, &ctx), 0);
|
||||
ASSERT_EQ(pthread_create(&threads[2], NULL,
|
||||
epoll61_blocking_epoll, &ctx), 0);
|
||||
|
||||
for (n = 0; n < ARRAY_SIZE(threads); ++n)
|
||||
ASSERT_EQ(pthread_join(threads[n], NULL), 0);
|
||||
}
|
||||
|
||||
close(ctx.epfd);
|
||||
close(ctx.evfd);
|
||||
}
|
||||
|
||||
TEST_HARNESS_MAIN
|
||||
|
||||
@@ -432,7 +432,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* ASSERT_EQ(expected, seen)
|
||||
* ASSERT_EQ()
|
||||
*
|
||||
* @expected: expected value
|
||||
* @seen: measured value
|
||||
@@ -443,7 +443,7 @@
|
||||
__EXPECT(expected, #expected, seen, #seen, ==, 1)
|
||||
|
||||
/**
|
||||
* ASSERT_NE(expected, seen)
|
||||
* ASSERT_NE()
|
||||
*
|
||||
* @expected: expected value
|
||||
* @seen: measured value
|
||||
@@ -454,7 +454,7 @@
|
||||
__EXPECT(expected, #expected, seen, #seen, !=, 1)
|
||||
|
||||
/**
|
||||
* ASSERT_LT(expected, seen)
|
||||
* ASSERT_LT()
|
||||
*
|
||||
* @expected: expected value
|
||||
* @seen: measured value
|
||||
@@ -465,7 +465,7 @@
|
||||
__EXPECT(expected, #expected, seen, #seen, <, 1)
|
||||
|
||||
/**
|
||||
* ASSERT_LE(expected, seen)
|
||||
* ASSERT_LE()
|
||||
*
|
||||
* @expected: expected value
|
||||
* @seen: measured value
|
||||
@@ -476,7 +476,7 @@
|
||||
__EXPECT(expected, #expected, seen, #seen, <=, 1)
|
||||
|
||||
/**
|
||||
* ASSERT_GT(expected, seen)
|
||||
* ASSERT_GT()
|
||||
*
|
||||
* @expected: expected value
|
||||
* @seen: measured value
|
||||
@@ -487,7 +487,7 @@
|
||||
__EXPECT(expected, #expected, seen, #seen, >, 1)
|
||||
|
||||
/**
|
||||
* ASSERT_GE(expected, seen)
|
||||
* ASSERT_GE()
|
||||
*
|
||||
* @expected: expected value
|
||||
* @seen: measured value
|
||||
@@ -498,7 +498,7 @@
|
||||
__EXPECT(expected, #expected, seen, #seen, >=, 1)
|
||||
|
||||
/**
|
||||
* ASSERT_NULL(seen)
|
||||
* ASSERT_NULL()
|
||||
*
|
||||
* @seen: measured value
|
||||
*
|
||||
@@ -508,7 +508,7 @@
|
||||
__EXPECT(NULL, "NULL", seen, #seen, ==, 1)
|
||||
|
||||
/**
|
||||
* ASSERT_TRUE(seen)
|
||||
* ASSERT_TRUE()
|
||||
*
|
||||
* @seen: measured value
|
||||
*
|
||||
@@ -518,7 +518,7 @@
|
||||
__EXPECT(0, "0", seen, #seen, !=, 1)
|
||||
|
||||
/**
|
||||
* ASSERT_FALSE(seen)
|
||||
* ASSERT_FALSE()
|
||||
*
|
||||
* @seen: measured value
|
||||
*
|
||||
@@ -528,7 +528,7 @@
|
||||
__EXPECT(0, "0", seen, #seen, ==, 1)
|
||||
|
||||
/**
|
||||
* ASSERT_STREQ(expected, seen)
|
||||
* ASSERT_STREQ()
|
||||
*
|
||||
* @expected: expected value
|
||||
* @seen: measured value
|
||||
@@ -539,7 +539,7 @@
|
||||
__EXPECT_STR(expected, seen, ==, 1)
|
||||
|
||||
/**
|
||||
* ASSERT_STRNE(expected, seen)
|
||||
* ASSERT_STRNE()
|
||||
*
|
||||
* @expected: expected value
|
||||
* @seen: measured value
|
||||
@@ -550,7 +550,7 @@
|
||||
__EXPECT_STR(expected, seen, !=, 1)
|
||||
|
||||
/**
|
||||
* EXPECT_EQ(expected, seen)
|
||||
* EXPECT_EQ()
|
||||
*
|
||||
* @expected: expected value
|
||||
* @seen: measured value
|
||||
@@ -561,7 +561,7 @@
|
||||
__EXPECT(expected, #expected, seen, #seen, ==, 0)
|
||||
|
||||
/**
|
||||
* EXPECT_NE(expected, seen)
|
||||
* EXPECT_NE()
|
||||
*
|
||||
* @expected: expected value
|
||||
* @seen: measured value
|
||||
@@ -572,7 +572,7 @@
|
||||
__EXPECT(expected, #expected, seen, #seen, !=, 0)
|
||||
|
||||
/**
|
||||
* EXPECT_LT(expected, seen)
|
||||
* EXPECT_LT()
|
||||
*
|
||||
* @expected: expected value
|
||||
* @seen: measured value
|
||||
@@ -583,7 +583,7 @@
|
||||
__EXPECT(expected, #expected, seen, #seen, <, 0)
|
||||
|
||||
/**
|
||||
* EXPECT_LE(expected, seen)
|
||||
* EXPECT_LE()
|
||||
*
|
||||
* @expected: expected value
|
||||
* @seen: measured value
|
||||
@@ -594,7 +594,7 @@
|
||||
__EXPECT(expected, #expected, seen, #seen, <=, 0)
|
||||
|
||||
/**
|
||||
* EXPECT_GT(expected, seen)
|
||||
* EXPECT_GT()
|
||||
*
|
||||
* @expected: expected value
|
||||
* @seen: measured value
|
||||
@@ -605,7 +605,7 @@
|
||||
__EXPECT(expected, #expected, seen, #seen, >, 0)
|
||||
|
||||
/**
|
||||
* EXPECT_GE(expected, seen)
|
||||
* EXPECT_GE()
|
||||
*
|
||||
* @expected: expected value
|
||||
* @seen: measured value
|
||||
@@ -616,7 +616,7 @@
|
||||
__EXPECT(expected, #expected, seen, #seen, >=, 0)
|
||||
|
||||
/**
|
||||
* EXPECT_NULL(seen)
|
||||
* EXPECT_NULL()
|
||||
*
|
||||
* @seen: measured value
|
||||
*
|
||||
@@ -626,7 +626,7 @@
|
||||
__EXPECT(NULL, "NULL", seen, #seen, ==, 0)
|
||||
|
||||
/**
|
||||
* EXPECT_TRUE(seen)
|
||||
* EXPECT_TRUE()
|
||||
*
|
||||
* @seen: measured value
|
||||
*
|
||||
@@ -636,7 +636,7 @@
|
||||
__EXPECT(0, "0", seen, #seen, !=, 0)
|
||||
|
||||
/**
|
||||
* EXPECT_FALSE(seen)
|
||||
* EXPECT_FALSE()
|
||||
*
|
||||
* @seen: measured value
|
||||
*
|
||||
@@ -646,7 +646,7 @@
|
||||
__EXPECT(0, "0", seen, #seen, ==, 0)
|
||||
|
||||
/**
|
||||
* EXPECT_STREQ(expected, seen)
|
||||
* EXPECT_STREQ()
|
||||
*
|
||||
* @expected: expected value
|
||||
* @seen: measured value
|
||||
@@ -657,7 +657,7 @@
|
||||
__EXPECT_STR(expected, seen, ==, 0)
|
||||
|
||||
/**
|
||||
* EXPECT_STRNE(expected, seen)
|
||||
* EXPECT_STRNE()
|
||||
*
|
||||
* @expected: expected value
|
||||
* @seen: measured value
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
/x86_64/vmx_preemption_timer_test
|
||||
/x86_64/svm_vmcall_test
|
||||
/x86_64/sync_regs_test
|
||||
/x86_64/vmx_apic_access_test
|
||||
/x86_64/vmx_close_while_nested_test
|
||||
/x86_64/vmx_dirty_log_test
|
||||
/x86_64/vmx_set_nested_state_test
|
||||
|
||||
@@ -49,6 +49,7 @@ TEST_GEN_PROGS_x86_64 += x86_64/state_test
|
||||
TEST_GEN_PROGS_x86_64 += x86_64/vmx_preemption_timer_test
|
||||
TEST_GEN_PROGS_x86_64 += x86_64/svm_vmcall_test
|
||||
TEST_GEN_PROGS_x86_64 += x86_64/sync_regs_test
|
||||
TEST_GEN_PROGS_x86_64 += x86_64/vmx_apic_access_test
|
||||
TEST_GEN_PROGS_x86_64 += x86_64/vmx_close_while_nested_test
|
||||
TEST_GEN_PROGS_x86_64 += x86_64/vmx_dirty_log_test
|
||||
TEST_GEN_PROGS_x86_64 += x86_64/vmx_set_nested_state_test
|
||||
|
||||
@@ -573,6 +573,10 @@ struct vmx_pages {
|
||||
void *eptp_hva;
|
||||
uint64_t eptp_gpa;
|
||||
void *eptp;
|
||||
|
||||
void *apic_access_hva;
|
||||
uint64_t apic_access_gpa;
|
||||
void *apic_access;
|
||||
};
|
||||
|
||||
union vmx_basic {
|
||||
@@ -615,5 +619,7 @@ void nested_map_memslot(struct vmx_pages *vmx, struct kvm_vm *vm,
|
||||
uint32_t memslot, uint32_t eptp_memslot);
|
||||
void prepare_eptp(struct vmx_pages *vmx, struct kvm_vm *vm,
|
||||
uint32_t eptp_memslot);
|
||||
void prepare_virtualize_apic_accesses(struct vmx_pages *vmx, struct kvm_vm *vm,
|
||||
uint32_t eptp_memslot);
|
||||
|
||||
#endif /* SELFTEST_KVM_VMX_H */
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#define KVM_UTIL_PGS_PER_HUGEPG 512
|
||||
@@ -664,13 +665,21 @@ void vm_userspace_mem_region_add(struct kvm_vm *vm,
|
||||
|
||||
/* As needed perform madvise */
|
||||
if (src_type == VM_MEM_SRC_ANONYMOUS || src_type == VM_MEM_SRC_ANONYMOUS_THP) {
|
||||
ret = madvise(region->host_mem, npages * vm->page_size,
|
||||
src_type == VM_MEM_SRC_ANONYMOUS ? MADV_NOHUGEPAGE : MADV_HUGEPAGE);
|
||||
TEST_ASSERT(ret == 0, "madvise failed,\n"
|
||||
" addr: %p\n"
|
||||
" length: 0x%lx\n"
|
||||
" src_type: %x",
|
||||
region->host_mem, npages * vm->page_size, src_type);
|
||||
struct stat statbuf;
|
||||
|
||||
ret = stat("/sys/kernel/mm/transparent_hugepage", &statbuf);
|
||||
TEST_ASSERT(ret == 0 || (ret == -1 && errno == ENOENT),
|
||||
"stat /sys/kernel/mm/transparent_hugepage");
|
||||
|
||||
TEST_ASSERT(ret == 0 || src_type != VM_MEM_SRC_ANONYMOUS_THP,
|
||||
"VM_MEM_SRC_ANONYMOUS_THP requires THP to be configured in the host kernel");
|
||||
|
||||
if (ret == 0) {
|
||||
ret = madvise(region->host_mem, npages * vm->page_size,
|
||||
src_type == VM_MEM_SRC_ANONYMOUS ? MADV_NOHUGEPAGE : MADV_HUGEPAGE);
|
||||
TEST_ASSERT(ret == 0, "madvise failed, addr: %p length: 0x%lx src_type: %x",
|
||||
region->host_mem, npages * vm->page_size, src_type);
|
||||
}
|
||||
}
|
||||
|
||||
region->unused_phy_pages = sparsebit_alloc();
|
||||
|
||||
@@ -542,3 +542,12 @@ void prepare_eptp(struct vmx_pages *vmx, struct kvm_vm *vm,
|
||||
vmx->eptp_hva = addr_gva2hva(vm, (uintptr_t)vmx->eptp);
|
||||
vmx->eptp_gpa = addr_gva2gpa(vm, (uintptr_t)vmx->eptp);
|
||||
}
|
||||
|
||||
void prepare_virtualize_apic_accesses(struct vmx_pages *vmx, struct kvm_vm *vm,
|
||||
uint32_t eptp_memslot)
|
||||
{
|
||||
vmx->apic_access = (void *)vm_vaddr_alloc(vm, getpagesize(),
|
||||
0x10000, 0, 0);
|
||||
vmx->apic_access_hva = addr_gva2hva(vm, (uintptr_t)vmx->apic_access);
|
||||
vmx->apic_access_gpa = addr_gva2gpa(vm, (uintptr_t)vmx->apic_access);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* vmx_apic_access_test
|
||||
*
|
||||
* Copyright (C) 2020, Google LLC.
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2.
|
||||
*
|
||||
* The first subtest simply checks to see that an L2 guest can be
|
||||
* launched with a valid APIC-access address that is backed by a
|
||||
* page of L1 physical memory.
|
||||
*
|
||||
* The second subtest sets the APIC-access address to a (valid) L1
|
||||
* physical address that is not backed by memory. KVM can't handle
|
||||
* this situation, so resuming L2 should result in a KVM exit for
|
||||
* internal error (emulation). This is not an architectural
|
||||
* requirement. It is just a shortcoming of KVM. The internal error
|
||||
* is unfortunate, but it's better than what used to happen!
|
||||
*/
|
||||
|
||||
#include "test_util.h"
|
||||
#include "kvm_util.h"
|
||||
#include "processor.h"
|
||||
#include "vmx.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "kselftest.h"
|
||||
|
||||
#define VCPU_ID 0
|
||||
|
||||
/* The virtual machine object. */
|
||||
static struct kvm_vm *vm;
|
||||
|
||||
static void l2_guest_code(void)
|
||||
{
|
||||
/* Exit to L1 */
|
||||
__asm__ __volatile__("vmcall");
|
||||
}
|
||||
|
||||
static void l1_guest_code(struct vmx_pages *vmx_pages, unsigned long high_gpa)
|
||||
{
|
||||
#define L2_GUEST_STACK_SIZE 64
|
||||
unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE];
|
||||
uint32_t control;
|
||||
|
||||
GUEST_ASSERT(prepare_for_vmx_operation(vmx_pages));
|
||||
GUEST_ASSERT(load_vmcs(vmx_pages));
|
||||
|
||||
/* Prepare the VMCS for L2 execution. */
|
||||
prepare_vmcs(vmx_pages, l2_guest_code,
|
||||
&l2_guest_stack[L2_GUEST_STACK_SIZE]);
|
||||
control = vmreadz(CPU_BASED_VM_EXEC_CONTROL);
|
||||
control |= CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
|
||||
vmwrite(CPU_BASED_VM_EXEC_CONTROL, control);
|
||||
control = vmreadz(SECONDARY_VM_EXEC_CONTROL);
|
||||
control |= SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
|
||||
vmwrite(SECONDARY_VM_EXEC_CONTROL, control);
|
||||
vmwrite(APIC_ACCESS_ADDR, vmx_pages->apic_access_gpa);
|
||||
|
||||
/* Try to launch L2 with the memory-backed APIC-access address. */
|
||||
GUEST_SYNC(vmreadz(APIC_ACCESS_ADDR));
|
||||
GUEST_ASSERT(!vmlaunch());
|
||||
GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
|
||||
|
||||
vmwrite(APIC_ACCESS_ADDR, high_gpa);
|
||||
|
||||
/* Try to resume L2 with the unbacked APIC-access address. */
|
||||
GUEST_SYNC(vmreadz(APIC_ACCESS_ADDR));
|
||||
GUEST_ASSERT(!vmresume());
|
||||
GUEST_ASSERT(vmreadz(VM_EXIT_REASON) == EXIT_REASON_VMCALL);
|
||||
|
||||
GUEST_DONE();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
unsigned long apic_access_addr = ~0ul;
|
||||
unsigned int paddr_width;
|
||||
unsigned int vaddr_width;
|
||||
vm_vaddr_t vmx_pages_gva;
|
||||
unsigned long high_gpa;
|
||||
struct vmx_pages *vmx;
|
||||
bool done = false;
|
||||
|
||||
nested_vmx_check_supported();
|
||||
|
||||
vm = vm_create_default(VCPU_ID, 0, (void *) l1_guest_code);
|
||||
vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
|
||||
|
||||
kvm_get_cpu_address_width(&paddr_width, &vaddr_width);
|
||||
high_gpa = (1ul << paddr_width) - getpagesize();
|
||||
if ((unsigned long)DEFAULT_GUEST_PHY_PAGES * getpagesize() > high_gpa) {
|
||||
print_skip("No unbacked physical page available");
|
||||
exit(KSFT_SKIP);
|
||||
}
|
||||
|
||||
vmx = vcpu_alloc_vmx(vm, &vmx_pages_gva);
|
||||
prepare_virtualize_apic_accesses(vmx, vm, 0);
|
||||
vcpu_args_set(vm, VCPU_ID, 2, vmx_pages_gva, high_gpa);
|
||||
|
||||
while (!done) {
|
||||
volatile struct kvm_run *run = vcpu_state(vm, VCPU_ID);
|
||||
struct ucall uc;
|
||||
|
||||
vcpu_run(vm, VCPU_ID);
|
||||
if (apic_access_addr == high_gpa) {
|
||||
TEST_ASSERT(run->exit_reason ==
|
||||
KVM_EXIT_INTERNAL_ERROR,
|
||||
"Got exit reason other than KVM_EXIT_INTERNAL_ERROR: %u (%s)\n",
|
||||
run->exit_reason,
|
||||
exit_reason_str(run->exit_reason));
|
||||
TEST_ASSERT(run->internal.suberror ==
|
||||
KVM_INTERNAL_ERROR_EMULATION,
|
||||
"Got internal suberror other than KVM_INTERNAL_ERROR_EMULATION: %u\n",
|
||||
run->internal.suberror);
|
||||
break;
|
||||
}
|
||||
TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
|
||||
"Got exit_reason other than KVM_EXIT_IO: %u (%s)\n",
|
||||
run->exit_reason,
|
||||
exit_reason_str(run->exit_reason));
|
||||
|
||||
switch (get_ucall(vm, VCPU_ID, &uc)) {
|
||||
case UCALL_ABORT:
|
||||
TEST_FAIL("%s at %s:%ld", (const char *)uc.args[0],
|
||||
__FILE__, uc.args[1]);
|
||||
/* NOT REACHED */
|
||||
case UCALL_SYNC:
|
||||
apic_access_addr = uc.args[1];
|
||||
break;
|
||||
case UCALL_DONE:
|
||||
done = true;
|
||||
break;
|
||||
default:
|
||||
TEST_ASSERT(false, "Unknown ucall %lu", uc.cmd);
|
||||
}
|
||||
}
|
||||
kvm_vm_free(vm);
|
||||
return 0;
|
||||
}
|
||||
@@ -316,6 +316,14 @@ pp sleep 3
|
||||
n2 ping -W 1 -c 1 192.168.241.1
|
||||
n1 wg set wg0 peer "$pub2" persistent-keepalive 0
|
||||
|
||||
# Test that sk_bound_dev_if works
|
||||
n1 ping -I wg0 -c 1 -W 1 192.168.241.2
|
||||
# What about when the mark changes and the packet must be rerouted?
|
||||
n1 iptables -t mangle -I OUTPUT -j MARK --set-xmark 1
|
||||
n1 ping -c 1 -W 1 192.168.241.2 # First the boring case
|
||||
n1 ping -I wg0 -c 1 -W 1 192.168.241.2 # Then the sk_bound_dev_if case
|
||||
n1 iptables -t mangle -D OUTPUT -j MARK --set-xmark 1
|
||||
|
||||
# Test that onion routing works, even when it loops
|
||||
n1 wg set wg0 peer "$pub3" allowed-ips 192.168.242.2/32 endpoint 192.168.241.2:5
|
||||
ip1 addr add 192.168.242.1/24 dev wg0
|
||||
|
||||
@@ -18,10 +18,12 @@ CONFIG_NF_NAT=y
|
||||
CONFIG_NETFILTER_XTABLES=y
|
||||
CONFIG_NETFILTER_XT_NAT=y
|
||||
CONFIG_NETFILTER_XT_MATCH_LENGTH=y
|
||||
CONFIG_NETFILTER_XT_MARK=y
|
||||
CONFIG_NF_CONNTRACK_IPV4=y
|
||||
CONFIG_NF_NAT_IPV4=y
|
||||
CONFIG_IP_NF_IPTABLES=y
|
||||
CONFIG_IP_NF_FILTER=y
|
||||
CONFIG_IP_NF_MANGLE=y
|
||||
CONFIG_IP_NF_NAT=y
|
||||
CONFIG_IP_ADVANCED_ROUTER=y
|
||||
CONFIG_IP_MULTIPLE_TABLES=y
|
||||
|
||||
Reference in New Issue
Block a user