2021-01-12 13:42:53 -08:00
// SPDX-License-Identifier: GPL-2.0
/*
* KVM memslot modification stress test
* Adapted from demand_paging_test . c
*
* Copyright ( C ) 2018 , Red Hat , Inc .
* Copyright ( C ) 2020 , Google , Inc .
*/
# define _GNU_SOURCE /* for program_invocation_name */
# include <stdio.h>
# include <stdlib.h>
# include <sys/syscall.h>
# include <unistd.h>
# include <asm/unistd.h>
# include <time.h>
# include <poll.h>
# include <pthread.h>
# include <linux/bitmap.h>
# include <linux/bitops.h>
# include <linux/userfaultfd.h>
2022-10-12 09:57:27 -07:00
# include "memstress.h"
2021-01-12 13:42:53 -08:00
# include "processor.h"
# include "test_util.h"
# include "guest_modes.h"
# define DUMMY_MEMSLOT_INDEX 7
# define DEFAULT_MEMSLOT_MODIFICATION_ITERATIONS 10
static int nr_vcpus = 1 ;
static uint64_t guest_percpu_mem_size = DEFAULT_PER_VCPU_MEM_SIZE ;
2022-10-12 09:57:29 -07:00
static void vcpu_worker ( struct memstress_vcpu_args * vcpu_args )
2021-01-12 13:42:53 -08:00
{
2022-02-16 13:38:12 -08:00
struct kvm_vcpu * vcpu = vcpu_args - > vcpu ;
2021-01-12 13:42:53 -08:00
struct kvm_run * run ;
2022-02-16 13:38:12 -08:00
int ret ;
2021-01-12 13:42:53 -08:00
2022-02-16 13:38:12 -08:00
run = vcpu - > run ;
2021-01-12 13:42:53 -08:00
/* Let the guest access its memory until a stop signal is received */
KVM/arm64 updates for 6.2
- Enable the per-vcpu dirty-ring tracking mechanism, together with an
option to keep the good old dirty log around for pages that are
dirtied by something other than a vcpu.
- Switch to the relaxed parallel fault handling, using RCU to delay
page table reclaim and giving better performance under load.
- Relax the MTE ABI, allowing a VMM to use the MAP_SHARED mapping
option, which multi-process VMMs such as crosvm rely on.
- Merge the pKVM shadow vcpu state tracking that allows the hypervisor
to have its own view of a vcpu, keeping that state private.
- Add support for the PMUv3p5 architecture revision, bringing support
for 64bit counters on systems that support it, and fix the
no-quite-compliant CHAIN-ed counter support for the machines that
actually exist out there.
- Fix a handful of minor issues around 52bit VA/PA support (64kB pages
only) as a prefix of the oncoming support for 4kB and 16kB pages.
- Add/Enable/Fix a bunch of selftests covering memslots, breakpoints,
stage-2 faults and access tracking. You name it, we got it, we
probably broke it.
- Pick a small set of documentation and spelling fixes, because no
good merge window would be complete without those.
As a side effect, this tag also drags:
- The 'kvmarm-fixes-6.1-3' tag as a dependency to the dirty-ring
series
- A shared branch with the arm64 tree that repaints all the system
registers to match the ARM ARM's naming, and resulting in
interesting conflicts
-----BEGIN PGP SIGNATURE-----
iQJDBAABCgAtFiEEn9UcU+C1Yxj9lZw9I9DQutE9ekMFAmOODb0PHG1hekBrZXJu
ZWwub3JnAAoJECPQ0LrRPXpDztsQAInRnsgLl57/SpqhZzExNCllN6AT/bdeB3uz
rnw3ScJOV174uNKp8lnPWoTvu2YUGiVtBp6tFHhDI8le7zHX438ZT8KE5mcs8p5i
KfFKnb8SHV2DDpqkcy24c0Xl/6vsg1qkKrdfJb49yl5ZakRITDpynW/7tn6dXsxX
wASeGFdCYeW4g2xMQzsCbtx6LgeQ8uomBmzRfPrOtZHYYxAn6+4Mj4595EC1sWxM
AQnbp8tW3Vw46saEZAQvUEOGOW9q0Nls7G21YqQ52IA+ZVDK1LmAF2b1XY3edjkk
pX8EsXOURfqdasBxfSfF3SgnUazoz9GHpSzp1cTVTktrPp40rrT7Ldtml0ktq69d
1malPj47KVMDsIq0kNJGnMxciXFgAHw+VaCQX+k4zhIatNwviMbSop2fEoxj22jc
4YGgGOxaGrnvmAJhreCIbr4CkZk5CJ8Zvmtfg+QM6npIp8BY8896nvORx/d4i6tT
H4caadd8AAR56ANUyd3+KqF3x0WrkaU0PLHJLy1tKwOXJUUTjcpvIfahBAAeUlSR
qEFrtb+EEMPgAwLfNOICcNkPZR/yyuYvM+FiUQNVy5cNiwFkpztpIctfOFaHySGF
K07O2/a1F6xKL0OKRUg7hGKknF9ecmux4vHhiUMuIk9VOgNTWobHozBDorLKXMzC
aWa6oGVC
=iIPT
-----END PGP SIGNATURE-----
Merge tag 'kvmarm-6.2' of https://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into HEAD
KVM/arm64 updates for 6.2
- Enable the per-vcpu dirty-ring tracking mechanism, together with an
option to keep the good old dirty log around for pages that are
dirtied by something other than a vcpu.
- Switch to the relaxed parallel fault handling, using RCU to delay
page table reclaim and giving better performance under load.
- Relax the MTE ABI, allowing a VMM to use the MAP_SHARED mapping
option, which multi-process VMMs such as crosvm rely on.
- Merge the pKVM shadow vcpu state tracking that allows the hypervisor
to have its own view of a vcpu, keeping that state private.
- Add support for the PMUv3p5 architecture revision, bringing support
for 64bit counters on systems that support it, and fix the
no-quite-compliant CHAIN-ed counter support for the machines that
actually exist out there.
- Fix a handful of minor issues around 52bit VA/PA support (64kB pages
only) as a prefix of the oncoming support for 4kB and 16kB pages.
- Add/Enable/Fix a bunch of selftests covering memslots, breakpoints,
stage-2 faults and access tracking. You name it, we got it, we
probably broke it.
- Pick a small set of documentation and spelling fixes, because no
good merge window would be complete without those.
As a side effect, this tag also drags:
- The 'kvmarm-fixes-6.1-3' tag as a dependency to the dirty-ring
series
- A shared branch with the arm64 tree that repaints all the system
registers to match the ARM ARM's naming, and resulting in
interesting conflicts
2022-12-06 12:27:39 -05:00
while ( ! READ_ONCE ( memstress_args . stop_vcpus ) ) {
2022-06-02 13:41:33 -07:00
ret = _vcpu_run ( vcpu ) ;
2021-01-12 13:42:53 -08:00
TEST_ASSERT ( ret = = 0 , " vcpu_run failed: %d \n " , ret ) ;
2022-06-02 13:41:33 -07:00
if ( get_ucall ( vcpu , NULL ) = = UCALL_SYNC )
2021-01-12 13:42:53 -08:00
continue ;
TEST_ASSERT ( false ,
" Invalid guest sync status: exit_reason=%s \n " ,
exit_reason_str ( run - > exit_reason ) ) ;
}
}
struct memslot_antagonist_args {
struct kvm_vm * vm ;
useconds_t delay ;
uint64_t nr_modifications ;
} ;
static void add_remove_memslot ( struct kvm_vm * vm , useconds_t delay ,
2021-05-21 17:38:28 +00:00
uint64_t nr_modifications )
2021-01-12 13:42:53 -08:00
{
2022-10-13 14:30:20 +08:00
uint64_t pages = max_t ( int , vm - > page_size , getpagesize ( ) ) / vm - > page_size ;
2021-05-21 17:38:28 +00:00
uint64_t gpa ;
2021-01-12 13:42:53 -08:00
int i ;
2021-05-21 17:38:28 +00:00
/*
2022-10-12 09:57:27 -07:00
* Add the dummy memslot just below the memstress memslot , which is
2021-05-21 17:38:28 +00:00
* at the top of the guest physical address space .
*/
2022-10-12 09:57:29 -07:00
gpa = memstress_args . gpa - pages * vm - > page_size ;
2021-05-21 17:38:28 +00:00
2021-01-12 13:42:53 -08:00
for ( i = 0 ; i < nr_modifications ; i + + ) {
usleep ( delay ) ;
vm_userspace_mem_region_add ( vm , VM_MEM_SRC_ANONYMOUS , gpa ,
2021-05-21 17:38:28 +00:00
DUMMY_MEMSLOT_INDEX , pages , 0 ) ;
2021-01-12 13:42:53 -08:00
vm_mem_region_delete ( vm , DUMMY_MEMSLOT_INDEX ) ;
}
}
struct test_params {
2022-11-03 12:17:17 -07:00
useconds_t delay ;
uint64_t nr_iterations ;
2021-01-12 13:42:53 -08:00
bool partition_vcpu_memory_access ;
} ;
static void run_test ( enum vm_guest_mode mode , void * arg )
{
struct test_params * p = arg ;
struct kvm_vm * vm ;
2022-10-12 09:57:29 -07:00
vm = memstress_create_vm ( mode , nr_vcpus , guest_percpu_mem_size , 1 ,
2021-11-11 00:03:09 +00:00
VM_MEM_SRC_ANONYMOUS ,
p - > partition_vcpu_memory_access ) ;
2021-01-12 13:42:53 -08:00
pr_info ( " Finished creating vCPUs \n " ) ;
2022-10-12 09:57:29 -07:00
memstress_start_vcpu_threads ( nr_vcpus , vcpu_worker ) ;
2021-01-12 13:42:53 -08:00
pr_info ( " Started all vCPUs \n " ) ;
2022-11-03 12:17:17 -07:00
add_remove_memslot ( vm , p - > delay , p - > nr_iterations ) ;
2021-01-12 13:42:53 -08:00
2022-10-12 09:57:29 -07:00
memstress_join_vcpu_threads ( nr_vcpus ) ;
2021-01-12 13:42:53 -08:00
pr_info ( " All vCPU threads joined \n " ) ;
2022-10-12 09:57:29 -07:00
memstress_destroy_vm ( vm ) ;
2021-01-12 13:42:53 -08:00
}
static void help ( char * name )
{
puts ( " " ) ;
printf ( " usage: %s [-h] [-m mode] [-d delay_usec] \n "
" [-b memory] [-v vcpus] [-o] [-i iterations] \n " , name ) ;
guest_modes_help ( ) ;
printf ( " -d: add a delay between each iteration of adding and \n "
" deleting a memslot in usec. \n " ) ;
printf ( " -b: specify the size of the memory region which should be \n "
" accessed by each vCPU. e.g. 10M or 3G. \n "
" Default: 1G \n " ) ;
printf ( " -v: specify the number of vCPUs to run. \n " ) ;
printf ( " -o: Overlap guest memory accesses instead of partitioning \n "
" them into a separate region of memory for each vCPU. \n " ) ;
printf ( " -i: specify the number of iterations of adding and removing \n "
" a memslot. \n "
" Default: %d \n " , DEFAULT_MEMSLOT_MODIFICATION_ITERATIONS ) ;
puts ( " " ) ;
exit ( 0 ) ;
}
int main ( int argc , char * argv [ ] )
{
int max_vcpus = kvm_check_cap ( KVM_CAP_MAX_VCPUS ) ;
int opt ;
struct test_params p = {
2022-11-03 12:17:17 -07:00
. delay = 0 ,
. nr_iterations = DEFAULT_MEMSLOT_MODIFICATION_ITERATIONS ,
2021-01-12 13:42:53 -08:00
. partition_vcpu_memory_access = true
} ;
guest_modes_append_default ( ) ;
while ( ( opt = getopt ( argc , argv , " hm:d:b:v:oi: " ) ) ! = - 1 ) {
switch ( opt ) {
case ' m ' :
guest_modes_cmdline ( optarg ) ;
break ;
case ' d ' :
2022-11-03 12:17:18 -07:00
p . delay = atoi_non_negative ( " Delay " , optarg ) ;
2021-01-12 13:42:53 -08:00
break ;
case ' b ' :
guest_percpu_mem_size = parse_size ( optarg ) ;
break ;
case ' v ' :
2022-11-03 12:17:18 -07:00
nr_vcpus = atoi_positive ( " Number of vCPUs " , optarg ) ;
TEST_ASSERT ( nr_vcpus < = max_vcpus ,
2021-01-12 13:42:53 -08:00
" Invalid number of vcpus, must be between 1 and %d " ,
max_vcpus ) ;
break ;
case ' o ' :
p . partition_vcpu_memory_access = false ;
break ;
case ' i ' :
2022-11-03 12:17:18 -07:00
p . nr_iterations = atoi_positive ( " Number of iterations " , optarg ) ;
2021-01-12 13:42:53 -08:00
break ;
case ' h ' :
default :
help ( argv [ 0 ] ) ;
break ;
}
}
for_each_guest_mode ( run_test , & p ) ;
return 0 ;
}