0001
0002 #include <fcntl.h>
0003 #include <stdio.h>
0004 #include <stdlib.h>
0005 #include <string.h>
0006 #include <sys/ioctl.h>
0007
0008 #include "test_util.h"
0009
0010 #include "kvm_util.h"
0011 #include "processor.h"
0012
0013 static void guest_ins_port80(uint8_t *buffer, unsigned int count)
0014 {
0015 unsigned long end;
0016
0017 if (count == 2)
0018 end = (unsigned long)buffer + 1;
0019 else
0020 end = (unsigned long)buffer + 8192;
0021
0022 asm volatile("cld; rep; insb" : "+D"(buffer), "+c"(count) : "d"(0x80) : "memory");
0023 GUEST_ASSERT_1(count == 0, count);
0024 GUEST_ASSERT_2((unsigned long)buffer == end, buffer, end);
0025 }
0026
0027 static void guest_code(void)
0028 {
0029 uint8_t buffer[8192];
0030 int i;
0031
0032
0033
0034
0035
0036
0037
0038
0039 guest_ins_port80(buffer, 2);
0040 guest_ins_port80(buffer, 3);
0041
0042
0043 memset(buffer, 0, sizeof(buffer));
0044 guest_ins_port80(buffer, 8192);
0045 for (i = 0; i < 8192; i++)
0046 GUEST_ASSERT_2(buffer[i] == 0xaa, i, buffer[i]);
0047
0048 GUEST_DONE();
0049 }
0050
0051 int main(int argc, char *argv[])
0052 {
0053 struct kvm_vcpu *vcpu;
0054 struct kvm_regs regs;
0055 struct kvm_run *run;
0056 struct kvm_vm *vm;
0057 struct ucall uc;
0058
0059
0060 setbuf(stdout, NULL);
0061
0062 vm = vm_create_with_one_vcpu(&vcpu, guest_code);
0063 run = vcpu->run;
0064
0065 memset(®s, 0, sizeof(regs));
0066
0067 while (1) {
0068 vcpu_run(vcpu);
0069
0070 TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
0071 "Unexpected exit reason: %u (%s),\n",
0072 run->exit_reason,
0073 exit_reason_str(run->exit_reason));
0074
0075 if (get_ucall(vcpu, &uc))
0076 break;
0077
0078 TEST_ASSERT(run->io.port == 0x80,
0079 "Expected I/O at port 0x80, got port 0x%x\n", run->io.port);
0080
0081
0082
0083
0084
0085
0086
0087
0088 vcpu_regs_get(vcpu, ®s);
0089 if (regs.rcx == 2)
0090 regs.rcx = 1;
0091 if (regs.rcx == 3)
0092 regs.rcx = 8192;
0093 memset((void *)run + run->io.data_offset, 0xaa, 4096);
0094 vcpu_regs_set(vcpu, ®s);
0095 }
0096
0097 switch (uc.cmd) {
0098 case UCALL_DONE:
0099 break;
0100 case UCALL_ABORT:
0101 REPORT_GUEST_ASSERT_2(uc, "argN+1 = 0x%lx, argN+2 = 0x%lx");
0102 default:
0103 TEST_FAIL("Unknown ucall %lu", uc.cmd);
0104 }
0105
0106 kvm_vm_free(vm);
0107 return 0;
0108 }