Unified · Split
| @@ -7196,6 +7196,10 @@ The valid value for 'flags' is: · 7195 unmodified lines | ||
| 7196 | 7196 | u64 leaf; |
| 7197 | 7197 | u64 r11, r12, r13, r14; |
| 7198 | 7198 | } get_tdvmcall_info; |
| 7199 | + struct { | |
| 7200 | + u64 ret; | |
| 7201 | + u64 vector; | |
| 7202 | + } setup_event_notify; | |
| 7199 | 7203 | }; |
| 7200 | 7204 | } tdx; |
| 7201 | 7205 | |
| @@ -7226,6 +7230,9 @@ status of TDVMCALLs. The output values for the given leaf should be · 24 unmodified lines | ||
| 7226 | 7230 | placed in fields from ``r11`` to ``r14`` of the ``get_tdvmcall_info`` |
| 7227 | 7231 | field of the union. |
| 7228 | 7232 | |
| 7233 | +* ``TDVMCALL_SETUP_EVENT_NOTIFY_INTERRUPT``: the guest has requested to | |
| 7234 | +set up a notification interrupt for vector ``vector``. | |
| 7235 | + | |
| 7229 | 7236 | KVM may add support for more values in the future that may cause a userspace |
| 7230 | 7237 | exit, even without calls to ``KVM_ENABLE_CAP`` or similar. In this case, |
| 7231 | 7238 | it will enter with output fields already valid; in the common case, the |
| @@ -72,6 +72,7 @@ · 71 unmodified lines | ||
| 72 | 72 | #define TDVMCALL_MAP_GPA 0x10001 |
| 73 | 73 | #define TDVMCALL_GET_QUOTE 0x10002 |
| 74 | 74 | #define TDVMCALL_REPORT_FATAL_ERROR 0x10003 |
| 75 | +#define TDVMCALL_SETUP_EVENT_NOTIFY_INTERRUPT 0x10004ULL | |
| 75 | 76 | |
| 76 | 77 | /* |
| 77 | 78 | * TDG.VP.VMCALL Status Codes (returned in R10) |
| @@ -1530,6 +1530,27 @@ static int tdx_get_quote(struct kvm_vcpu *vcpu) · 1529 unmodified lines | ||
| 1530 | 1530 | return 0; |
| 1531 | 1531 | } |
| 1532 | 1532 | |
| 1533 | +static int tdx_setup_event_notify_interrupt(struct kvm_vcpu *vcpu) | |
| 1534 | +{ | |
| 1535 | + struct vcpu_tdx *tdx = to_tdx(vcpu); | |
| 1536 | + u64 vector = tdx->vp_enter_args.r12; | |
| 1537 | + | |
| 1538 | + if (vector < 32 || vector > 255) { | |
| 1539 | + tdvmcall_set_return_code(vcpu, TDVMCALL_STATUS_INVALID_OPERAND); | |
| 1540 | + return 1; | |
| 1541 | + } | |
| 1542 | + | |
| 1543 | + vcpu->run->exit_reason = KVM_EXIT_TDX; | |
| 1544 | + vcpu->run->tdx.flags = 0; | |
| 1545 | + vcpu->run->tdx.nr = TDVMCALL_SETUP_EVENT_NOTIFY_INTERRUPT; | |
| 1546 | + vcpu->run->tdx.setup_event_notify.ret = TDVMCALL_STATUS_SUBFUNC_UNSUPPORTED; | |
| 1547 | + vcpu->run->tdx.setup_event_notify.vector = vector; | |
| 1548 | + | |
| 1549 | + vcpu->arch.complete_userspace_io = tdx_complete_simple; | |
| 1550 | + | |
| 1551 | + return 0; | |
| 1552 | +} | |
| 1553 | + | |
| 1533 | 1554 | static int handle_tdvmcall(struct kvm_vcpu *vcpu) |
| 1534 | 1555 | { |
| 1535 | 1556 | switch (tdvmcall_leaf(vcpu)) { |
| @@ -1541,6 +1562,8 @@ static int handle_tdvmcall(struct kvm_vcpu *vcpu) · 5 unmodified lines | ||
| 1541 | 1562 | return tdx_get_td_vm_call_info(vcpu); |
| 1542 | 1563 | case TDVMCALL_GET_QUOTE: |
| 1543 | 1564 | return tdx_get_quote(vcpu); |
| 1565 | + case TDVMCALL_SETUP_EVENT_NOTIFY_INTERRUPT: | |
| 1566 | + return tdx_setup_event_notify_interrupt(vcpu); | |
| 1544 | 1567 | default: |
| 1545 | 1568 | break; |
| 1546 | 1569 | } |
| @@ -467,6 +467,10 @@ struct kvm_run { · 466 unmodified lines | ||
| 467 | 467 | __u64 leaf; |
| 468 | 468 | __u64 r11, r12, r13, r14; |
| 469 | 469 | } get_tdvmcall_info; |
| 470 | + struct { | |
| 471 | + __u64 ret; | |
| 472 | + __u64 vector; | |
| 473 | + } setup_event_notify; | |
| 470 | 474 | }; |
| 471 | 475 | } tdx; |
| 472 | 476 | /* Fix the size of the union. */ |