@@ -403,6 +403,87 @@ int32_t pio_instr_vmexit_handler(struct acrn_vcpu *vcpu)
403
403
return status ;
404
404
}
405
405
406
+ int32_t ept_violation_vmexit_handler (struct acrn_vcpu * vcpu )
407
+ {
408
+ int32_t status = - EINVAL , ret ;
409
+ uint64_t exit_qual ;
410
+ uint64_t gpa ;
411
+ struct io_request * io_req = & vcpu -> req ;
412
+ struct mmio_request * mmio_req = & io_req -> reqs .mmio ;
413
+
414
+ /* Handle page fault from guest */
415
+ exit_qual = vcpu -> arch .exit_qualification ;
416
+
417
+ io_req -> type = REQ_MMIO ;
418
+
419
+ /* Specify if read or write operation */
420
+ if ((exit_qual & 0x2UL ) != 0UL ) {
421
+ /* Write operation */
422
+ mmio_req -> direction = REQUEST_WRITE ;
423
+ mmio_req -> value = 0UL ;
424
+
425
+ /* XXX: write access while EPT perm RX -> WP */
426
+ if ((exit_qual & 0x38UL ) == 0x28UL ) {
427
+ io_req -> type = REQ_WP ;
428
+ }
429
+ } else {
430
+ /* Read operation */
431
+ mmio_req -> direction = REQUEST_READ ;
432
+
433
+ /* TODO: Need to determine how sign extension is determined for
434
+ * reads
435
+ */
436
+ }
437
+
438
+ /* Get the guest physical address */
439
+ gpa = exec_vmread64 (VMX_GUEST_PHYSICAL_ADDR_FULL );
440
+
441
+ TRACE_2L (TRACE_VMEXIT_EPT_VIOLATION , exit_qual , gpa );
442
+
443
+ /* Adjust IPA appropriately and OR page offset to get full IPA of abort
444
+ */
445
+ mmio_req -> address = gpa ;
446
+
447
+ ret = decode_instruction (vcpu );
448
+ if (ret > 0 ) {
449
+ mmio_req -> size = (uint64_t )ret ;
450
+ /*
451
+ * For MMIO write, ask DM to run MMIO emulation after
452
+ * instruction emulation. For MMIO read, ask DM to run MMIO
453
+ * emulation at first.
454
+ */
455
+
456
+ /* Determine value being written. */
457
+ if (mmio_req -> direction == REQUEST_WRITE ) {
458
+ status = emulate_instruction (vcpu );
459
+ if (status != 0 ) {
460
+ ret = - EFAULT ;
461
+ }
462
+ }
463
+
464
+ if (ret > 0 ) {
465
+ status = emulate_io (vcpu , io_req );
466
+ if (status == 0 ) {
467
+ emulate_mmio_post (vcpu , io_req );
468
+ } else {
469
+ if (status == IOREQ_PENDING ) {
470
+ status = 0 ;
471
+ }
472
+ }
473
+ }
474
+ } else {
475
+ if (ret == - EFAULT ) {
476
+ pr_info ("page fault happen during decode_instruction" );
477
+ status = 0 ;
478
+ }
479
+ }
480
+
481
+ if (ret <= 0 ) {
482
+ pr_acrnlog ("Guest Linear Address: 0x%016llx" , exec_vmread (VMX_GUEST_LINEAR_ADDR ));
483
+ pr_acrnlog ("Guest Physical Address address: 0x%016llx" , gpa );
484
+ }
485
+ return status ;
486
+ }
406
487
407
488
/**
408
489
* @brief Allow a VM to access a port I/O range
0 commit comments