| 1927 | } |
| 1928 | |
| 1929 | static int |
| 1930 | nested_fault(struct vm *vm, int vcpuid, uint64_t info1, uint64_t info2, |
| 1931 | uint64_t *retinfo) |
| 1932 | { |
| 1933 | enum exc_class exc1, exc2; |
| 1934 | int type1, vector1; |
| 1935 | |
| 1936 | KASSERT(info1 & VM_INTINFO_VALID, ("info1 %#lx is not valid", info1)); |
| 1937 | KASSERT(info2 & VM_INTINFO_VALID, ("info2 %#lx is not valid", info2)); |
| 1938 | |
| 1939 | /* |
| 1940 | * If an exception occurs while attempting to call the double-fault |
| 1941 | * handler the processor enters shutdown mode (aka triple fault). |
| 1942 | */ |
| 1943 | type1 = info1 & VM_INTINFO_TYPE; |
| 1944 | vector1 = info1 & 0xff; |
| 1945 | if (type1 == VM_INTINFO_HWEXCEPTION && vector1 == IDT_DF) { |
| 1946 | VCPU_CTR2(vm, vcpuid, "triple fault: info1(%#lx), info2(%#lx)", |
| 1947 | info1, info2); |
| 1948 | vm_suspend(vm, VM_SUSPEND_TRIPLEFAULT); |
| 1949 | *retinfo = 0; |
| 1950 | return (0); |
| 1951 | } |
| 1952 | |
| 1953 | /* |
| 1954 | * Table 6-5 "Conditions for Generating a Double Fault", Intel SDM, Vol3 |
| 1955 | */ |
| 1956 | exc1 = exception_class(info1); |
| 1957 | exc2 = exception_class(info2); |
| 1958 | if ((exc1 == EXC_CONTRIBUTORY && exc2 == EXC_CONTRIBUTORY) || |
| 1959 | (exc1 == EXC_PAGEFAULT && exc2 != EXC_BENIGN)) { |
| 1960 | /* Convert nested fault into a double fault. */ |
| 1961 | *retinfo = IDT_DF; |
| 1962 | *retinfo |= VM_INTINFO_VALID | VM_INTINFO_HWEXCEPTION; |
| 1963 | *retinfo |= VM_INTINFO_DEL_ERRCODE; |
| 1964 | } else { |
| 1965 | /* Handle exceptions serially */ |
| 1966 | *retinfo = info2; |
| 1967 | } |
| 1968 | return (1); |
| 1969 | } |
| 1970 | |
| 1971 | static uint64_t |
| 1972 | vcpu_exception_intinfo(struct vcpu *vcpu) |
no test coverage detected