AArch64 EL2 hypervisor for QEMU virt that boots at EL2
1

Configure Feed

Select the types of activity you want to include in your feed.

ariel / core / psci.c
2.9 kB 107 lines
1#include "hv/arch.h" 2#include "hv/log.h" 3#include "hv/psci.h" 4#include "hv/string.h" 5#include "hv/uart.h" 6 7#define PSCI32_VERSION 0x84000000ull 8#define PSCI32_CPU_SUSPEND 0x84000001ull 9#define PSCI32_CPU_OFF 0x84000002ull 10#define PSCI32_CPU_ON 0x84000003ull 11#define PSCI32_AFFINITY_INFO 0x84000004ull 12#define PSCI32_SYSTEM_OFF 0x84000008ull 13#define PSCI32_SYSTEM_RESET 0x84000009ull 14#define PSCI32_FEATURES 0x8400000aull 15#define PSCI64_CPU_SUSPEND 0xc4000001ull 16#define PSCI64_CPU_ON 0xc4000003ull 17#define PSCI64_AFFINITY_INFO 0xc4000004ull 18 19#define PSCI_RET_SUCCESS 0ull 20#define PSCI_RET_NOT_SUPPORTED UINT64_MAX 21#define PSCI_RET_INVALID_PARAMETERS (~0ull - 1ull) 22#define PSCI_RET_DENIED (~0ull - 2ull) 23 24static uint64_t g_calls; 25static uint64_t g_denied_cpu_on; 26static uint64_t g_last_function; 27 28static void log_psci(struct vcpu *vcpu, uint64_t fid, uint64_t ret) 29{ 30 struct log_event ev; 31 hv_memset(&ev, 0, sizeof(ev)); 32 ev.kind = LOG_HVC; 33 ev.vcpu = vcpu != (struct vcpu *)0 ? vcpu->id : UINT64_MAX; 34 ev.operand = fid; 35 ev.result = ret; 36 ev.reason = 320u; 37 ev.name = "psci"; 38 log_event_commit(&ev); 39} 40 41bool psci_handle_call(struct vcpu *vcpu, uint64_t function_id) 42{ 43 uint64_t ret = PSCI_RET_NOT_SUPPORTED; 44 45 if (vcpu == (struct vcpu *)0) { 46 return false; 47 } 48 49 g_calls++; 50 g_last_function = function_id; 51 switch (function_id) { 52 case PSCI32_VERSION: 53 ret = 0x00010001ull; 54 break; 55 case PSCI32_FEATURES: { 56 uint64_t query = vcpu_read_gpr(vcpu, 1u); 57 if (query == PSCI32_VERSION || query == PSCI32_FEATURES || 58 query == PSCI32_AFFINITY_INFO || query == PSCI64_AFFINITY_INFO || 59 query == PSCI32_SYSTEM_OFF || query == PSCI32_SYSTEM_RESET) { 60 ret = PSCI_RET_SUCCESS; 61 } 62 break; 63 } 64 case PSCI32_AFFINITY_INFO: 65 case PSCI64_AFFINITY_INFO: 66 ret = PSCI_RET_SUCCESS; 67 break; 68 case PSCI32_CPU_SUSPEND: 69 case PSCI64_CPU_SUSPEND: 70 ret = PSCI_RET_DENIED; 71 break; 72 case PSCI32_CPU_ON: 73 case PSCI64_CPU_ON: 74 g_denied_cpu_on++; 75 ret = PSCI_RET_DENIED; 76 break; 77 case PSCI32_CPU_OFF: 78 ret = PSCI_RET_DENIED; 79 break; 80 case PSCI32_SYSTEM_OFF: 81 case PSCI32_SYSTEM_RESET: 82 log_psci(vcpu, function_id, PSCI_RET_SUCCESS); 83 uart_puts("psci power request function="); 84 uart_put_hex64(function_id); 85 uart_puts("; halting\n"); 86 arch_halt(); 87 default: 88 ret = PSCI_RET_NOT_SUPPORTED; 89 break; 90 } 91 92 vcpu_write_gpr(vcpu, 0u, ret); 93 log_psci(vcpu, function_id, ret); 94 arch_advance_guest_pc(vcpu); 95 return true; 96} 97 98void psci_dump(void) 99{ 100 uart_puts("psci calls="); 101 uart_put_dec64(g_calls); 102 uart_puts(" denied_cpu_on="); 103 uart_put_dec64(g_denied_cpu_on); 104 uart_puts(" last="); 105 uart_put_hex64(g_last_function); 106 uart_puts("\n"); 107}