~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/kvm/x86_64/userspace_io_test.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 #include <fcntl.h>
  3 #include <stdio.h>
  4 #include <stdlib.h>
  5 #include <string.h>
  6 #include <sys/ioctl.h>
  7 
  8 #include "test_util.h"
  9 
 10 #include "kvm_util.h"
 11 #include "processor.h"
 12 
 13 static void guest_ins_port80(uint8_t *buffer, unsigned int count)
 14 {
 15         unsigned long end;
 16 
 17         if (count == 2)
 18                 end = (unsigned long)buffer + 1;
 19         else
 20                 end = (unsigned long)buffer + 8192;
 21 
 22         asm volatile("cld; rep; insb" : "+D"(buffer), "+c"(count) : "d"(0x80) : "memory");
 23         GUEST_ASSERT_EQ(count, 0);
 24         GUEST_ASSERT_EQ((unsigned long)buffer, end);
 25 }
 26 
 27 static void guest_code(void)
 28 {
 29         uint8_t buffer[8192];
 30         int i;
 31 
 32         /*
 33          * Special case tests.  main() will adjust RCX 2 => 1 and 3 => 8192 to
 34          * test that KVM doesn't explode when userspace modifies the "count" on
 35          * a userspace I/O exit.  KVM isn't required to play nice with the I/O
 36          * itself as KVM doesn't support manipulating the count, it just needs
 37          * to not explode or overflow a buffer.
 38          */
 39         guest_ins_port80(buffer, 2);
 40         guest_ins_port80(buffer, 3);
 41 
 42         /* Verify KVM fills the buffer correctly when not stuffing RCX. */
 43         memset(buffer, 0, sizeof(buffer));
 44         guest_ins_port80(buffer, 8192);
 45         for (i = 0; i < 8192; i++)
 46                 __GUEST_ASSERT(buffer[i] == 0xaa,
 47                                "Expected '0xaa', got '0x%x' at buffer[%u]",
 48                                buffer[i], i);
 49 
 50         GUEST_DONE();
 51 }
 52 
 53 int main(int argc, char *argv[])
 54 {
 55         struct kvm_vcpu *vcpu;
 56         struct kvm_regs regs;
 57         struct kvm_run *run;
 58         struct kvm_vm *vm;
 59         struct ucall uc;
 60 
 61         vm = vm_create_with_one_vcpu(&vcpu, guest_code);
 62         run = vcpu->run;
 63 
 64         memset(&regs, 0, sizeof(regs));
 65 
 66         while (1) {
 67                 vcpu_run(vcpu);
 68                 TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
 69 
 70                 if (get_ucall(vcpu, &uc))
 71                         break;
 72 
 73                 TEST_ASSERT(run->io.port == 0x80,
 74                             "Expected I/O at port 0x80, got port 0x%x", run->io.port);
 75 
 76                 /*
 77                  * Modify the rep string count in RCX: 2 => 1 and 3 => 8192.
 78                  * Note, this abuses KVM's batching of rep string I/O to avoid
 79                  * getting stuck in an infinite loop.  That behavior isn't in
 80                  * scope from a testing perspective as it's not ABI in any way,
 81                  * i.e. it really is abusing internal KVM knowledge.
 82                  */
 83                 vcpu_regs_get(vcpu, &regs);
 84                 if (regs.rcx == 2)
 85                         regs.rcx = 1;
 86                 if (regs.rcx == 3)
 87                         regs.rcx = 8192;
 88                 memset((void *)run + run->io.data_offset, 0xaa, 4096);
 89                 vcpu_regs_set(vcpu, &regs);
 90         }
 91 
 92         switch (uc.cmd) {
 93         case UCALL_DONE:
 94                 break;
 95         case UCALL_ABORT:
 96                 REPORT_GUEST_ASSERT(uc);
 97         default:
 98                 TEST_FAIL("Unknown ucall %lu", uc.cmd);
 99         }
100 
101         kvm_vm_free(vm);
102         return 0;
103 }
104 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php