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:
Jakub Kicinski
2020-11-06 17:33:38 -08:00
956 changed files with 9428 additions and 32158 deletions
+1 -2
View File
@@ -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)
+25 -7
View File
@@ -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
+22 -22
View File
@@ -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
+1
View File
@@ -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
+1
View File
@@ -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 */
+16 -7
View File
@@ -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