mirror of
https://github.com/torvalds/linux.git
synced 2024-12-27 05:11:48 +00:00
87e27cf628
Add xen handles realted definitions for grant table which ia64/xen needs. Pointer argumsnts for ia64/xen hypercall are passed in pseudo physical address (guest physical address) so that it is required to convert guest kernel virtual address into pseudo physical address right before issuing hypercall. The xen guest handle represents such arguments. Define necessary handles and helper functions. Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp> Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
217 lines
6.9 KiB
C
217 lines
6.9 KiB
C
/******************************************************************************
|
|
* arch-x86_32.h
|
|
*
|
|
* Guest OS interface to x86 32-bit Xen.
|
|
*
|
|
* Copyright (c) 2004, K A Fraser
|
|
*/
|
|
|
|
#ifndef __XEN_PUBLIC_ARCH_X86_32_H__
|
|
#define __XEN_PUBLIC_ARCH_X86_32_H__
|
|
|
|
#ifdef __XEN__
|
|
#define __DEFINE_GUEST_HANDLE(name, type) \
|
|
typedef struct { type *p; } __guest_handle_ ## name
|
|
#else
|
|
#define __DEFINE_GUEST_HANDLE(name, type) \
|
|
typedef type * __guest_handle_ ## name
|
|
#endif
|
|
|
|
#define DEFINE_GUEST_HANDLE_STRUCT(name) \
|
|
__DEFINE_GUEST_HANDLE(name, struct name)
|
|
#define DEFINE_GUEST_HANDLE(name) __DEFINE_GUEST_HANDLE(name, name)
|
|
#define GUEST_HANDLE(name) __guest_handle_ ## name
|
|
|
|
#ifdef __XEN__
|
|
#if defined(__i386__)
|
|
#define set_xen_guest_handle(hnd, val) \
|
|
do { \
|
|
if (sizeof(hnd) == 8) \
|
|
*(uint64_t *)&(hnd) = 0; \
|
|
(hnd).p = val; \
|
|
} while (0)
|
|
#elif defined(__x86_64__)
|
|
#define set_xen_guest_handle(hnd, val) do { (hnd).p = val; } while (0)
|
|
#endif
|
|
#else
|
|
#if defined(__i386__)
|
|
#define set_xen_guest_handle(hnd, val) \
|
|
do { \
|
|
if (sizeof(hnd) == 8) \
|
|
*(uint64_t *)&(hnd) = 0; \
|
|
(hnd) = val; \
|
|
} while (0)
|
|
#elif defined(__x86_64__)
|
|
#define set_xen_guest_handle(hnd, val) do { (hnd) = val; } while (0)
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef __ASSEMBLY__
|
|
/* Guest handles for primitive C types. */
|
|
__DEFINE_GUEST_HANDLE(uchar, unsigned char);
|
|
__DEFINE_GUEST_HANDLE(uint, unsigned int);
|
|
__DEFINE_GUEST_HANDLE(ulong, unsigned long);
|
|
DEFINE_GUEST_HANDLE(char);
|
|
DEFINE_GUEST_HANDLE(int);
|
|
DEFINE_GUEST_HANDLE(long);
|
|
DEFINE_GUEST_HANDLE(void);
|
|
#endif
|
|
|
|
/*
|
|
* SEGMENT DESCRIPTOR TABLES
|
|
*/
|
|
/*
|
|
* A number of GDT entries are reserved by Xen. These are not situated at the
|
|
* start of the GDT because some stupid OSes export hard-coded selector values
|
|
* in their ABI. These hard-coded values are always near the start of the GDT,
|
|
* so Xen places itself out of the way, at the far end of the GDT.
|
|
*/
|
|
#define FIRST_RESERVED_GDT_PAGE 14
|
|
#define FIRST_RESERVED_GDT_BYTE (FIRST_RESERVED_GDT_PAGE * 4096)
|
|
#define FIRST_RESERVED_GDT_ENTRY (FIRST_RESERVED_GDT_BYTE / 8)
|
|
|
|
/*
|
|
* These flat segments are in the Xen-private section of every GDT. Since these
|
|
* are also present in the initial GDT, many OSes will be able to avoid
|
|
* installing their own GDT.
|
|
*/
|
|
#define FLAT_RING1_CS 0xe019 /* GDT index 259 */
|
|
#define FLAT_RING1_DS 0xe021 /* GDT index 260 */
|
|
#define FLAT_RING1_SS 0xe021 /* GDT index 260 */
|
|
#define FLAT_RING3_CS 0xe02b /* GDT index 261 */
|
|
#define FLAT_RING3_DS 0xe033 /* GDT index 262 */
|
|
#define FLAT_RING3_SS 0xe033 /* GDT index 262 */
|
|
|
|
#define FLAT_KERNEL_CS FLAT_RING1_CS
|
|
#define FLAT_KERNEL_DS FLAT_RING1_DS
|
|
#define FLAT_KERNEL_SS FLAT_RING1_SS
|
|
#define FLAT_USER_CS FLAT_RING3_CS
|
|
#define FLAT_USER_DS FLAT_RING3_DS
|
|
#define FLAT_USER_SS FLAT_RING3_SS
|
|
|
|
/* And the trap vector is... */
|
|
#define TRAP_INSTR "int $0x82"
|
|
|
|
/*
|
|
* Virtual addresses beyond this are not modifiable by guest OSes. The
|
|
* machine->physical mapping table starts at this address, read-only.
|
|
*/
|
|
#ifdef CONFIG_X86_PAE
|
|
#define __HYPERVISOR_VIRT_START 0xF5800000
|
|
#else
|
|
#define __HYPERVISOR_VIRT_START 0xFC000000
|
|
#endif
|
|
|
|
#ifndef HYPERVISOR_VIRT_START
|
|
#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START)
|
|
#endif
|
|
|
|
#ifndef machine_to_phys_mapping
|
|
#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
|
|
#endif
|
|
|
|
/* Maximum number of virtual CPUs in multi-processor guests. */
|
|
#define MAX_VIRT_CPUS 32
|
|
|
|
#ifndef __ASSEMBLY__
|
|
|
|
/*
|
|
* Send an array of these to HYPERVISOR_set_trap_table()
|
|
*/
|
|
#define TI_GET_DPL(_ti) ((_ti)->flags & 3)
|
|
#define TI_GET_IF(_ti) ((_ti)->flags & 4)
|
|
#define TI_SET_DPL(_ti, _dpl) ((_ti)->flags |= (_dpl))
|
|
#define TI_SET_IF(_ti, _if) ((_ti)->flags |= ((!!(_if))<<2))
|
|
|
|
struct trap_info {
|
|
uint8_t vector; /* exception vector */
|
|
uint8_t flags; /* 0-3: privilege level; 4: clear event enable? */
|
|
uint16_t cs; /* code selector */
|
|
unsigned long address; /* code offset */
|
|
};
|
|
DEFINE_GUEST_HANDLE_STRUCT(trap_info);
|
|
|
|
struct cpu_user_regs {
|
|
uint32_t ebx;
|
|
uint32_t ecx;
|
|
uint32_t edx;
|
|
uint32_t esi;
|
|
uint32_t edi;
|
|
uint32_t ebp;
|
|
uint32_t eax;
|
|
uint16_t error_code; /* private */
|
|
uint16_t entry_vector; /* private */
|
|
uint32_t eip;
|
|
uint16_t cs;
|
|
uint8_t saved_upcall_mask;
|
|
uint8_t _pad0;
|
|
uint32_t eflags; /* eflags.IF == !saved_upcall_mask */
|
|
uint32_t esp;
|
|
uint16_t ss, _pad1;
|
|
uint16_t es, _pad2;
|
|
uint16_t ds, _pad3;
|
|
uint16_t fs, _pad4;
|
|
uint16_t gs, _pad5;
|
|
};
|
|
DEFINE_GUEST_HANDLE_STRUCT(cpu_user_regs);
|
|
|
|
typedef uint64_t tsc_timestamp_t; /* RDTSC timestamp */
|
|
|
|
/*
|
|
* The following is all CPU context. Note that the fpu_ctxt block is filled
|
|
* in by FXSAVE if the CPU has feature FXSR; otherwise FSAVE is used.
|
|
*/
|
|
struct vcpu_guest_context {
|
|
/* FPU registers come first so they can be aligned for FXSAVE/FXRSTOR. */
|
|
struct { char x[512]; } fpu_ctxt; /* User-level FPU registers */
|
|
#define VGCF_I387_VALID (1<<0)
|
|
#define VGCF_HVM_GUEST (1<<1)
|
|
#define VGCF_IN_KERNEL (1<<2)
|
|
unsigned long flags; /* VGCF_* flags */
|
|
struct cpu_user_regs user_regs; /* User-level CPU registers */
|
|
struct trap_info trap_ctxt[256]; /* Virtual IDT */
|
|
unsigned long ldt_base, ldt_ents; /* LDT (linear address, # ents) */
|
|
unsigned long gdt_frames[16], gdt_ents; /* GDT (machine frames, # ents) */
|
|
unsigned long kernel_ss, kernel_sp; /* Virtual TSS (only SS1/SP1) */
|
|
unsigned long ctrlreg[8]; /* CR0-CR7 (control registers) */
|
|
unsigned long debugreg[8]; /* DB0-DB7 (debug registers) */
|
|
unsigned long event_callback_cs; /* CS:EIP of event callback */
|
|
unsigned long event_callback_eip;
|
|
unsigned long failsafe_callback_cs; /* CS:EIP of failsafe callback */
|
|
unsigned long failsafe_callback_eip;
|
|
unsigned long vm_assist; /* VMASST_TYPE_* bitmap */
|
|
};
|
|
DEFINE_GUEST_HANDLE_STRUCT(vcpu_guest_context);
|
|
|
|
struct arch_shared_info {
|
|
unsigned long max_pfn; /* max pfn that appears in table */
|
|
/* Frame containing list of mfns containing list of mfns containing p2m. */
|
|
unsigned long pfn_to_mfn_frame_list_list;
|
|
unsigned long nmi_reason;
|
|
};
|
|
|
|
struct arch_vcpu_info {
|
|
unsigned long cr2;
|
|
unsigned long pad[5]; /* sizeof(struct vcpu_info) == 64 */
|
|
};
|
|
|
|
struct xen_callback {
|
|
unsigned long cs;
|
|
unsigned long eip;
|
|
};
|
|
#endif /* !__ASSEMBLY__ */
|
|
|
|
/*
|
|
* Prefix forces emulation of some non-trapping instructions.
|
|
* Currently only CPUID.
|
|
*/
|
|
#ifdef __ASSEMBLY__
|
|
#define XEN_EMULATE_PREFIX .byte 0x0f,0x0b,0x78,0x65,0x6e ;
|
|
#define XEN_CPUID XEN_EMULATE_PREFIX cpuid
|
|
#else
|
|
#define XEN_EMULATE_PREFIX ".byte 0x0f,0x0b,0x78,0x65,0x6e ; "
|
|
#define XEN_CPUID XEN_EMULATE_PREFIX "cpuid"
|
|
#endif
|
|
|
|
#endif
|