#include <sys/sysmacros.h>
#include <sys/machsystm.h>
#include <sys/cpu.h>
#include <sys/intreg.h>
#include <sys/machcpuvar.h>
#include <vm/hat_sfmmu.h>
#include <sys/error.h>
#include <sys/hypervisor_api.h>
void
cpu_intrq_register(struct cpu *cpu)
{
struct machcpu *mcpup = &cpu->cpu_m;
uint64_t ret;
ret = hv_cpu_qconf(INTR_CPU_Q, mcpup->cpu_q_base_pa, cpu_q_entries);
if (ret != H_EOK)
cmn_err(CE_PANIC, "cpu%d: cpu_mondo queue configuration "
"failed, error %lu", cpu->cpu_id, ret);
ret = hv_cpu_qconf(INTR_DEV_Q, mcpup->dev_q_base_pa, dev_q_entries);
if (ret != H_EOK)
cmn_err(CE_PANIC, "cpu%d: dev_mondo queue configuration "
"failed, error %lu", cpu->cpu_id, ret);
ret = hv_cpu_qconf(CPU_RQ, mcpup->cpu_rq_base_pa, cpu_rq_entries);
if (ret != H_EOK)
cmn_err(CE_PANIC, "cpu%d: resumable error queue configuration "
"failed, error %lu", cpu->cpu_id, ret);
ret = hv_cpu_qconf(CPU_NRQ, mcpup->cpu_nrq_base_pa, cpu_nrq_entries);
if (ret != H_EOK)
cmn_err(CE_PANIC, "cpu%d: non-resumable error queue "
"configuration failed, error %lu", cpu->cpu_id, ret);
}
int
cpu_intrq_setup(struct cpu *cpu)
{
struct machcpu *mcpup = &cpu->cpu_m;
size_t size;
mcpup->mondo_data = contig_mem_alloc(INTR_REPORT_SIZE);
if (mcpup->mondo_data == NULL) {
cmn_err(CE_NOTE, "cpu%d: cpu mondo_data allocation failed",
cpu->cpu_id);
return (ENOMEM);
}
mcpup->mondo_data_ra = va_to_pa(mcpup->mondo_data);
size = ncpu_guest_max * sizeof (uint16_t);
if (size < INTR_REPORT_SIZE)
size = INTR_REPORT_SIZE;
if (!ISP2(size)) {
size = 1 << highbit(size);
}
mcpup->cpu_list = contig_mem_alloc(size);
if (mcpup->cpu_list == NULL) {
cmn_err(CE_NOTE, "cpu%d: cpu cpu_list allocation failed",
cpu->cpu_id);
return (ENOMEM);
}
mcpup->cpu_list_ra = va_to_pa(mcpup->cpu_list);
size = cpu_q_entries * INTR_REPORT_SIZE;
mcpup->cpu_q_va = contig_mem_alloc(size);
if (mcpup->cpu_q_va == NULL) {
cmn_err(CE_NOTE, "cpu%d: cpu intrq allocation failed",
cpu->cpu_id);
return (ENOMEM);
}
mcpup->cpu_q_base_pa = va_to_pa(mcpup->cpu_q_va);
mcpup->cpu_q_size = size;
size = dev_q_entries * INTR_REPORT_SIZE;
mcpup->dev_q_va = contig_mem_alloc(size);
if (mcpup->dev_q_va == NULL) {
cmn_err(CE_NOTE, "cpu%d: dev intrq allocation failed",
cpu->cpu_id);
return (ENOMEM);
}
mcpup->dev_q_base_pa = va_to_pa(mcpup->dev_q_va);
mcpup->dev_q_size = size;
size = cpu_rq_entries * Q_ENTRY_SIZE;
mcpup->cpu_rq_va = contig_mem_alloc(2 * size);
if (mcpup->cpu_rq_va == NULL) {
cmn_err(CE_NOTE, "cpu%d: resumable queue allocation failed",
cpu->cpu_id);
return (ENOMEM);
}
mcpup->cpu_rq_base_pa = va_to_pa(mcpup->cpu_rq_va);
mcpup->cpu_rq_size = size;
bzero(mcpup->cpu_rq_va, 2 * size);
size = cpu_nrq_entries * Q_ENTRY_SIZE;
mcpup->cpu_nrq_va = contig_mem_alloc(2 * size);
if (mcpup->cpu_nrq_va == NULL) {
cmn_err(CE_NOTE, "cpu%d: nonresumable queue allocation failed",
cpu->cpu_id);
return (ENOMEM);
}
mcpup->cpu_nrq_base_pa = va_to_pa(mcpup->cpu_nrq_va);
mcpup->cpu_nrq_size = size;
bzero(mcpup->cpu_nrq_va, 2 * size);
return (0);
}
void
cpu_intrq_cleanup(struct cpu *cpu)
{
struct machcpu *mcpup = &cpu->cpu_m;
int cpu_list_size;
uint64_t cpu_q_size;
uint64_t dev_q_size;
uint64_t cpu_rq_size;
uint64_t cpu_nrq_size;
if (mcpup->mondo_data) {
contig_mem_free(mcpup->mondo_data, INTR_REPORT_SIZE);
mcpup->mondo_data = NULL;
mcpup->mondo_data_ra = 0;
}
cpu_list_size = ncpu_guest_max * sizeof (uint16_t);
if (cpu_list_size < INTR_REPORT_SIZE)
cpu_list_size = INTR_REPORT_SIZE;
if (!ISP2(cpu_list_size)) {
cpu_list_size = 1 << highbit(cpu_list_size);
}
if (mcpup->cpu_list) {
contig_mem_free(mcpup->cpu_list, cpu_list_size);
mcpup->cpu_list = NULL;
mcpup->cpu_list_ra = 0;
}
if (mcpup->cpu_q_va) {
cpu_q_size = cpu_q_entries * INTR_REPORT_SIZE;
contig_mem_free(mcpup->cpu_q_va, cpu_q_size);
mcpup->cpu_q_va = NULL;
mcpup->cpu_q_base_pa = 0;
mcpup->cpu_q_size = 0;
}
if (mcpup->dev_q_va) {
dev_q_size = dev_q_entries * INTR_REPORT_SIZE;
contig_mem_free(mcpup->dev_q_va, dev_q_size);
mcpup->dev_q_va = NULL;
mcpup->dev_q_base_pa = 0;
mcpup->dev_q_size = 0;
}
if (mcpup->cpu_rq_va) {
cpu_rq_size = cpu_rq_entries * Q_ENTRY_SIZE;
contig_mem_free(mcpup->cpu_rq_va, 2 * cpu_rq_size);
mcpup->cpu_rq_va = NULL;
mcpup->cpu_rq_base_pa = 0;
mcpup->cpu_rq_size = 0;
}
if (mcpup->cpu_nrq_va) {
cpu_nrq_size = cpu_nrq_entries * Q_ENTRY_SIZE;
contig_mem_free(mcpup->cpu_nrq_va, 2 * cpu_nrq_size);
mcpup->cpu_nrq_va = NULL;
mcpup->cpu_nrq_base_pa = 0;
mcpup->cpu_nrq_size = 0;
}
}