| Current File : //usr/share/src/uts/i86pc/sys/zvmm/zvmm_mach_hcall.h |
/*
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _SYS_ZVMM_MACH_HCALL_H
#define _SYS_ZVMM_MACH_HCALL_H
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* This is the argument used by the ZVCNTRL_START_CPU hypercall
*/
typedef struct zvg_start_cpu {
ushort_t zvg_which_cpu;
ushort_t zvg_idt_lim;
ushort_t zvg_gdt_lim;
uint64_t zvg_idt_base;
uint64_t zvg_gdt_base;
uint64_t zvg_gsbase;
uint64_t zvg_tss_base;
uint64_t zvg_stack;
uint64_t zvg_entry;
} zvg_start_cpu_t;
/*
* zvmm passes initial info to the guest in this structure.
* zvboot loader module is invoked with the following setup:
*
* full 64 bit paging mode, RAM (up to free_mem_start) is addressible
* where virtual address == physical address.
*
* Since the Solaris kernel loads from 4Meg to just above 12Meg, the zvboot
* loader program should avoid that address range.
*
* %rdi points to zv_boot_info, somewhere in mapped memory.
* %rsp points to a large stack area, also in mapped memory.
*
* all memory above free_mem_start is available.
*/
typedef struct zv_boot_info {
void *zv_ramdisk_start;
size_t zv_ramdisk_size;
void *free_mem_start; /* start of avail mem */
struct boot_memlist *zv_memlist;
uint_t zv_ncpu;
} zv_boot_info_t;
/*
* Structure used to track pending interrupt numbers for zvpsm interrupts.
*
* On older guests we allocate and maintain this information inside the host
* zvmm module. The guests determine which interrupt number to service at a
* given PIL by using the ZVCNTRL_READ_PILQ hcall after taking an interrupt
* at the given PIL's vector. The host code for that hypercall manages the
* interrupt queues and handles any APIC end-of-interrupt processing.
*
* For newer guests on h/w with APIC virtualization the guest can avoid all
* the hypercall overhead. The guest must identify memory to use for this
* data structure (2 contiguous pages) for each VCPU with the ZVCNTRL_MAP_PILQ
* hypercall on each VCPU before enabling interrupts on the VCPU. Then the
* guest VCPUs can pull entries from a given VCPU PIL queue on its own. When
* the guest VCPU empties the PIL queue it must cause APIC end-of-interrupt
* processing. The guest does this with a wrmsr of 0 to the MSR returned
* from the MAP_PILQ call. Note that that MSR will be the x2apic EOI MSR,
* but no other actual configuration of the x2APIC in the guest is needed.
*
* Use ZVCNTRL_FEATURE to detect support for ZVCNTRL_MAP_PILQ. A given guest
* should use only ZVCNTRL_READ_PILQ or ZVCNTRL_MAP_PILQ. As soon as one is
* invoked the other other hcall becomes invalid within that guest.
*
* For correct operation, a guest *must* only ever change the ziq_next field by
* incrementing it up to ziq_last as it consumes interrupts from the queue.
* A value of 0xffff in ziq_q is used to mean "no interrupt". If the guest
* finds this value it should skip to the next entry in the queue -- treating
* it as a spurious interrupt. It is recommended that a guest write the 0xffff
* value to each entry at ziq_next before incrementing ziq_next being careful
* to observe write order (ie. use sfence).
*
* Note the structure reflects a single PIL. The 2 pages contain an array
* of 14 of these. We only need 14, as vectors < 0x20 (which would be PIL 0 and
* PIL 1) aren't used for interrupts on x86.
*/
/* get the pointer to a PIL's zv_int_queue_t */
#define PIL_TO_ZIQ(base, pil) (((zv_int_queue_t *)(base)) + (pil) - 2)
#define ZV_NUM_PILQ 14
#define ZIQ_EMPTY(q) ((q)->ziq_next == (q)->ziq_last)
#define ZIQ_FULL(q) ((q)->ziq_last + 1 == (q)->ziq_next)
typedef struct zv_int_queue {
volatile uint8_t ziq_next; /* index of next to process */
volatile uint8_t ziq_last; /* index of last to process */
uint8_t ziq_oflow; /* flags that a new enqueue failed */
uint8_t ziq_pad;
uint16_t ziq_q[256];
} zv_int_queue_t;
/*
* The array of zv_int_queue_t's must be stored across 2 pages. When it comes
* from guest memory those pages must be contiguous and aligned so that they
* are contiguous in host phys memory / kpm mappings.
*/
#define ZV_INT_Q_SIZE 8192
#ifdef __cplusplus
}
#endif
#endif /* _SYS_ZVMM_MACH_HCALL_H */