mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
merge
This commit is contained in:
commit
1464591d5f
85 files changed
+2880
-973
No files matched your search
@@ -47,7 +47,7 @@ static inline int notify_via_evtchn(int port)
|
||||
{
|
||||
evtchn_op_t op;
|
||||
op.cmd = EVTCHNOP_send;
|
||||
op.u.send.local_port = port;
|
||||
op.u.send.port = port;
|
||||
return HYPERVISOR_event_channel_op(&op);
|
||||
}
|
||||
|
||||
|
||||
+151
-519
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <types.h>
|
||||
#include <xen/xen.h>
|
||||
#include <xen/dom0_ops.h>
|
||||
|
||||
/*
|
||||
* a placeholder for the start of day information passed up from the hypervisor
|
||||
@@ -37,548 +38,281 @@ void clear_evtchn(u32 port);
|
||||
* Assembler stubs for hyper-calls.
|
||||
*/
|
||||
#if defined(__i386__)
|
||||
/* Taken from Linux */
|
||||
|
||||
#ifndef __HYPERCALL_H__
|
||||
#define __HYPERCALL_H__
|
||||
|
||||
#include <xen/sched.h>
|
||||
|
||||
#define _hypercall0(type, name) \
|
||||
({ \
|
||||
long __res; \
|
||||
asm volatile ( \
|
||||
TRAP_INSTR \
|
||||
: "=a" (__res) \
|
||||
: "0" (__HYPERVISOR_##name) \
|
||||
: "memory" ); \
|
||||
(type)__res; \
|
||||
})
|
||||
|
||||
#define _hypercall1(type, name, a1) \
|
||||
({ \
|
||||
long __res, __ign1; \
|
||||
asm volatile ( \
|
||||
TRAP_INSTR \
|
||||
: "=a" (__res), "=b" (__ign1) \
|
||||
: "0" (__HYPERVISOR_##name), "1" ((long)(a1)) \
|
||||
: "memory" ); \
|
||||
(type)__res; \
|
||||
})
|
||||
|
||||
#define _hypercall2(type, name, a1, a2) \
|
||||
({ \
|
||||
long __res, __ign1, __ign2; \
|
||||
asm volatile ( \
|
||||
TRAP_INSTR \
|
||||
: "=a" (__res), "=b" (__ign1), "=c" (__ign2) \
|
||||
: "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \
|
||||
"2" ((long)(a2)) \
|
||||
: "memory" ); \
|
||||
(type)__res; \
|
||||
})
|
||||
|
||||
#define _hypercall3(type, name, a1, a2, a3) \
|
||||
({ \
|
||||
long __res, __ign1, __ign2, __ign3; \
|
||||
asm volatile ( \
|
||||
TRAP_INSTR \
|
||||
: "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
|
||||
"=d" (__ign3) \
|
||||
: "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \
|
||||
"2" ((long)(a2)), "3" ((long)(a3)) \
|
||||
: "memory" ); \
|
||||
(type)__res; \
|
||||
})
|
||||
|
||||
#define _hypercall4(type, name, a1, a2, a3, a4) \
|
||||
({ \
|
||||
long __res, __ign1, __ign2, __ign3, __ign4; \
|
||||
asm volatile ( \
|
||||
TRAP_INSTR \
|
||||
: "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
|
||||
"=d" (__ign3), "=S" (__ign4) \
|
||||
: "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \
|
||||
"2" ((long)(a2)), "3" ((long)(a3)), \
|
||||
"4" ((long)(a4)) \
|
||||
: "memory" ); \
|
||||
(type)__res; \
|
||||
})
|
||||
|
||||
#define _hypercall5(type, name, a1, a2, a3, a4, a5) \
|
||||
({ \
|
||||
long __res, __ign1, __ign2, __ign3, __ign4, __ign5; \
|
||||
asm volatile ( \
|
||||
TRAP_INSTR \
|
||||
: "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
|
||||
"=d" (__ign3), "=S" (__ign4), "=D" (__ign5) \
|
||||
: "0" (__HYPERVISOR_##name), "1" ((long)(a1)), \
|
||||
"2" ((long)(a2)), "3" ((long)(a3)), \
|
||||
"4" ((long)(a4)), "5" ((long)(a5)) \
|
||||
: "memory" ); \
|
||||
(type)__res; \
|
||||
})
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_set_trap_table(
|
||||
trap_info_t *table)
|
||||
trap_info_t *table)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ignore;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ignore)
|
||||
: "0" (__HYPERVISOR_set_trap_table), "1" (table)
|
||||
: "memory" );
|
||||
|
||||
return ret;
|
||||
return _hypercall1(int, set_trap_table, table);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_mmu_update(
|
||||
mmu_update_t *req, int count, int *success_count, domid_t domid)
|
||||
mmu_update_t *req, int count, int *success_count, domid_t domid)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign1, ign2, ign3, ign4;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
|
||||
: "0" (__HYPERVISOR_mmu_update), "1" (req), "2" (count),
|
||||
"3" (success_count), "4" (domid)
|
||||
: "memory" );
|
||||
|
||||
return ret;
|
||||
return _hypercall4(int, mmu_update, req, count, success_count, domid);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_mmuext_op(
|
||||
struct mmuext_op *op, int count, int *success_count, domid_t domid)
|
||||
struct mmuext_op *op, int count, int *success_count, domid_t domid)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign1, ign2, ign3, ign4;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
|
||||
: "0" (__HYPERVISOR_mmuext_op), "1" (op), "2" (count),
|
||||
"3" (success_count), "4" (domid)
|
||||
: "memory" );
|
||||
|
||||
return ret;
|
||||
return _hypercall4(int, mmuext_op, op, count, success_count, domid);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_set_gdt(
|
||||
unsigned long *frame_list, int entries)
|
||||
unsigned long *frame_list, int entries)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign1, ign2;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign1), "=c" (ign2)
|
||||
: "0" (__HYPERVISOR_set_gdt), "1" (frame_list), "2" (entries)
|
||||
: "memory" );
|
||||
|
||||
|
||||
return ret;
|
||||
return _hypercall2(int, set_gdt, frame_list, entries);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_stack_switch(
|
||||
unsigned long ss, unsigned long esp)
|
||||
unsigned long ss, unsigned long esp)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign1, ign2;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign1), "=c" (ign2)
|
||||
: "0" (__HYPERVISOR_stack_switch), "1" (ss), "2" (esp)
|
||||
: "memory" );
|
||||
|
||||
return ret;
|
||||
return _hypercall2(int, stack_switch, ss, esp);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_set_callbacks(
|
||||
unsigned long event_selector, unsigned long event_address,
|
||||
unsigned long failsafe_selector, unsigned long failsafe_address)
|
||||
unsigned long event_selector, unsigned long event_address,
|
||||
unsigned long failsafe_selector, unsigned long failsafe_address)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign1, ign2, ign3, ign4;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
|
||||
: "0" (__HYPERVISOR_set_callbacks), "1" (event_selector),
|
||||
"2" (event_address), "3" (failsafe_selector), "4" (failsafe_address)
|
||||
: "memory" );
|
||||
|
||||
return ret;
|
||||
return _hypercall4(int, set_callbacks,
|
||||
event_selector, event_address,
|
||||
failsafe_selector, failsafe_address);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_fpu_taskswitch(
|
||||
int set)
|
||||
int set)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign)
|
||||
: "0" (__HYPERVISOR_fpu_taskswitch), "1" (set)
|
||||
: "memory" );
|
||||
|
||||
return ret;
|
||||
return _hypercall1(int, fpu_taskswitch, set);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_yield(
|
||||
void)
|
||||
HYPERVISOR_sched_op(
|
||||
int cmd, unsigned long arg)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign)
|
||||
: "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_yield)
|
||||
: "memory", "ecx" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_block(
|
||||
void)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign1;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign1)
|
||||
: "0" (__HYPERVISOR_sched_op), "1" (SCHEDOP_block)
|
||||
: "memory", "ecx" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_shutdown(
|
||||
void)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign1;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign1)
|
||||
: "0" (__HYPERVISOR_sched_op),
|
||||
"1" (SCHEDOP_shutdown | (SHUTDOWN_poweroff << SCHEDOP_reasonshift))
|
||||
: "memory", "ecx" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_reboot(
|
||||
void)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign1;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign1)
|
||||
: "0" (__HYPERVISOR_sched_op),
|
||||
"1" (SCHEDOP_shutdown | (SHUTDOWN_reboot << SCHEDOP_reasonshift))
|
||||
: "memory", "ecx" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_suspend(
|
||||
unsigned long srec)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign1, ign2;
|
||||
|
||||
/* NB. On suspend, control software expects a suspend record in %esi. */
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign1), "=S" (ign2)
|
||||
: "0" (__HYPERVISOR_sched_op),
|
||||
"b" (SCHEDOP_shutdown | (SHUTDOWN_suspend << SCHEDOP_reasonshift)),
|
||||
"S" (srec) : "memory", "ecx");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_crash(
|
||||
void)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign1;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign1)
|
||||
: "0" (__HYPERVISOR_sched_op),
|
||||
"1" (SCHEDOP_shutdown | (SHUTDOWN_crash << SCHEDOP_reasonshift))
|
||||
: "memory", "ecx" );
|
||||
|
||||
return ret;
|
||||
return _hypercall2(int, sched_op, cmd, arg);
|
||||
}
|
||||
|
||||
static inline long
|
||||
HYPERVISOR_set_timer_op(
|
||||
u64 timeout)
|
||||
u64 timeout)
|
||||
{
|
||||
int ret;
|
||||
unsigned long timeout_hi = (unsigned long)(timeout>>32);
|
||||
unsigned long timeout_lo = (unsigned long)timeout;
|
||||
unsigned long ign1, ign2;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign1), "=c" (ign2)
|
||||
: "0" (__HYPERVISOR_set_timer_op), "b" (timeout_lo), "c" (timeout_hi)
|
||||
: "memory");
|
||||
|
||||
return ret;
|
||||
unsigned long timeout_hi = (unsigned long)(timeout>>32);
|
||||
unsigned long timeout_lo = (unsigned long)timeout;
|
||||
return _hypercall2(long, set_timer_op, timeout_lo, timeout_hi);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static inline int
|
||||
HYPERVISOR_dom0_op(
|
||||
dom0_op_t *dom0_op)
|
||||
dom0_op_t *dom0_op)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign1;
|
||||
|
||||
dom0_op->interface_version = DOM0_INTERFACE_VERSION;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign1)
|
||||
: "0" (__HYPERVISOR_dom0_op), "1" (dom0_op)
|
||||
: "memory");
|
||||
|
||||
return ret;
|
||||
dom0_op->interface_version = DOM0_INTERFACE_VERSION;
|
||||
return _hypercall1(int, dom0_op, dom0_op);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_set_debugreg(
|
||||
int reg, unsigned long value)
|
||||
int reg, unsigned long value)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign1, ign2;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign1), "=c" (ign2)
|
||||
: "0" (__HYPERVISOR_set_debugreg), "1" (reg), "2" (value)
|
||||
: "memory" );
|
||||
|
||||
return ret;
|
||||
return _hypercall2(int, set_debugreg, reg, value);
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
HYPERVISOR_get_debugreg(
|
||||
int reg)
|
||||
int reg)
|
||||
{
|
||||
unsigned long ret;
|
||||
unsigned long ign;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign)
|
||||
: "0" (__HYPERVISOR_get_debugreg), "1" (reg)
|
||||
: "memory" );
|
||||
|
||||
return ret;
|
||||
return _hypercall1(unsigned long, get_debugreg, reg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_update_descriptor(
|
||||
u64 ma, u64 desc)
|
||||
u64 ma, u64 desc)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign1, ign2, ign3, ign4;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
|
||||
: "0" (__HYPERVISOR_update_descriptor),
|
||||
"1" ((unsigned long)ma), "2" ((unsigned long)(ma>>32)),
|
||||
"3" ((unsigned long)desc), "4" ((unsigned long)(desc>>32))
|
||||
: "memory" );
|
||||
|
||||
return ret;
|
||||
return _hypercall4(int, update_descriptor, ma, ma>>32, desc, desc>>32);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_dom_mem_op(
|
||||
unsigned int op, unsigned long *extent_list,
|
||||
unsigned long nr_extents, unsigned int extent_order)
|
||||
HYPERVISOR_memory_op(
|
||||
unsigned int cmd, void *arg)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign1, ign2, ign3, ign4, ign5;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4),
|
||||
"=D" (ign5)
|
||||
: "0" (__HYPERVISOR_dom_mem_op), "1" (op), "2" (extent_list),
|
||||
"3" (nr_extents), "4" (extent_order), "5" (DOMID_SELF)
|
||||
: "memory" );
|
||||
|
||||
return ret;
|
||||
return _hypercall2(int, memory_op, cmd, arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_multicall(
|
||||
void *call_list, int nr_calls)
|
||||
void *call_list, int nr_calls)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign1, ign2;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign1), "=c" (ign2)
|
||||
: "0" (__HYPERVISOR_multicall), "1" (call_list), "2" (nr_calls)
|
||||
: "memory" );
|
||||
|
||||
return ret;
|
||||
return _hypercall2(int, multicall, call_list, nr_calls);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_update_va_mapping(
|
||||
unsigned long va, pte_t new_val, unsigned long flags)
|
||||
unsigned long va, pte_t new_val, unsigned long flags)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign1, ign2, ign3, ign4;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3), "=S" (ign4)
|
||||
: "0" (__HYPERVISOR_update_va_mapping),
|
||||
"1" (va), "2" ((new_val).pte_low),
|
||||
unsigned long pte_hi = 0;
|
||||
#ifdef CONFIG_X86_PAE
|
||||
"3" ((new_val).pte_high),
|
||||
#else
|
||||
"3" (0),
|
||||
pte_hi = new_val.pte_high;
|
||||
#endif
|
||||
"4" (flags)
|
||||
: "memory" );
|
||||
|
||||
return ret;
|
||||
return _hypercall4(int, update_va_mapping, va,
|
||||
new_val.pte_low, pte_hi, flags);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_event_channel_op(
|
||||
void *op)
|
||||
void *op)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ignore;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ignore)
|
||||
: "0" (__HYPERVISOR_event_channel_op), "1" (op)
|
||||
: "memory" );
|
||||
|
||||
return ret;
|
||||
return _hypercall1(int, event_channel_op, op);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_xen_version(
|
||||
int cmd, void *arg)
|
||||
int cmd, void *arg)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ignore, ign2;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ignore), "=c" (ign2)
|
||||
: "0" (__HYPERVISOR_xen_version), "1" (cmd), "2" (arg)
|
||||
: "memory" );
|
||||
|
||||
return ret;
|
||||
return _hypercall2(int, xen_version, cmd, arg);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_console_io(
|
||||
int cmd, int count, char *str)
|
||||
int cmd, int count, char *str)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign1, ign2, ign3;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
|
||||
: "0" (__HYPERVISOR_console_io), "1" (cmd), "2" (count), "3" (str)
|
||||
: "memory" );
|
||||
|
||||
return ret;
|
||||
return _hypercall3(int, console_io, cmd, count, str);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_physdev_op(
|
||||
void *physdev_op)
|
||||
void *physdev_op)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign)
|
||||
: "0" (__HYPERVISOR_physdev_op), "1" (physdev_op)
|
||||
: "memory" );
|
||||
|
||||
return ret;
|
||||
return _hypercall1(int, physdev_op, physdev_op);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_grant_table_op(
|
||||
unsigned int cmd, void *uop, unsigned int count)
|
||||
unsigned int cmd, void *uop, unsigned int count)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign1, ign2, ign3;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3)
|
||||
: "0" (__HYPERVISOR_grant_table_op), "1" (cmd), "2" (uop), "3" (count)
|
||||
: "memory" );
|
||||
|
||||
return ret;
|
||||
return _hypercall3(int, grant_table_op, cmd, uop, count);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_update_va_mapping_otherdomain(
|
||||
unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
|
||||
unsigned long va, pte_t new_val, unsigned long flags, domid_t domid)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign1, ign2, ign3, ign4, ign5;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign1), "=c" (ign2), "=d" (ign3),
|
||||
"=S" (ign4), "=D" (ign5)
|
||||
: "0" (__HYPERVISOR_update_va_mapping_otherdomain),
|
||||
"1" (va), "2" ((new_val).pte_low),
|
||||
unsigned long pte_hi = 0;
|
||||
#ifdef CONFIG_X86_PAE
|
||||
"3" ((new_val).pte_high),
|
||||
#else
|
||||
"3" (0),
|
||||
pte_hi = new_val.pte_high;
|
||||
#endif
|
||||
"4" (flags), "5" (domid) :
|
||||
"memory" );
|
||||
|
||||
return ret;
|
||||
return _hypercall5(int, update_va_mapping_otherdomain, va,
|
||||
new_val.pte_low, pte_hi, flags, domid);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_vm_assist(
|
||||
unsigned int cmd, unsigned int type)
|
||||
unsigned int cmd, unsigned int type)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign1, ign2;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign1), "=c" (ign2)
|
||||
: "0" (__HYPERVISOR_vm_assist), "1" (cmd), "2" (type)
|
||||
: "memory" );
|
||||
|
||||
return ret;
|
||||
return _hypercall2(int, vm_assist, cmd, type);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_boot_vcpu(
|
||||
unsigned long vcpu, vcpu_guest_context_t *ctxt)
|
||||
HYPERVISOR_vcpu_op(
|
||||
int cmd, int vcpuid, void *extra_args)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign1, ign2;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign1), "=c" (ign2)
|
||||
: "0" (__HYPERVISOR_boot_vcpu), "1" (vcpu), "2" (ctxt)
|
||||
: "memory");
|
||||
|
||||
return ret;
|
||||
return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_vcpu_down(
|
||||
int vcpu)
|
||||
HYPERVISOR_suspend(
|
||||
unsigned long srec)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign1;
|
||||
/* Yes, I really do want to clobber edx here: when we resume a
|
||||
vcpu after unpickling a multi-processor domain, it returns
|
||||
here, but clobbers all of the call clobbered registers. */
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign1)
|
||||
: "0" (__HYPERVISOR_sched_op),
|
||||
"1" (SCHEDOP_vcpu_down | (vcpu << SCHEDOP_vcpushift))
|
||||
: "memory", "ecx", "edx" );
|
||||
|
||||
return ret;
|
||||
return _hypercall3(int, sched_op, SCHEDOP_shutdown,
|
||||
SHUTDOWN_suspend, srec);
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_vcpu_up(
|
||||
int vcpu)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign1;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign1)
|
||||
: "0" (__HYPERVISOR_sched_op),
|
||||
"1" (SCHEDOP_vcpu_up | (vcpu << SCHEDOP_vcpushift))
|
||||
: "memory", "ecx" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int
|
||||
HYPERVISOR_vcpu_pickle(
|
||||
int vcpu, vcpu_guest_context_t *ctxt)
|
||||
{
|
||||
int ret;
|
||||
unsigned long ign1, ign2;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret), "=b" (ign1), "=c" (ign2)
|
||||
: "0" (__HYPERVISOR_sched_op),
|
||||
"1" (SCHEDOP_vcpu_pickle | (vcpu << SCHEDOP_vcpushift)),
|
||||
"2" (ctxt)
|
||||
: "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* __HYPERCALL_H__ */
|
||||
#elif defined(__x86_64__)
|
||||
|
||||
#define __syscall_clobber "r11","rcx","memory"
|
||||
@@ -792,106 +526,4 @@ HYPERVISOR_set_timer_op(
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static __inline__ int HYPERVISOR_dom0_op(void *dom0_op)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_dom0_op),
|
||||
_a1 (dom0_op) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __inline__ int HYPERVISOR_set_debugreg(int reg, unsigned long value)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_set_debugreg),
|
||||
_a1 (reg), _a2 (value) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __inline__ unsigned long HYPERVISOR_get_debugreg(int reg)
|
||||
{
|
||||
unsigned long ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_get_debugreg),
|
||||
_a1 (reg) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __inline__ int HYPERVISOR_update_descriptor(
|
||||
unsigned long pa, unsigned long word1, unsigned long word2)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_update_descriptor),
|
||||
_a1 (pa), _a2 (word1), _a3 (word2) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __inline__ int HYPERVISOR_dom_mem_op(void *dom_mem_op)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_memory_op),
|
||||
_a1 (dom_mem_op) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __inline__ int HYPERVISOR_multicall(void *call_list, int nr_calls)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_multicall),
|
||||
_a1 (call_list), _a2 (nr_calls) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __inline__ int HYPERVISOR_update_va_mapping(
|
||||
unsigned long page_nr, unsigned long new_val, unsigned long flags)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_update_va_mapping),
|
||||
_a1 (page_nr), _a2 (new_val), _a3 (flags) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __inline__ int HYPERVISOR_xen_version(int cmd)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_xen_version),
|
||||
_a1 (cmd) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __inline__ int HYPERVISOR_console_io(int cmd, int count, char *str)
|
||||
{
|
||||
int ret;
|
||||
__asm__ __volatile__ (
|
||||
TRAP_INSTR
|
||||
: "=a" (ret) : "0" (__HYPERVISOR_console_io),
|
||||
_a1 (cmd), _a2 (count), _a3 (str) : "memory" );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* __HYPERVISOR_H__ */
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <xen/xen.h>
|
||||
|
||||
|
||||
#define force_evtchn_callback() ((void)HYPERVISOR_xen_version(0))
|
||||
#define force_evtchn_callback() ((void)HYPERVISOR_xen_version(0, 0))
|
||||
|
||||
#define __KERNEL_CS FLAT_KERNEL_CS
|
||||
#define __KERNEL_DS FLAT_KERNEL_DS
|
||||
@@ -55,6 +55,8 @@
|
||||
/* Everything below this point is not included by assembler (.S) files. */
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
extern shared_info_t *HYPERVISOR_shared_info;
|
||||
|
||||
void trap_init(void);
|
||||
|
||||
/*
|
||||
|
||||
@@ -54,7 +54,14 @@ typedef unsigned long uintptr_t;
|
||||
typedef struct { unsigned long pte; } pte_t;
|
||||
#endif
|
||||
|
||||
|
||||
typedef u8 uint8_t;
|
||||
typedef s8 int8_t;
|
||||
typedef u16 uint16_t;
|
||||
typedef s16 int16_t;
|
||||
typedef u32 uint32_t;
|
||||
typedef s32 int32_t;
|
||||
typedef u64 uint64_t;
|
||||
typedef s64 int64_t;
|
||||
|
||||
|
||||
#define INT_MAX ((int)(~0U>>1))
|
||||
|
||||
@@ -61,7 +61,7 @@ void failsafe_callback(void);
|
||||
|
||||
extern char shared_info[PAGE_SIZE];
|
||||
|
||||
#define __pte(x) ((pte_t) { (0) } )
|
||||
#define __pte(x) ((pte_t) { (x) } )
|
||||
|
||||
static shared_info_t *map_shared_info(unsigned long pa)
|
||||
{
|
||||
@@ -150,5 +150,5 @@ void start_kernel(start_info_t *si)
|
||||
void do_exit(void)
|
||||
{
|
||||
printk("do_exit called!\n");
|
||||
for ( ;; ) HYPERVISOR_shutdown();
|
||||
for ( ;; ) HYPERVISOR_sched_op(SCHEDOP_shutdown, SHUTDOWN_crash);
|
||||
}
|
||||
@@ -208,7 +208,7 @@ void block_domain(u32 millisecs)
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv);
|
||||
HYPERVISOR_set_timer_op(monotonic_clock() + 1000000LL * (s64) millisecs);
|
||||
HYPERVISOR_block();
|
||||
HYPERVISOR_sched_op(SCHEDOP_block, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
#include <wait.h>
|
||||
#include <sched.h>
|
||||
#include <semaphore.h>
|
||||
#include "xenstored.h"
|
||||
#include <xen/io/xs_wire.h>
|
||||
#include "xenbus_comms.h"
|
||||
|
||||
#define streq(a, b) (strcmp((a), (b)) == 0)
|
||||
@@ -408,7 +408,12 @@ static char *xs_read_watch(char **token)
|
||||
|
||||
static int xs_acknowledge_watch(const char *token)
|
||||
{
|
||||
#if 0
|
||||
return xs_error(xs_single(XS_WATCH_ACK, token, NULL));
|
||||
#else
|
||||
/* XS_WATCH_ACK is no longer available */
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int xs_unwatch(const char *path, const char *token)
|
||||
|
||||
@@ -733,6 +733,7 @@ void __init setup_arch(char **cmdline_p)
|
||||
#ifdef CONFIG_XEN
|
||||
{
|
||||
int i, j, k, fpp;
|
||||
unsigned long va;
|
||||
|
||||
/* Make sure we have a large enough P->M table. */
|
||||
phys_to_machine_mapping = alloc_bootmem(
|
||||
@@ -746,9 +747,21 @@ void __init setup_arch(char **cmdline_p)
|
||||
__pa(xen_start_info->mfn_list),
|
||||
PFN_PHYS(PFN_UP(xen_start_info->nr_pages *
|
||||
sizeof(unsigned long))));
|
||||
make_pages_readonly((void *)xen_start_info->mfn_list,
|
||||
PFN_UP(xen_start_info->nr_pages *
|
||||
sizeof(unsigned long)));
|
||||
|
||||
/* 'Initial mapping' of old p2m table must be destroyed. */
|
||||
for (va = xen_start_info->mfn_list;
|
||||
va < (xen_start_info->mfn_list +
|
||||
(xen_start_info->nr_pages*sizeof(unsigned long)));
|
||||
va += PAGE_SIZE) {
|
||||
HYPERVISOR_update_va_mapping(va, __pte_ma(0), 0);
|
||||
}
|
||||
|
||||
/* 'Initial mapping' of initrd must be destroyed. */
|
||||
for (va = xen_start_info->mod_start;
|
||||
va < (xen_start_info->mod_start+xen_start_info->mod_len);
|
||||
va += PAGE_SIZE) {
|
||||
HYPERVISOR_update_va_mapping(va, __pte_ma(0), 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise the list of the frames that specify the list of
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#define evtchn_upcall_pending 0
|
||||
#define evtchn_upcall_mask 1
|
||||
|
||||
#define sizeof_vcpu_shift 3
|
||||
#define sizeof_vcpu_shift 4
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
//#define preempt_disable(reg) incl threadinfo_preempt_count(reg)
|
||||
|
||||
@@ -70,6 +70,9 @@ spinlock_t balloon_lock = SPIN_LOCK_UNLOCKED;
|
||||
static unsigned long current_pages;
|
||||
static unsigned long target_pages;
|
||||
|
||||
/* VM /proc information for memory */
|
||||
extern unsigned long totalram_pages;
|
||||
|
||||
/* We may hit the hard limit in Xen. If we do then we remember it. */
|
||||
static unsigned long hard_limit;
|
||||
|
||||
@@ -188,12 +191,13 @@ static int increase_reservation(unsigned long nr_pages)
|
||||
rc = HYPERVISOR_memory_op(
|
||||
XENMEM_increase_reservation, &reservation);
|
||||
if (rc < nr_pages) {
|
||||
int ret;
|
||||
/* We hit the Xen hard limit: reprobe. */
|
||||
reservation.extent_start = mfn_list;
|
||||
reservation.nr_extents = rc;
|
||||
BUG_ON(HYPERVISOR_memory_op(
|
||||
XENMEM_decrease_reservation,
|
||||
&reservation) != rc);
|
||||
ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
|
||||
&reservation);
|
||||
BUG_ON(ret != rc);
|
||||
hard_limit = current_pages + rc - driver_pages;
|
||||
goto out;
|
||||
}
|
||||
@@ -210,11 +214,14 @@ static int increase_reservation(unsigned long nr_pages)
|
||||
xen_machphys_update(mfn_list[i], pfn);
|
||||
|
||||
/* Link back into the page tables if not highmem. */
|
||||
if (pfn < max_low_pfn)
|
||||
BUG_ON(HYPERVISOR_update_va_mapping(
|
||||
if (pfn < max_low_pfn) {
|
||||
int ret;
|
||||
ret = HYPERVISOR_update_va_mapping(
|
||||
(unsigned long)__va(pfn << PAGE_SHIFT),
|
||||
pfn_pte_ma(mfn_list[i], PAGE_KERNEL),
|
||||
0));
|
||||
0);
|
||||
BUG_ON(ret);
|
||||
}
|
||||
|
||||
/* Relinquish the page back to the allocator. */
|
||||
ClearPageReserved(page);
|
||||
@@ -223,6 +230,7 @@ static int increase_reservation(unsigned long nr_pages)
|
||||
}
|
||||
|
||||
current_pages += nr_pages;
|
||||
totalram_pages = current_pages;
|
||||
|
||||
out:
|
||||
balloon_unlock(flags);
|
||||
@@ -238,6 +246,7 @@ static int decrease_reservation(unsigned long nr_pages)
|
||||
struct page *page;
|
||||
void *v;
|
||||
int need_sleep = 0;
|
||||
int ret;
|
||||
struct xen_memory_reservation reservation = {
|
||||
.address_bits = 0,
|
||||
.extent_order = 0,
|
||||
@@ -264,8 +273,9 @@ static int decrease_reservation(unsigned long nr_pages)
|
||||
if (!PageHighMem(page)) {
|
||||
v = phys_to_virt(pfn << PAGE_SHIFT);
|
||||
scrub_pages(v, 1);
|
||||
BUG_ON(HYPERVISOR_update_va_mapping(
|
||||
(unsigned long)v, __pte_ma(0), 0));
|
||||
ret = HYPERVISOR_update_va_mapping(
|
||||
(unsigned long)v, __pte_ma(0), 0);
|
||||
BUG_ON(ret);
|
||||
}
|
||||
#ifdef CONFIG_XEN_SCRUB_PAGES
|
||||
else {
|
||||
@@ -291,10 +301,11 @@ static int decrease_reservation(unsigned long nr_pages)
|
||||
|
||||
reservation.extent_start = mfn_list;
|
||||
reservation.nr_extents = nr_pages;
|
||||
BUG_ON(HYPERVISOR_memory_op(
|
||||
XENMEM_decrease_reservation, &reservation) != nr_pages);
|
||||
ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
|
||||
BUG_ON(ret != nr_pages);
|
||||
|
||||
current_pages -= nr_pages;
|
||||
totalram_pages = current_pages;
|
||||
|
||||
balloon_unlock(flags);
|
||||
|
||||
@@ -496,6 +507,7 @@ static int dealloc_pte_fn(
|
||||
pte_t *pte, struct page *pte_page, unsigned long addr, void *data)
|
||||
{
|
||||
unsigned long mfn = pte_mfn(*pte);
|
||||
int ret;
|
||||
struct xen_memory_reservation reservation = {
|
||||
.extent_start = &mfn,
|
||||
.nr_extents = 1,
|
||||
@@ -505,8 +517,8 @@ static int dealloc_pte_fn(
|
||||
set_pte_at(&init_mm, addr, pte, __pte_ma(0));
|
||||
phys_to_machine_mapping[__pa(addr) >> PAGE_SHIFT] =
|
||||
INVALID_P2M_ENTRY;
|
||||
BUG_ON(HYPERVISOR_memory_op(
|
||||
XENMEM_decrease_reservation, &reservation) != 1);
|
||||
ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
|
||||
BUG_ON(ret != 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -514,6 +526,7 @@ struct page *balloon_alloc_empty_page_range(unsigned long nr_pages)
|
||||
{
|
||||
unsigned long vstart, flags;
|
||||
unsigned int order = get_order(nr_pages * PAGE_SIZE);
|
||||
int ret;
|
||||
|
||||
vstart = __get_free_pages(GFP_KERNEL, order);
|
||||
if (vstart == 0)
|
||||
@@ -522,8 +535,9 @@ struct page *balloon_alloc_empty_page_range(unsigned long nr_pages)
|
||||
scrub_pages(vstart, 1 << order);
|
||||
|
||||
balloon_lock(flags);
|
||||
BUG_ON(generic_page_range(
|
||||
&init_mm, vstart, PAGE_SIZE << order, dealloc_pte_fn, NULL));
|
||||
ret = generic_page_range(
|
||||
&init_mm, vstart, PAGE_SIZE << order, dealloc_pte_fn, NULL);
|
||||
BUG_ON(ret);
|
||||
current_pages -= 1UL << order;
|
||||
balloon_unlock(flags);
|
||||
|
||||
|
||||
@@ -108,6 +108,7 @@ static void fast_flush_area(int idx, int nr_pages)
|
||||
struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
|
||||
unsigned int i, invcount = 0;
|
||||
u16 handle;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < nr_pages; i++) {
|
||||
handle = pending_handle(idx, i);
|
||||
@@ -120,8 +121,9 @@ static void fast_flush_area(int idx, int nr_pages)
|
||||
invcount++;
|
||||
}
|
||||
|
||||
BUG_ON(HYPERVISOR_grant_table_op(
|
||||
GNTTABOP_unmap_grant_ref, unmap, invcount));
|
||||
ret = HYPERVISOR_grant_table_op(
|
||||
GNTTABOP_unmap_grant_ref, unmap, invcount);
|
||||
BUG_ON(ret);
|
||||
}
|
||||
|
||||
|
||||
@@ -338,6 +340,7 @@ static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
|
||||
struct bio *bio = NULL, *biolist[BLKIF_MAX_SEGMENTS_PER_REQUEST];
|
||||
int nbio = 0;
|
||||
request_queue_t *q;
|
||||
int ret;
|
||||
|
||||
/* Check that number of segments is sane. */
|
||||
nseg = req->nr_segments;
|
||||
@@ -367,8 +370,8 @@ static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
|
||||
map[i].flags |= GNTMAP_readonly;
|
||||
}
|
||||
|
||||
BUG_ON(HYPERVISOR_grant_table_op(
|
||||
GNTTABOP_map_grant_ref, map, nseg));
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, nseg);
|
||||
BUG_ON(ret);
|
||||
|
||||
for (i = 0; i < nseg; i++) {
|
||||
if (unlikely(map[i].handle < 0)) {
|
||||
@@ -493,6 +496,7 @@ static int __init blkif_init(void)
|
||||
{
|
||||
int i;
|
||||
struct page *page;
|
||||
int ret;
|
||||
|
||||
blkif_interface_init();
|
||||
|
||||
@@ -509,7 +513,8 @@ static int __init blkif_init(void)
|
||||
spin_lock_init(&blkio_schedule_list_lock);
|
||||
INIT_LIST_HEAD(&blkio_schedule_list);
|
||||
|
||||
BUG_ON(kernel_thread(blkio_schedule, 0, CLONE_FS | CLONE_FILES) < 0);
|
||||
ret = kernel_thread(blkio_schedule, 0, CLONE_FS | CLONE_FILES);
|
||||
BUG_ON(ret < 0);
|
||||
|
||||
blkif_xenbus_init();
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ blkif_t *alloc_blkif(domid_t domid)
|
||||
static int map_frontend_page(blkif_t *blkif, unsigned long shared_page)
|
||||
{
|
||||
struct gnttab_map_grant_ref op;
|
||||
int ret;
|
||||
|
||||
op.host_addr = (unsigned long)blkif->blk_ring_area->addr;
|
||||
op.flags = GNTMAP_host_map;
|
||||
@@ -38,8 +39,9 @@ static int map_frontend_page(blkif_t *blkif, unsigned long shared_page)
|
||||
op.dom = blkif->domid;
|
||||
|
||||
lock_vm_area(blkif->blk_ring_area);
|
||||
BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1));
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
|
||||
unlock_vm_area(blkif->blk_ring_area);
|
||||
BUG_ON(ret);
|
||||
|
||||
if (op.handle < 0) {
|
||||
DPRINTK(" Grant table operation failure !\n");
|
||||
@@ -55,14 +57,16 @@ static int map_frontend_page(blkif_t *blkif, unsigned long shared_page)
|
||||
static void unmap_frontend_page(blkif_t *blkif)
|
||||
{
|
||||
struct gnttab_unmap_grant_ref op;
|
||||
int ret;
|
||||
|
||||
op.host_addr = (unsigned long)blkif->blk_ring_area->addr;
|
||||
op.handle = blkif->shmem_handle;
|
||||
op.dev_bus_addr = 0;
|
||||
|
||||
lock_vm_area(blkif->blk_ring_area);
|
||||
BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
|
||||
unlock_vm_area(blkif->blk_ring_area);
|
||||
BUG_ON(ret);
|
||||
}
|
||||
|
||||
int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn)
|
||||
|
||||
@@ -305,6 +305,7 @@ static irqreturn_t blkif_int(int irq, void *dev_id, struct pt_regs *ptregs)
|
||||
|
||||
for (i = info->ring.rsp_cons; i != rp; i++) {
|
||||
unsigned long id;
|
||||
int ret;
|
||||
|
||||
bret = RING_GET_RESPONSE(&info->ring, i);
|
||||
id = bret->id;
|
||||
@@ -321,9 +322,10 @@ static irqreturn_t blkif_int(int irq, void *dev_id, struct pt_regs *ptregs)
|
||||
DPRINTK("Bad return from blkdev data "
|
||||
"request: %x\n", bret->status);
|
||||
|
||||
BUG_ON(end_that_request_first(
|
||||
ret = end_that_request_first(
|
||||
req, (bret->status == BLKIF_RSP_OKAY),
|
||||
req->hard_nr_sectors));
|
||||
req->hard_nr_sectors);
|
||||
BUG_ON(ret);
|
||||
end_that_request_last(req);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -413,6 +413,7 @@ static void fast_flush_area(int idx, int nr_pages)
|
||||
unsigned int i, op = 0;
|
||||
struct grant_handle_pair *handle;
|
||||
unsigned long ptep;
|
||||
int ret;
|
||||
|
||||
for ( i = 0; i < nr_pages; i++)
|
||||
{
|
||||
@@ -440,8 +441,8 @@ static void fast_flush_area(int idx, int nr_pages)
|
||||
BLKTAP_INVALIDATE_HANDLE(handle);
|
||||
}
|
||||
|
||||
BUG_ON(HYPERVISOR_grant_table_op(
|
||||
GNTTABOP_unmap_grant_ref, unmap, op));
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, unmap, op);
|
||||
BUG_ON(ret);
|
||||
|
||||
if (blktap_vma != NULL)
|
||||
zap_page_range(blktap_vma,
|
||||
@@ -673,6 +674,7 @@ static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
|
||||
struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
|
||||
int op, ret;
|
||||
unsigned int nseg;
|
||||
int retval;
|
||||
|
||||
/* Check that number of segments is sane. */
|
||||
nseg = req->nr_segments;
|
||||
@@ -740,8 +742,8 @@ static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
|
||||
op++;
|
||||
}
|
||||
|
||||
BUG_ON(HYPERVISOR_grant_table_op(
|
||||
GNTTABOP_map_grant_ref, map, op));
|
||||
retval = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, map, op);
|
||||
BUG_ON(retval);
|
||||
|
||||
op = 0;
|
||||
for (i = 0; i < (req->nr_segments*2); i += 2) {
|
||||
@@ -877,7 +879,8 @@ static int __init blkif_init(void)
|
||||
spin_lock_init(&blkio_schedule_list_lock);
|
||||
INIT_LIST_HEAD(&blkio_schedule_list);
|
||||
|
||||
BUG_ON(kernel_thread(blkio_schedule, 0, CLONE_FS | CLONE_FILES) < 0);
|
||||
i = kernel_thread(blkio_schedule, 0, CLONE_FS | CLONE_FILES);
|
||||
BUG_ON(i<0);
|
||||
|
||||
blkif_xenbus_init();
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ blkif_t *alloc_blkif(domid_t domid)
|
||||
static int map_frontend_page(blkif_t *blkif, unsigned long shared_page)
|
||||
{
|
||||
struct gnttab_map_grant_ref op;
|
||||
int ret;
|
||||
|
||||
op.host_addr = (unsigned long)blkif->blk_ring_area->addr;
|
||||
op.flags = GNTMAP_host_map;
|
||||
@@ -38,8 +39,9 @@ static int map_frontend_page(blkif_t *blkif, unsigned long shared_page)
|
||||
op.dom = blkif->domid;
|
||||
|
||||
lock_vm_area(blkif->blk_ring_area);
|
||||
BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1));
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
|
||||
unlock_vm_area(blkif->blk_ring_area);
|
||||
BUG_ON(ret);
|
||||
|
||||
if (op.handle < 0) {
|
||||
DPRINTK(" Grant table operation failure !\n");
|
||||
@@ -55,14 +57,16 @@ static int map_frontend_page(blkif_t *blkif, unsigned long shared_page)
|
||||
static void unmap_frontend_page(blkif_t *blkif)
|
||||
{
|
||||
struct gnttab_unmap_grant_ref op;
|
||||
int ret;
|
||||
|
||||
op.host_addr = (unsigned long)blkif->blk_ring_area->addr;
|
||||
op.handle = blkif->shmem_handle;
|
||||
op.dev_bus_addr = 0;
|
||||
|
||||
lock_vm_area(blkif->blk_ring_area);
|
||||
BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
|
||||
unlock_vm_area(blkif->blk_ring_area);
|
||||
BUG_ON(ret);
|
||||
}
|
||||
|
||||
int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn)
|
||||
|
||||
@@ -282,6 +282,7 @@ static int evtchn_ioctl(struct inode *inode, struct file *file,
|
||||
|
||||
case IOCTL_EVTCHN_UNBIND: {
|
||||
struct ioctl_evtchn_unbind unbind;
|
||||
int ret;
|
||||
|
||||
rc = -EFAULT;
|
||||
if (copy_from_user(&unbind, (void *)arg, sizeof(unbind)))
|
||||
@@ -306,7 +307,8 @@ static int evtchn_ioctl(struct inode *inode, struct file *file,
|
||||
|
||||
op.cmd = EVTCHNOP_close;
|
||||
op.u.close.port = unbind.port;
|
||||
BUG_ON(HYPERVISOR_event_channel_op(&op));
|
||||
ret = HYPERVISOR_event_channel_op(&op);
|
||||
BUG_ON(ret);
|
||||
|
||||
rc = 0;
|
||||
break;
|
||||
@@ -399,6 +401,7 @@ static int evtchn_release(struct inode *inode, struct file *filp)
|
||||
|
||||
for (i = 0; i < NR_EVENT_CHANNELS; i++)
|
||||
{
|
||||
int ret;
|
||||
if (port_user[i] != u)
|
||||
continue;
|
||||
|
||||
@@ -407,7 +410,8 @@ static int evtchn_release(struct inode *inode, struct file *filp)
|
||||
|
||||
op.cmd = EVTCHNOP_close;
|
||||
op.u.close.port = i;
|
||||
BUG_ON(HYPERVISOR_event_channel_op(&op));
|
||||
ret = HYPERVISOR_event_channel_op(&op);
|
||||
BUG_ON(ret);
|
||||
}
|
||||
|
||||
spin_unlock_irq(&port_user_lock);
|
||||
|
||||
@@ -115,6 +115,7 @@ static int map_frontend_pages(
|
||||
netif_t *netif, grant_ref_t tx_ring_ref, grant_ref_t rx_ring_ref)
|
||||
{
|
||||
struct gnttab_map_grant_ref op;
|
||||
int ret;
|
||||
|
||||
op.host_addr = (unsigned long)netif->comms_area->addr;
|
||||
op.flags = GNTMAP_host_map;
|
||||
@@ -122,8 +123,9 @@ static int map_frontend_pages(
|
||||
op.dom = netif->domid;
|
||||
|
||||
lock_vm_area(netif->comms_area);
|
||||
BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1));
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
|
||||
unlock_vm_area(netif->comms_area);
|
||||
BUG_ON(ret);
|
||||
|
||||
if (op.handle < 0) {
|
||||
DPRINTK(" Gnttab failure mapping tx_ring_ref!\n");
|
||||
@@ -139,8 +141,9 @@ static int map_frontend_pages(
|
||||
op.dom = netif->domid;
|
||||
|
||||
lock_vm_area(netif->comms_area);
|
||||
BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1));
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
|
||||
unlock_vm_area(netif->comms_area);
|
||||
BUG_ON(ret);
|
||||
|
||||
if (op.handle < 0) {
|
||||
DPRINTK(" Gnttab failure mapping rx_ring_ref!\n");
|
||||
@@ -156,22 +159,25 @@ static int map_frontend_pages(
|
||||
static void unmap_frontend_pages(netif_t *netif)
|
||||
{
|
||||
struct gnttab_unmap_grant_ref op;
|
||||
int ret;
|
||||
|
||||
op.host_addr = (unsigned long)netif->comms_area->addr;
|
||||
op.handle = netif->tx_shmem_handle;
|
||||
op.dev_bus_addr = 0;
|
||||
|
||||
lock_vm_area(netif->comms_area);
|
||||
BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
|
||||
unlock_vm_area(netif->comms_area);
|
||||
BUG_ON(ret);
|
||||
|
||||
op.host_addr = (unsigned long)netif->comms_area->addr + PAGE_SIZE;
|
||||
op.handle = netif->rx_shmem_handle;
|
||||
op.dev_bus_addr = 0;
|
||||
|
||||
lock_vm_area(netif->comms_area);
|
||||
BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
|
||||
unlock_vm_area(netif->comms_area);
|
||||
BUG_ON(ret);
|
||||
}
|
||||
|
||||
int netif_map(netif_t *netif, unsigned long tx_ring_ref,
|
||||
|
||||
@@ -112,9 +112,12 @@ static void free_mfn(unsigned long mfn)
|
||||
spin_lock_irqsave(&mfn_lock, flags);
|
||||
if ( alloc_index != MAX_MFN_ALLOC )
|
||||
mfn_list[alloc_index++] = mfn;
|
||||
else
|
||||
BUG_ON(HYPERVISOR_memory_op(XENMEM_decrease_reservation,
|
||||
&reservation) != 1);
|
||||
else {
|
||||
int ret;
|
||||
ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
|
||||
&reservation);
|
||||
BUG_ON(ret != 1);
|
||||
}
|
||||
spin_unlock_irqrestore(&mfn_lock, flags);
|
||||
}
|
||||
#endif
|
||||
@@ -159,13 +162,15 @@ int netif_be_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
*/
|
||||
if (skb_shared(skb) || skb_cloned(skb) || !is_xen_skb(skb)) {
|
||||
int hlen = skb->data - skb->head;
|
||||
int ret;
|
||||
struct sk_buff *nskb = dev_alloc_skb(hlen + skb->len);
|
||||
if ( unlikely(nskb == NULL) )
|
||||
goto drop;
|
||||
skb_reserve(nskb, hlen);
|
||||
__skb_put(nskb, skb->len);
|
||||
BUG_ON(skb_copy_bits(skb, -hlen, nskb->data - hlen,
|
||||
skb->len + hlen));
|
||||
ret = skb_copy_bits(skb, -hlen, nskb->data - hlen,
|
||||
skb->len + hlen);
|
||||
BUG_ON(ret);
|
||||
nskb->dev = skb->dev;
|
||||
nskb->proto_csum_valid = skb->proto_csum_valid;
|
||||
dev_kfree_skb(skb);
|
||||
@@ -218,6 +223,7 @@ static void net_rx_action(unsigned long unused)
|
||||
struct sk_buff *skb;
|
||||
u16 notify_list[NETIF_RX_RING_SIZE];
|
||||
int notify_nr = 0;
|
||||
int ret;
|
||||
|
||||
skb_queue_head_init(&rxq);
|
||||
|
||||
@@ -279,7 +285,8 @@ static void net_rx_action(unsigned long unused)
|
||||
mcl++;
|
||||
|
||||
mcl[-2].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
|
||||
BUG_ON(HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl) != 0);
|
||||
ret = HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl);
|
||||
BUG_ON(ret != 0);
|
||||
|
||||
mcl = rx_mcl;
|
||||
if( HYPERVISOR_grant_table_op(GNTTABOP_transfer, grant_rx_op,
|
||||
@@ -421,6 +428,7 @@ inline static void net_tx_action_dealloc(void)
|
||||
u16 pending_idx;
|
||||
PEND_RING_IDX dc, dp;
|
||||
netif_t *netif;
|
||||
int ret;
|
||||
|
||||
dc = dealloc_cons;
|
||||
dp = dealloc_prod;
|
||||
@@ -436,8 +444,9 @@ inline static void net_tx_action_dealloc(void)
|
||||
gop->handle = grant_tx_ref[pending_idx];
|
||||
gop++;
|
||||
}
|
||||
BUG_ON(HYPERVISOR_grant_table_op(
|
||||
GNTTABOP_unmap_grant_ref, tx_unmap_ops, gop - tx_unmap_ops));
|
||||
ret = HYPERVISOR_grant_table_op(
|
||||
GNTTABOP_unmap_grant_ref, tx_unmap_ops, gop - tx_unmap_ops);
|
||||
BUG_ON(ret);
|
||||
|
||||
while (dealloc_cons != dp) {
|
||||
pending_idx = dealloc_ring[MASK_PEND_IDX(dealloc_cons++)];
|
||||
@@ -477,6 +486,7 @@ static void net_tx_action(unsigned long unused)
|
||||
NETIF_RING_IDX i;
|
||||
gnttab_map_grant_ref_t *mop;
|
||||
unsigned int data_len;
|
||||
int ret;
|
||||
|
||||
if (dealloc_cons != dealloc_prod)
|
||||
net_tx_action_dealloc();
|
||||
@@ -599,8 +609,9 @@ static void net_tx_action(unsigned long unused)
|
||||
if (mop == tx_map_ops)
|
||||
return;
|
||||
|
||||
BUG_ON(HYPERVISOR_grant_table_op(
|
||||
GNTTABOP_map_grant_ref, tx_map_ops, mop - tx_map_ops));
|
||||
ret = HYPERVISOR_grant_table_op(
|
||||
GNTTABOP_map_grant_ref, tx_map_ops, mop - tx_map_ops);
|
||||
BUG_ON(ret);
|
||||
|
||||
mop = tx_map_ops;
|
||||
while ((skb = __skb_dequeue(&tx_queue)) != NULL) {
|
||||
|
||||
@@ -78,6 +78,7 @@ tpmif_find(domid_t domid, long int instance)
|
||||
static int
|
||||
map_frontend_page(tpmif_t *tpmif, unsigned long shared_page)
|
||||
{
|
||||
int ret;
|
||||
struct gnttab_map_grant_ref op = {
|
||||
.host_addr = (unsigned long)tpmif->tx_area->addr,
|
||||
.flags = GNTMAP_host_map,
|
||||
@@ -86,8 +87,9 @@ map_frontend_page(tpmif_t *tpmif, unsigned long shared_page)
|
||||
};
|
||||
|
||||
lock_vm_area(tpmif->tx_area);
|
||||
BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1));
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1);
|
||||
unlock_vm_area(tpmif->tx_area);
|
||||
BUG_ON(ret);
|
||||
|
||||
if (op.handle < 0) {
|
||||
DPRINTK(" Grant table operation failure !\n");
|
||||
@@ -104,14 +106,16 @@ static void
|
||||
unmap_frontend_page(tpmif_t *tpmif)
|
||||
{
|
||||
struct gnttab_unmap_grant_ref op;
|
||||
int ret;
|
||||
|
||||
op.host_addr = (unsigned long)tpmif->tx_area->addr;
|
||||
op.handle = tpmif->shmem_handle;
|
||||
op.dev_bus_addr = 0;
|
||||
|
||||
lock_vm_area(tpmif->tx_area);
|
||||
BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
|
||||
ret = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1);
|
||||
unlock_vm_area(tpmif->tx_area);
|
||||
BUG_ON(ret);
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -34,7 +34,9 @@ struct vm_struct *alloc_vm_area(unsigned long size)
|
||||
|
||||
void free_vm_area(struct vm_struct *area)
|
||||
{
|
||||
BUG_ON(remove_vm_area(area->addr) != area);
|
||||
struct vm_struct *ret;
|
||||
ret = remove_vm_area(area->addr);
|
||||
BUG_ON(ret != area);
|
||||
kfree(area);
|
||||
}
|
||||
|
||||
|
||||
@@ -738,6 +738,7 @@ static int __init xenbus_probe_init(void)
|
||||
|
||||
unsigned long page;
|
||||
evtchn_op_t op = { 0 };
|
||||
int ret;
|
||||
|
||||
|
||||
/* Allocate page. */
|
||||
@@ -758,7 +759,8 @@ static int __init xenbus_probe_init(void)
|
||||
op.u.alloc_unbound.dom = DOMID_SELF;
|
||||
op.u.alloc_unbound.remote_dom = 0;
|
||||
|
||||
BUG_ON(HYPERVISOR_event_channel_op(&op));
|
||||
ret = HYPERVISOR_event_channel_op(&op);
|
||||
BUG_ON(ret);
|
||||
xen_start_info->store_evtchn = op.u.alloc_unbound.port;
|
||||
|
||||
/* And finally publish the above info in /proc/xen */
|
||||
|
||||
@@ -82,7 +82,7 @@ static struct xs_handle xs_state;
|
||||
static LIST_HEAD(watches);
|
||||
static DEFINE_SPINLOCK(watches_lock);
|
||||
|
||||
/* List of pending watch calbback events, and a lock to protect it. */
|
||||
/* List of pending watch callback events, and a lock to protect it. */
|
||||
static LIST_HEAD(watch_events);
|
||||
static DEFINE_SPINLOCK(watch_events_lock);
|
||||
|
||||
@@ -544,11 +544,8 @@ void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...)
|
||||
char *printf_buffer = NULL, *path_buffer = NULL;
|
||||
|
||||
printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL);
|
||||
if (printf_buffer == NULL) {
|
||||
printk("xenbus: failed to write error node for %s (%d): %d\n",
|
||||
dev->nodename, err, errno);
|
||||
if (printf_buffer == NULL)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
len = sprintf(printf_buffer, "%i ", -err);
|
||||
va_start(ap, fmt);
|
||||
@@ -561,8 +558,8 @@ void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...)
|
||||
path_buffer = error_path(dev);
|
||||
|
||||
if (path_buffer == NULL) {
|
||||
printk("xenbus: failed to write error node for %s (%s): %d\n",
|
||||
dev->nodename, printf_buffer, errno);
|
||||
printk("xenbus: failed to write error node for %s (%s)\n",
|
||||
dev->nodename, printf_buffer);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -587,8 +584,8 @@ void xenbus_dev_ok(struct xenbus_device *dev)
|
||||
char *path_buffer = error_path(dev);
|
||||
|
||||
if (path_buffer == NULL) {
|
||||
printk("xenbus: failed to clear error node for %s: "
|
||||
"%d\n", dev->nodename, errno);
|
||||
printk("xenbus: failed to clear error node for %s\n",
|
||||
dev->nodename);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,9 +16,6 @@ SUBDIRS += vtpm_manager
|
||||
SUBDIRS += vtpm
|
||||
endif
|
||||
SUBDIRS += xenstat
|
||||
|
||||
.PHONY: all install clean check check_clean ioemu eioemuinstall ioemuclean
|
||||
|
||||
# These don't cross-compile
|
||||
ifeq ($(XEN_COMPILE_ARCH),$(XEN_TARGET_ARCH))
|
||||
SUBDIRS += python
|
||||
|
||||
@@ -512,7 +512,9 @@ static void handle_xs(int fd)
|
||||
enum_domains();
|
||||
else if (sscanf(vec[XS_WATCH_TOKEN], "dom%u", &domid) == 1) {
|
||||
dom = lookup_domain(domid);
|
||||
if (dom->is_dead == false)
|
||||
/* We may get watches firing for domains that have recently
|
||||
been removed, so dom may be NULL here. */
|
||||
if (dom && dom->is_dead == false)
|
||||
domain_create_ring(dom);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ INSTALL_DATA = $(INSTALL) -m0644
|
||||
# Init scripts.
|
||||
XEND_INITD = init.d/xend
|
||||
XENDOMAINS_INITD = init.d/xendomains
|
||||
XENDOMAINS_SYSCONFIG = init.d/sysconfig.xendomains
|
||||
|
||||
# Xen configuration dir and configs to go there.
|
||||
XEN_CONFIG_DIR = /etc/xen
|
||||
@@ -24,8 +25,9 @@ XEN_SCRIPTS = network-bridge vif-bridge
|
||||
XEN_SCRIPTS += network-route vif-route
|
||||
XEN_SCRIPTS += network-nat vif-nat
|
||||
XEN_SCRIPTS += block
|
||||
XEN_SCRIPTS += block-enbd
|
||||
XEN_SCRIPTS += block-enbd block-nbd
|
||||
XEN_SCRIPTS += xen-hotplug-common.sh xen-network-common.sh vif-common.sh
|
||||
XEN_SCRIPTS += block-common.sh
|
||||
|
||||
XEN_HOTPLUG_DIR = /etc/hotplug
|
||||
XEN_HOTPLUG_SCRIPTS = xen-backend.agent
|
||||
@@ -52,8 +54,10 @@ install: all install-initd install-configs install-scripts $(HOTPLUGS)
|
||||
|
||||
install-initd:
|
||||
[ -d $(DESTDIR)/etc/init.d ] || $(INSTALL_DIR) $(DESTDIR)/etc/init.d
|
||||
[ -d $(DESTDIR)/etc/sysconfig ] || $(INSTALL_DIR) $(DESTDIR)/etc/sysconfig
|
||||
$(INSTALL_PROG) $(XEND_INITD) $(DESTDIR)/etc/init.d
|
||||
$(INSTALL_PROG) $(XENDOMAINS_INITD) $(DESTDIR)/etc/init.d
|
||||
$(INSTALL_PROG) $(XENDOMAINS_SYSCONFIG) $(DESTDIR)/etc/sysconfig/xendomains
|
||||
|
||||
install-configs: $(XEN_CONFIGS)
|
||||
[ -d $(DESTDIR)$(XEN_CONFIG_DIR) ] || \
|
||||
|
||||
+2
-14
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
dir=$(dirname "$0")
|
||||
. "$dir/xen-hotplug-common.sh"
|
||||
. "$dir/block-common.sh"
|
||||
|
||||
expand_dev() {
|
||||
local dev
|
||||
@@ -16,21 +16,9 @@ expand_dev() {
|
||||
echo -n $dev
|
||||
}
|
||||
|
||||
write_dev() {
|
||||
local major
|
||||
local minor
|
||||
local pdev
|
||||
|
||||
major=$(stat -L -c %t "$1")
|
||||
minor=$(stat -L -c %T "$1")
|
||||
pdev=$(printf "0x%02x%02x" 0x$major 0x$minor)
|
||||
xenstore_write "$XENBUS_PATH"/physical-device $pdev \
|
||||
"$XENBUS_PATH"/node $1
|
||||
}
|
||||
|
||||
t=$(xenstore_read "$XENBUS_PATH"/type || true)
|
||||
|
||||
case $1 in
|
||||
case "$command" in
|
||||
bind)
|
||||
p=$(xenstore_read "$XENBUS_PATH"/params)
|
||||
case $t in
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
#
|
||||
# Copyright (c) 2005 XenSource Ltd.
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
|
||||
dir=$(dirname "$0")
|
||||
. "$dir/xen-hotplug-common.sh"
|
||||
|
||||
command="$1"
|
||||
|
||||
if [ "$command" != "bind" ] && [ "$command" != "unbind" ]
|
||||
then
|
||||
log err "Invalid command: $command"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
XENBUS_PATH="${XENBUS_PATH:?}"
|
||||
|
||||
|
||||
##
|
||||
# Write physical-device = 0xMMmm and node = device to the store, where MM
|
||||
# and mm are the major and minor numbers of device.
|
||||
#
|
||||
# @param device The device from which major and minor numbers are read, which
|
||||
# will be written into the store.
|
||||
#
|
||||
write_dev() {
|
||||
local major
|
||||
local minor
|
||||
local pdev
|
||||
|
||||
major=$(stat -L -c %t "$1")
|
||||
minor=$(stat -L -c %T "$1")
|
||||
pdev=$(printf "0x%02x%02x" "0x$major" "0x$minor")
|
||||
xenstore_write "$XENBUS_PATH"/physical-device "$pdev" \
|
||||
"$XENBUS_PATH"/node "$1"
|
||||
}
|
||||
@@ -2,25 +2,19 @@
|
||||
|
||||
# Usage: block-enbd [bind server ctl_port |unbind node]
|
||||
#
|
||||
# The file argument to the bind command is the file we are to bind to a
|
||||
# loop device.
|
||||
#
|
||||
# The node argument to unbind is the name of the device node we are to
|
||||
# unbind.
|
||||
#
|
||||
# This assumes you're running a correctly configured server at the other end!
|
||||
|
||||
set -e
|
||||
dir=$(dirname "$0")
|
||||
. "$dir/block-common.sh"
|
||||
|
||||
case $1 in
|
||||
case "$command" in
|
||||
bind)
|
||||
for dev in /dev/nd*; do
|
||||
if nbd-client $2:$3 $dev; then
|
||||
major=$(stat -L -c %t "$dev")
|
||||
minor=$(stat -L -c %T "$dev")
|
||||
pdev=$(printf "0x%02x%02x" 0x$major 0x$minor)
|
||||
xenstore-write "$XENBUS_PATH"/physical-device $pdev \
|
||||
"$XENBUS_PATH"/node $dev
|
||||
write_dev $dev
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Usage: block-nbd [bind server ctl_port |unbind node]
|
||||
#
|
||||
# The node argument to unbind is the name of the device node we are to
|
||||
# unbind.
|
||||
#
|
||||
# This assumes you're running a correctly configured server at the other end!
|
||||
|
||||
dir=$(dirname "$0")
|
||||
. "$dir/block-common.sh"
|
||||
|
||||
case "$command" in
|
||||
bind)
|
||||
for dev in /dev/nbd*; do
|
||||
if nbd-client $2 $3 $dev; then
|
||||
write_dev $dev
|
||||
exit 0
|
||||
fi
|
||||
done
|
||||
exit 1
|
||||
;;
|
||||
unbind)
|
||||
nbd-client -d $2
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,126 @@
|
||||
## Path: System/xen
|
||||
## Description: xen domain start/stop on boot
|
||||
## Type: string
|
||||
## Default:
|
||||
#
|
||||
# The xendomains script can send SysRq requests to domains on shutdown.
|
||||
# If you don't want to MIGRATE, SAVE, or SHUTDOWN, this may be a possibility
|
||||
# to do a quick and dirty shutdown ("s e i u o") or at least sync the disks
|
||||
# of the domains ("s").
|
||||
#
|
||||
XENDOMAINS_SYSRQ=""
|
||||
|
||||
## Type: integer
|
||||
## Default: 100000
|
||||
#
|
||||
# If XENDOMAINS_SYSRQ is set, this variable determines how long to wait
|
||||
# (in microseconds) after each SysRq, so the domain has a chance to react.
|
||||
# If you want to a quick'n'dirty shutdown via SysRq, you may want to set
|
||||
# it to a relatively high value (1200000).
|
||||
#
|
||||
XENDOMAINS_USLEEP=100000
|
||||
|
||||
## Type: string
|
||||
## Default: ""
|
||||
#
|
||||
# Set this to a non-empty string if you want to migrate virtual machines
|
||||
# on shutdown. The string will be passed to the xm migrate DOMID command
|
||||
# as is: It should contain the target IP address of the physical machine
|
||||
# to migrate to and optionally parameters like --live. Leave empty if
|
||||
# you don't want to try virtual machine relocation on shutdown.
|
||||
# If migration succeeds, neither SAVE nor SHUTDOWN will be executed for
|
||||
# that domain.
|
||||
#
|
||||
XENDOMAINS_MIGRATE=""
|
||||
|
||||
## Type: string
|
||||
## Default: /var/lib/xen/save
|
||||
#
|
||||
# Directory to save running domains to when the system (dom0) is
|
||||
# shut down. Will also be used to restore domains from if # XENDOMAINS_RESTORE
|
||||
# is set (see below). Leave empty to disable domain saving on shutdown
|
||||
# (e.g. because you rather shut domains down).
|
||||
# If domain saving does succeed, SHUTDOWN will not be executed.
|
||||
#
|
||||
XENDOMAINS_SAVE=/var/lib/xen/save
|
||||
|
||||
## Type: string
|
||||
## Default: "--halt --wait"
|
||||
#
|
||||
# If neither MIGRATE nor SAVE were enabled or if they failed, you can
|
||||
# try to shut down a domain by sending it a shutdown request. To do this,
|
||||
# set this to "--halt --wait". Omit the "--wait" flag to avoid waiting
|
||||
# for the domain to be really down. Leave empty to skip domain shutdown.
|
||||
#
|
||||
XENDOMAINS_SHUTDOWN="--halt --wait"
|
||||
|
||||
## Type: string
|
||||
## Default: "--all --halt --wait"
|
||||
#
|
||||
# After we have gone over all virtual machines (resp. all automatically
|
||||
# started ones, see XENDOMAINS_AUTO_ONLY below) in a loop and sent SysRq,
|
||||
# migrated, saved and/or shutdown according to the settings above, we
|
||||
# might want to shutdown the virtual machines that are still running
|
||||
# for some reason or another. To do this, set this variable to
|
||||
# "--all --halt --wait", it will be passed to xm shutdown.
|
||||
# Leave it empty not to do anything special here.
|
||||
# (Note: This will hit all virtual machines, even if XENDOMAINS_AUTO_ONLY
|
||||
# is set.)
|
||||
#
|
||||
XENDOMAINS_SHUTDOWN_ALL="--all --halt --wait"
|
||||
|
||||
## Type: boolean
|
||||
## Default: true
|
||||
#
|
||||
# This variable determines whether saved domains from XENDOMAINS_SAVE
|
||||
# will be restored on system startup.
|
||||
#
|
||||
XENDOMAINS_RESTORE=true
|
||||
|
||||
## Type: string
|
||||
## Default: /etc/xen/auto
|
||||
#
|
||||
# This variable sets the directory where domains configurations
|
||||
# are stored that should be started on system startup automatically.
|
||||
# Leave empty if you don't want to start domains automatically
|
||||
# (or just don't place any xen domain config files in that dir).
|
||||
# Note that the script tries to be clever if both RESTORE and AUTO are
|
||||
# set: It will first restore saved domains and then only start domains
|
||||
# in AUTO which are not running yet.
|
||||
# Note that the name matching is somewhat fuzzy.
|
||||
#
|
||||
XENDOMAINS_AUTO=/etc/xen/auto
|
||||
|
||||
## Type: boolean
|
||||
## Default: false
|
||||
#
|
||||
# If this variable is set to "true", only the domains started via config
|
||||
# files in XENDOMAINS_AUTO will be treated according to XENDOMAINS_SYSRQ,
|
||||
# XENDOMAINS_MIGRATE, XENDOMAINS_SAVE, XENDMAINS_SHUTDOWN; otherwise
|
||||
# all running domains will be.
|
||||
# Note that the name matching is somewhat fuzzy.
|
||||
#
|
||||
XENDOMAINS_AUTO_ONLY=false
|
||||
|
||||
## Type: integer
|
||||
## Default: 300
|
||||
#
|
||||
# On xendomains stop, a number of xm commands (xm migrate, save, shutdown,
|
||||
# shutdown --all) may be executed. In the worst case, these commands may
|
||||
# stall forever, which will prevent a successful shutdown of the machine.
|
||||
# If this variable is non-zero, the script will set up a watchdog timer
|
||||
# for every of these xm commands and time it out after the number of seconds
|
||||
# specified by this variable.
|
||||
# Note that SHUTDOWN_ALL will not be called if no virtual machines or only
|
||||
# zombies are still running, so you don't need to enable this timeout just
|
||||
# for the zombie case.
|
||||
# The setting should be large enough to make sure that migrate/save/shutdown
|
||||
# can succeed. If you do live migrations, keep in mind that live migration
|
||||
# of a 1GB machine over Gigabit ethernet may actually take something like
|
||||
# 100s (assuming that live migration uses 10% of the network # bandwidth).
|
||||
# Depending on the virtual machine, a shutdown may also require a significant
|
||||
# amount of time. So better setup this variable to a huge number and hope the
|
||||
# watchdog never fires.
|
||||
#
|
||||
XENDOMAINS_STOP_MAXWAIT=300
|
||||
|
||||
Executable → Regular
+406
-80
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
#
|
||||
# /etc/init.d/xendomains
|
||||
# Start / stop domains automatically when domain 0 boots / shuts down.
|
||||
@@ -22,101 +22,418 @@
|
||||
# Should-Stop:
|
||||
# Default-Start: 3 4 5
|
||||
# Default-Stop: 0 1 2 6
|
||||
# Default-Enabled: yes
|
||||
# Short-Description: Start/stop secondary xen domains
|
||||
# Description: Start / stop domains automatically when domain 0
|
||||
# boots / shuts down.
|
||||
### END INIT INFO
|
||||
|
||||
# Correct exit code would probably be 5, but it's enough
|
||||
# if xend complains if we're not running as privileged domain
|
||||
if ! [ -e /proc/xen/privcmd ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
RETVAL=0
|
||||
|
||||
INITD=/etc/init.d
|
||||
|
||||
AUTODIR=/etc/xen/auto
|
||||
LOCKFILE=/var/lock/subsys/xendomains
|
||||
XENDOM_CONFIG=/etc/sysconfig/xendomains
|
||||
|
||||
if [ -e /lib/lsb ]; then
|
||||
# assume an LSB-compliant distro (Debian with LSB package,
|
||||
# recent-enough SuSE, others...)
|
||||
test -r $XENDOM_CONFIG || { echo "$XENDOM_CONFIG not existing";
|
||||
if [ "$1" = "stop" ]; then exit 0;
|
||||
else exit 6; fi; }
|
||||
|
||||
. /lib/lsb/init-functions # source LSB standard functions
|
||||
. $XENDOM_CONFIG
|
||||
|
||||
on_fn_exit()
|
||||
# Use the SUSE rc_ init script functions;
|
||||
# emulate them on LSB, RH and other systems
|
||||
if test -e /etc/rc.status; then
|
||||
# SUSE rc script library
|
||||
. /etc/rc.status
|
||||
else
|
||||
_cmd=$1
|
||||
declare -a _SMSG
|
||||
if test "${_cmd}" = "status"; then
|
||||
_SMSG=(running dead dead unused unknown)
|
||||
_RC_UNUSED=3
|
||||
else
|
||||
_SMSG=(done failed failed missed failed skipped unused failed failed)
|
||||
_RC_UNUSED=6
|
||||
fi
|
||||
if test -e /lib/lsb/init-functions; then
|
||||
# LSB
|
||||
. /lib/lsb/init-functions
|
||||
echo_rc()
|
||||
{
|
||||
if test ${_RC_RV} = 0; then
|
||||
log_success_msg " [${_SMSG[${_RC_RV}]}] "
|
||||
else
|
||||
log_failure_msg " [${_SMSG[${_RC_RV}]}] "
|
||||
fi
|
||||
}
|
||||
elif test -e /etc/init.d/functions; then
|
||||
# REDHAT
|
||||
. /etc/init.d/functions
|
||||
echo_rc()
|
||||
{
|
||||
#echo -n " [${_SMSG[${_RC_RV}]}] "
|
||||
if test ${_RC_RV} = 0; then
|
||||
success " [${_SMSG[${_RC_RV}]}] "
|
||||
else
|
||||
failure " [${_SMSG[${_RC_RV}]}] "
|
||||
fi
|
||||
}
|
||||
else
|
||||
# emulate it
|
||||
echo_rc()
|
||||
{
|
||||
echo " [${_SMSG[${_RC_RV}]}] "
|
||||
}
|
||||
fi
|
||||
rc_reset() { _RC_RV=0; }
|
||||
rc_failed()
|
||||
{
|
||||
if [ $RETVAL -eq 0 ]; then
|
||||
log_success_msg
|
||||
else
|
||||
log_failure_msg
|
||||
fi
|
||||
if test -z "$1"; then
|
||||
_RC_RV=1;
|
||||
elif test "$1" != "0"; then
|
||||
_RC_RV=$1;
|
||||
fi
|
||||
return ${_RC_RV}
|
||||
}
|
||||
elif [ -r $INITD/functions ]; then
|
||||
# assume a Redhat-like distro
|
||||
. $INITD/functions # source Redhat functions
|
||||
|
||||
on_fn_exit()
|
||||
rc_check()
|
||||
{
|
||||
if [ $RETVAL -eq 0 ]; then
|
||||
success
|
||||
else
|
||||
failure
|
||||
fi
|
||||
|
||||
echo
|
||||
return rc_failed $?
|
||||
}
|
||||
rc_status()
|
||||
{
|
||||
rc_failed $?
|
||||
if test "$1" = "-r"; then _RC_RV=0; shift; fi
|
||||
if test "$1" = "-s"; then rc_failed 5; echo_rc; rc_failed 3; shift; fi
|
||||
if test "$1" = "-u"; then rc_failed ${_RC_UNUSED}; echo_rc; rc_failed 3; shift; fi
|
||||
if test "$1" = "-v"; then echo_rc; shift; fi
|
||||
if test "$1" = "-r"; then _RC_RV=0; shift; fi
|
||||
return ${_RC_RV}
|
||||
}
|
||||
else
|
||||
# none of the above
|
||||
LOCKFILE=/var/lock/xendomains
|
||||
|
||||
on_fn_exit()
|
||||
rc_exit() { exit ${_RC_RV}; }
|
||||
rc_active()
|
||||
{
|
||||
echo
|
||||
if test -z "$RUNLEVEL"; then read RUNLEVEL REST < <(/sbin/runlevel); fi
|
||||
if test -e /etc/init.d/S[0-9][0-9]${1}; then return 0; fi
|
||||
return 1
|
||||
}
|
||||
fi
|
||||
|
||||
if ! which usleep >&/dev/null
|
||||
then
|
||||
usleep()
|
||||
{
|
||||
if [ -n "$1" ]
|
||||
then
|
||||
sleep $(( $1 / 1000 ))
|
||||
fi
|
||||
}
|
||||
fi
|
||||
|
||||
# Reset status of this service
|
||||
rc_reset
|
||||
|
||||
start() {
|
||||
if [ -f $LOCKFILE ]; then return; fi
|
||||
##
|
||||
# Returns 0 (success) if the given parameter names a directory, and that
|
||||
# directory is not empty.
|
||||
#
|
||||
contains_something()
|
||||
{
|
||||
if [ -d "$1" ] && [ `/bin/ls $1 | wc -l` -gt 0 ]
|
||||
then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
echo -n $"Starting auto Xen domains:"
|
||||
# read name from xen config file
|
||||
rdname()
|
||||
{
|
||||
NM=`grep '^name *=' $1 | sed -e 's/^name *= *"\([^"]*\)".*$/\1/' -e 's/%[id]/[0-9]*/g'`
|
||||
}
|
||||
|
||||
# We expect config scripts for auto starting domains to be in
|
||||
# AUTODIR - they could just be symlinks to files elsewhere
|
||||
if [ -d $AUTODIR ] && [ $(ls $AUTODIR | wc -l) -gt 0 ]; then
|
||||
touch $LOCKFILE
|
||||
|
||||
# Create all domains with config files in AUTODIR.
|
||||
for dom in $AUTODIR/*; do
|
||||
xm create --quiet --defconfig $dom
|
||||
if [ $? -ne 0 ]; then
|
||||
RETVAL=$?
|
||||
fi
|
||||
done
|
||||
rdnames()
|
||||
{
|
||||
NAMES=
|
||||
if ! contains_something "$XENDOMAINS_AUTO"
|
||||
then
|
||||
return
|
||||
fi
|
||||
for dom in $XENDOMAINS_AUTO/*; do
|
||||
rdname $dom
|
||||
if test -z $NAMES; then
|
||||
NAMES=$NM;
|
||||
else
|
||||
NAMES="$NAMES|$NM"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
parseln()
|
||||
{
|
||||
name=`echo "$1" | cut -c0-17`
|
||||
name=${name%% *}
|
||||
rest=`echo "$1" | cut -c18- `
|
||||
read id mem cpu vcpu state tm < <(echo "$rest")
|
||||
}
|
||||
|
||||
is_running()
|
||||
{
|
||||
rdname $1
|
||||
RC=1
|
||||
while read LN; do
|
||||
parseln "$LN"
|
||||
if test $id = 0; then continue; fi
|
||||
case $name in
|
||||
($NM)
|
||||
RC=0
|
||||
;;
|
||||
esac
|
||||
done < <(xm list | grep -v '^Name')
|
||||
return $RC
|
||||
}
|
||||
|
||||
start()
|
||||
{
|
||||
if [ -f $LOCKFILE ]; then
|
||||
echo -n "xendomains already running (lockfile exists)"
|
||||
return;
|
||||
fi
|
||||
|
||||
on_fn_exit
|
||||
if [ "$XENDOMAINS_RESTORE" = "true" ] &&
|
||||
contains_something "$XENDOMAINS_SAVE"
|
||||
then
|
||||
mkdir -p $(dirname "$LOCKFILE")
|
||||
touch $LOCKFILE
|
||||
echo -n "Restoring Xen domains:"
|
||||
for dom in $XENDOMAINS_SAVE/*; do
|
||||
echo -n " ${dom##*/}"
|
||||
xm restore $dom
|
||||
if [ $? -ne 0 ]; then
|
||||
rc_failed $?
|
||||
echo -n '!'
|
||||
else
|
||||
# mv $dom ${dom%/*}/.${dom##*/}
|
||||
rm $dom
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if contains_something "$XENDOMAINS_AUTO"
|
||||
then
|
||||
touch $LOCKFILE
|
||||
echo -n "Starting auto Xen domains:"
|
||||
# We expect config scripts for auto starting domains to be in
|
||||
# XENDOMAINS_AUTO - they could just be symlinks to files elsewhere
|
||||
|
||||
# Create all domains with config files in XENDOMAINS_AUTO.
|
||||
# TODO: We should record which domain name belongs
|
||||
# so we have the option to selectively shut down / migrate later
|
||||
for dom in $XENDOMAINS_AUTO/*; do
|
||||
echo -n " ${dom##*/}"
|
||||
if is_running $dom; then
|
||||
echo -n "(skip)"
|
||||
else
|
||||
xm create --quiet --defconfig $dom
|
||||
if [ $? -ne 0 ]; then
|
||||
rc_failed $?
|
||||
echo -n '!'
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
all_zombies()
|
||||
{
|
||||
while read LN; do
|
||||
parseln "$LN"
|
||||
if test $id = 0; then continue; fi
|
||||
if test "$state" != "-b---d" -a "$state" != "-----d"; then
|
||||
return 1;
|
||||
fi
|
||||
done < <(xm list | grep -v '^Name')
|
||||
return 0
|
||||
}
|
||||
|
||||
# Wait for max $XENDOMAINS_STOP_MAXWAIT for xm $1 to finish;
|
||||
# if it has not exited by that time kill it, so the init script will
|
||||
# succeed within a finite amount of time; if $2 is nonnull, it will
|
||||
# kill the command as well as soon as no domain (except for zombies)
|
||||
# are left (used for shutdown --all).
|
||||
watchdog_xm()
|
||||
{
|
||||
if test -z "$XENDOMAINS_STOP_MAXWAIT" -o "$XENDOMAINS_STOP_MAXWAIT" = "0"; then
|
||||
exit
|
||||
fi
|
||||
usleep 20000
|
||||
for no in `seq 0 $XENDOMAINS_STOP_MAXWAIT`; do
|
||||
# exit if xm save/migrate/shutdown is finished
|
||||
PSAX=`ps axlw | grep "xm $1" | grep -v grep`
|
||||
if test -z "$PSAX"; then exit; fi
|
||||
echo -n "."; sleep 1
|
||||
# go to kill immediately if there's only zombies left
|
||||
if all_zombies && test -n "$2"; then break; fi
|
||||
done
|
||||
sleep 1
|
||||
read PSF PSUID PSPID PSPPID < <(echo "$PSAX")
|
||||
# kill xm $1
|
||||
kill $PSPID >/dev/null 2>&1
|
||||
}
|
||||
|
||||
stop()
|
||||
{
|
||||
# Collect list of domains to shut down
|
||||
if test "$XENDOMAINS_AUTO_ONLY" = "true"; then
|
||||
rdnames
|
||||
fi
|
||||
echo -n "Shutting down Xen domains:"
|
||||
while read LN; do
|
||||
parseln "$LN"
|
||||
if test $id = 0; then continue; fi
|
||||
echo -n " $name"
|
||||
if test "$XENDOMAINS_AUTO_ONLY" = "true"; then
|
||||
case $name in
|
||||
($NAMES)
|
||||
# nothing
|
||||
;;
|
||||
(*)
|
||||
echo -n "(skip)"
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
# XENDOMAINS_SYSRQ chould be something like just "s"
|
||||
# or "s e i u" or even "s e s i u o"
|
||||
# for the latter, you should set XENDOMAINS_USLEEP to 1200000 or so
|
||||
if test -n "$XENDOMAINS_SYSRQ"; then
|
||||
for sysrq in $XENDOMAINS_SYSRQ; do
|
||||
echo -n "(SR-$sysrq)"
|
||||
xm sysrq $id $sysrq
|
||||
if test $? -ne 0; then
|
||||
rc_failed $?
|
||||
echo -n '!'
|
||||
fi
|
||||
# usleep just ignores empty arg
|
||||
usleep $XENDOMAINS_USLEEP
|
||||
done
|
||||
fi
|
||||
if test "$state" = "-b---d" -o "$state" = "-----d"; then
|
||||
echo -n "(zomb)"
|
||||
continue
|
||||
fi
|
||||
if test -n "$XENDOMAINS_MIGRATE"; then
|
||||
echo -n "(migr)"
|
||||
watchdog_xm migrate &
|
||||
WDOG_PID=$!
|
||||
xm migrate $id $XENDOMAINS_MIGRATE
|
||||
if test $? -ne 0; then
|
||||
rc_failed $?
|
||||
echo -n '!'
|
||||
kill $WDOG_PID >/dev/null 2>&1
|
||||
else
|
||||
kill $WDOG_PID >/dev/null 2>&1
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
if test -n "$XENDOMAINS_SAVE"; then
|
||||
echo -n "(save)"
|
||||
watchdog_xm save &
|
||||
WDOG_PID=$!
|
||||
xm save $id $XENDOMAINS_SAVE/$name
|
||||
if test $? -ne 0; then
|
||||
rc_failed $?
|
||||
echo -n '!'
|
||||
kill $WDOG_PIG >/dev/null 2>&1
|
||||
else
|
||||
kill $WDOG_PIG >/dev/null 2>&1
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
if test -n "$XENDOMAINS_SHUTDOWN"; then
|
||||
# XENDOMAINS_SHUTDOWN should be "--halt --wait"
|
||||
echo -n "(shut)"
|
||||
watchdog_xm shutdown &
|
||||
WDOG_PID=$!
|
||||
xm shutdown $id $XENDOMAINS_SHUTDOWN
|
||||
if test $? -ne 0; then
|
||||
rc_failed $?
|
||||
echo -n '!'
|
||||
fi
|
||||
kill $WDOG_PIG >/dev/null 2>&1
|
||||
fi
|
||||
done < <(xm list | grep -v '^Name')
|
||||
|
||||
# NB. this shuts down ALL Xen domains (politely), not just the ones in
|
||||
# AUTODIR/*
|
||||
# This is because it's easier to do ;-) but arguably if this script is run
|
||||
# on system shutdown then it's also the right thing to do.
|
||||
|
||||
echo -n $"Shutting down all Xen domains:"
|
||||
if ! all_zombies && test -n "$XENDOMAINS_SHUTDOWN_ALL"; then
|
||||
# XENDOMAINS_SHUTDOWN_ALL should be "--all --halt --wait"
|
||||
echo -n " SHUTDOWN_ALL "
|
||||
watchdog_xm shutdown 1 &
|
||||
WDOG_PID=$!
|
||||
xm shutdown $XENDOMAINS_SHUTDOWN_ALL
|
||||
if test $? -ne 0; then
|
||||
rc_failed $?
|
||||
echo -n '!'
|
||||
fi
|
||||
kill $WDOG_PID >/dev/null 2>&1
|
||||
fi
|
||||
|
||||
xm shutdown --all --wait --halt
|
||||
# Unconditionally delete lock file
|
||||
rm -f $LOCKFILE
|
||||
}
|
||||
|
||||
RETVAL=$?
|
||||
check_domain_up()
|
||||
{
|
||||
while read LN; do
|
||||
parseln "$LN"
|
||||
if test $id = 0; then continue; fi
|
||||
case $name in
|
||||
($1)
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
done < <(xm list | grep -v "^Name")
|
||||
return 1
|
||||
}
|
||||
|
||||
[ $RETVAL -eq 0 ] && rm -f $LOCKFILE
|
||||
check_all_auto_domains_up()
|
||||
{
|
||||
if ! contains_something "$XENDOMAINS_AUTO"
|
||||
then
|
||||
return 0
|
||||
fi
|
||||
missing=
|
||||
for nm in $XENDOMAINS_AUTO/*; do
|
||||
rdname $nm
|
||||
found=0
|
||||
if check_domain_up "$NM"; then
|
||||
echo -n " $name"
|
||||
else
|
||||
missing="$missing $NM"
|
||||
fi
|
||||
done
|
||||
if test -n "$missing"; then
|
||||
echo -n " MISS AUTO:$missing"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
on_fn_exit
|
||||
check_all_saved_domains_up()
|
||||
{
|
||||
if ! contains_something "$XENDOMAINS_SAVE"
|
||||
then
|
||||
return 0
|
||||
fi
|
||||
missing=`/bin/ls $XENDOMAINS_SAVE`
|
||||
echo -n " MISS SAVED: " $missing
|
||||
return 1
|
||||
}
|
||||
|
||||
# This does NOT necessarily restart all running domains: instead it
|
||||
@@ -124,47 +441,56 @@ stop()
|
||||
# AUTODIR. If other domains have been started manually then they will
|
||||
# not get restarted.
|
||||
# Commented out to avoid confusion!
|
||||
#
|
||||
#restart()
|
||||
#{
|
||||
# stop
|
||||
# start
|
||||
#}
|
||||
|
||||
# same as restart for now - commented out to avoid confusion
|
||||
#reload()
|
||||
#{
|
||||
# restart
|
||||
#}
|
||||
restart()
|
||||
{
|
||||
stop
|
||||
start
|
||||
}
|
||||
|
||||
reload()
|
||||
{
|
||||
restart
|
||||
}
|
||||
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
rc_status
|
||||
if test -f $LOCKFILE; then rc_status -v; fi
|
||||
;;
|
||||
|
||||
stop)
|
||||
stop
|
||||
rc_status -v
|
||||
;;
|
||||
|
||||
# The following are commented out to disable them by default to avoid confusion
|
||||
# - see the notes above
|
||||
#
|
||||
# restart)
|
||||
# restart
|
||||
# ;;
|
||||
#
|
||||
# reload)
|
||||
# reload
|
||||
# ;;
|
||||
restart)
|
||||
restart
|
||||
;;
|
||||
reload)
|
||||
reload
|
||||
;;
|
||||
|
||||
status)
|
||||
xm list
|
||||
echo -n "Checking for xendomains:"
|
||||
if test ! -f $LOCKFILE; then
|
||||
rc_failed 3
|
||||
else
|
||||
check_all_auto_domains_up
|
||||
rc_status
|
||||
check_all_saved_domains_up
|
||||
rc_status
|
||||
fi
|
||||
rc_status -v
|
||||
;;
|
||||
|
||||
*)
|
||||
echo $"Usage: $0 {start|stop|status}"
|
||||
echo "Usage: $0 {start|stop|restart|reload|status}"
|
||||
rc_failed 3
|
||||
rc_status -v
|
||||
;;
|
||||
esac
|
||||
|
||||
exit $RETVAL
|
||||
rc_exit
|
||||
@@ -208,7 +208,7 @@ op_start () {
|
||||
|
||||
if ip link show ${vdev} 2>/dev/null >/dev/null; then
|
||||
mac=`ip link show ${netdev} | grep 'link\/ether' | sed -e 's/.*ether \(..:..:..:..:..:..\).*/\1/'`
|
||||
eval `/sbin/getcfg -d /etc/sysconfig/network/ -f ifcfg- -- ${netdev}`
|
||||
preiftransfer ${netdev}
|
||||
transfer_addrs ${netdev} ${vdev}
|
||||
if ! ifdown ${netdev}; then
|
||||
# if ifup didn't work, see if we have an ip= on cmd line
|
||||
@@ -231,7 +231,7 @@ op_start () {
|
||||
ip link set ${bridge} up
|
||||
ip link set ${vif0} up
|
||||
ip link set ${pdev} up
|
||||
if ! ifup ${HWD_CONFIG_0} ${netdev} ; then
|
||||
if ! ifup ${netdev} ; then
|
||||
if [ ${kip} ] ; then
|
||||
# use the addresses we grocked from /proc/cmdline
|
||||
if [ -z "${kmask}" ]; then
|
||||
|
||||
@@ -1,3 +1,21 @@
|
||||
#
|
||||
# Copyright (c) 2005 XenSource Ltd.
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2.1 of the GNU Lesser General Public
|
||||
# License as published by the Free Software Foundation.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
|
||||
|
||||
set -e
|
||||
|
||||
export PATH="/sbin:/bin:/usr/bin:/usr/sbin:$PATH"
|
||||
|
||||
@@ -16,11 +16,40 @@
|
||||
#
|
||||
|
||||
|
||||
# Gentoo doesn't have ifup/ifdown: define appropriate alternatives
|
||||
if ! which ifup >&/dev/null
|
||||
# On SuSE it is necessary to run a command before transfering addresses and
|
||||
# routes from the physical interface to the virtual. This command creates a
|
||||
# variable $HWD_CONFIG_0 that specifies the appropriate configuration for
|
||||
# ifup.
|
||||
|
||||
# Gentoo doesn't have ifup/ifdown, so we define appropriate alternatives.
|
||||
|
||||
# Other platforms just use ifup / ifdown directly.
|
||||
|
||||
##
|
||||
# preiftransfer
|
||||
#
|
||||
# @param $1 The current name for the physical device, which is also the name
|
||||
# that the virtual device will take once the physical device has
|
||||
# been renamed.
|
||||
|
||||
if [ -e /etc/SuSE-release ]
|
||||
then
|
||||
preiftransfer()
|
||||
{
|
||||
eval `/sbin/getcfg -d /etc/sysconfig/network/ -f ifcfg- -- $1`
|
||||
}
|
||||
ifup()
|
||||
{
|
||||
/sbin/ifup ${HWD_CONFIG_0} $1
|
||||
}
|
||||
elif ! which ifup >&/dev/null
|
||||
then
|
||||
if [ -e /etc/conf.d/net ]
|
||||
then
|
||||
preiftransfer()
|
||||
{
|
||||
true
|
||||
}
|
||||
ifup()
|
||||
{
|
||||
/etc/init.d/net.$1 start
|
||||
@@ -34,4 +63,9 @@ then
|
||||
"You don't have ifup and don't seem to be running Gentoo either!"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
preiftransfer()
|
||||
{
|
||||
true
|
||||
}
|
||||
fi
|
||||
@@ -0,0 +1,23 @@
|
||||
# -*- mode: python; -*-
|
||||
#
|
||||
# xm create configuration example.
|
||||
#
|
||||
# This configuration is appropriate for using Network Block Device (NBD)
|
||||
# filesystems.
|
||||
#
|
||||
# Each of these parameters will need changing to match your setup.
|
||||
#
|
||||
|
||||
kernel = "/boot/vmlinuz-2.6.13-15b-xen"
|
||||
ramdisk = "/boot/initrd-2.6.13-15b-xen"
|
||||
memory = 128
|
||||
name = "nbd4"
|
||||
nics=1
|
||||
# Please change MAC
|
||||
vif = [ 'mac=aa:cc:10:10:00:a0, bridge=xenbr0' ]
|
||||
# Please change PORT
|
||||
disk = [ 'nbd:134.100.233.115 20004,hda1,w' ]
|
||||
dhcp = "dhcp"
|
||||
hostname= "nbd4"
|
||||
root = "/dev/hda1 ro"
|
||||
extra = "3"
|
||||
@@ -22,6 +22,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#include "vl.h"
|
||||
#include <pthread.h>
|
||||
|
||||
/* debug IDE devices */
|
||||
//#define DEBUG_IDE
|
||||
@@ -360,6 +361,48 @@ typedef struct PCIIDEState {
|
||||
BMDMAState bmdma[2];
|
||||
} PCIIDEState;
|
||||
|
||||
#define DMA_MULTI_THREAD
|
||||
|
||||
#ifdef DMA_MULTI_THREAD
|
||||
|
||||
static int file_pipes[2];
|
||||
|
||||
static void ide_dma_loop(BMDMAState *bm);
|
||||
static void dma_thread_loop(BMDMAState *bm);
|
||||
|
||||
static void *dma_thread_func(void* opaque)
|
||||
{
|
||||
BMDMAState* req;
|
||||
|
||||
while (read(file_pipes[0], &req, sizeof(req))) {
|
||||
dma_thread_loop(req);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void dma_create_thread()
|
||||
{
|
||||
pthread_t tid;
|
||||
int rt;
|
||||
|
||||
if (pipe(file_pipes) != 0){
|
||||
fprintf(stderr, "create pipe failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ( (rt = pthread_create(&tid, NULL, dma_thread_func, NULL)) ) {
|
||||
fprintf(stderr, "Oops, dma thread creation failed, errno=%d\n", rt);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ( (rt = pthread_detach(tid)) ) {
|
||||
fprintf(stderr, "Oops, dma thread detachment failed, errno=%d\n", rt);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif //DMA_MULTI_THREAD
|
||||
|
||||
static void ide_dma_start(IDEState *s, IDEDMAFunc *dma_cb);
|
||||
|
||||
static void padstr(char *str, const char *src, int len)
|
||||
@@ -1978,7 +2021,15 @@ static void ide_map(PCIDevice *pci_dev, int region_num,
|
||||
|
||||
/* XXX: full callback usage to prepare non blocking I/Os support -
|
||||
error handling */
|
||||
#ifdef DMA_MULTI_THREAD
|
||||
static void ide_dma_loop(BMDMAState *bm)
|
||||
{
|
||||
write(file_pipes[1], &bm, sizeof(bm));
|
||||
}
|
||||
static void dma_thread_loop(BMDMAState *bm)
|
||||
#else
|
||||
static void ide_dma_loop(BMDMAState *bm)
|
||||
#endif //DMA_MULTI_THREAD
|
||||
{
|
||||
struct {
|
||||
uint32_t addr;
|
||||
@@ -2166,6 +2217,9 @@ void pci_ide_init(PCIBus *bus, BlockDriverState **hd_table)
|
||||
d->ide_if[i].pci_dev = (PCIDevice *)d;
|
||||
ide_init2(&d->ide_if[0], 16, hd_table[0], hd_table[1]);
|
||||
ide_init2(&d->ide_if[2], 16, hd_table[2], hd_table[3]);
|
||||
#ifdef DMA_MULTI_THREAD
|
||||
dma_create_thread();
|
||||
#endif //DMA_MULTI_THREAD
|
||||
}
|
||||
|
||||
/* hd_table must contain 4 block drivers */
|
||||
@@ -2196,6 +2250,9 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table)
|
||||
ide_init2(&d->ide_if[2], 15, hd_table[2], hd_table[3]);
|
||||
ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
|
||||
ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
|
||||
#ifdef DMA_MULTI_THREAD
|
||||
dma_create_thread();
|
||||
#endif //DMA_MULTI_THREAD
|
||||
}
|
||||
|
||||
/***********************************************************/
|
||||
|
||||
+11
-11
@@ -24,26 +24,26 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
typedef u_int8_t Elf_Byte;
|
||||
typedef uint8_t Elf_Byte;
|
||||
|
||||
typedef u_int32_t Elf32_Addr; /* Unsigned program address */
|
||||
typedef u_int32_t Elf32_Off; /* Unsigned file offset */
|
||||
typedef uint32_t Elf32_Addr; /* Unsigned program address */
|
||||
typedef uint32_t Elf32_Off; /* Unsigned file offset */
|
||||
typedef int32_t Elf32_Sword; /* Signed large integer */
|
||||
typedef u_int32_t Elf32_Word; /* Unsigned large integer */
|
||||
typedef u_int16_t Elf32_Half; /* Unsigned medium integer */
|
||||
typedef uint32_t Elf32_Word; /* Unsigned large integer */
|
||||
typedef uint16_t Elf32_Half; /* Unsigned medium integer */
|
||||
|
||||
typedef u_int64_t Elf64_Addr;
|
||||
typedef u_int64_t Elf64_Off;
|
||||
typedef uint64_t Elf64_Addr;
|
||||
typedef uint64_t Elf64_Off;
|
||||
typedef int32_t Elf64_Shalf;
|
||||
|
||||
typedef int32_t Elf64_Sword;
|
||||
typedef u_int32_t Elf64_Word;
|
||||
typedef uint32_t Elf64_Word;
|
||||
|
||||
typedef int64_t Elf64_Sxword;
|
||||
typedef u_int64_t Elf64_Xword;
|
||||
typedef uint64_t Elf64_Xword;
|
||||
|
||||
typedef u_int32_t Elf64_Half;
|
||||
typedef u_int16_t Elf64_Quarter;
|
||||
typedef uint32_t Elf64_Half;
|
||||
typedef uint16_t Elf64_Quarter;
|
||||
|
||||
/*
|
||||
* e_ident[] identification indexes
|
||||
|
||||
@@ -350,6 +350,8 @@ static int setup_guest(int xc_handle,
|
||||
start_info = xc_map_foreign_range(
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE, page_array[0]);
|
||||
memset(start_info, 0, sizeof(*start_info));
|
||||
rc = xc_version(xc_handle, XENVER_version, NULL);
|
||||
sprintf(start_info->magic, "Xen-%i.%i", rc >> 16, rc & (0xFFFF));
|
||||
start_info->flags = flags;
|
||||
start_info->store_mfn = nr_pages - 2;
|
||||
start_info->store_evtchn = store_evtchn;
|
||||
@@ -624,6 +626,8 @@ static int setup_guest(int xc_handle,
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
|
||||
page_array[(vstartinfo_start-dsi.v_start)>>PAGE_SHIFT]);
|
||||
memset(start_info, 0, sizeof(*start_info));
|
||||
rc = xc_version(xc_handle, XENVER_version, NULL);
|
||||
sprintf(start_info->magic, "Xen-%i.%i", rc >> 16, rc & (0xFFFF));
|
||||
start_info->nr_pages = nr_pages;
|
||||
start_info->shared_info = shared_info_frame << PAGE_SHIFT;
|
||||
start_info->flags = flags;
|
||||
|
||||
@@ -279,6 +279,7 @@ static int setup_guest(int xc_handle,
|
||||
vcpu_guest_context_t *ctxt,
|
||||
unsigned long shared_info_frame,
|
||||
unsigned int control_evtchn,
|
||||
unsigned int lapic,
|
||||
unsigned int vcpus,
|
||||
unsigned int store_evtchn,
|
||||
unsigned long *store_mfn)
|
||||
@@ -554,7 +555,7 @@ static int setup_guest(int xc_handle,
|
||||
ctxt->user_regs.eax = 0;
|
||||
ctxt->user_regs.esp = 0;
|
||||
ctxt->user_regs.ebx = 0; /* startup_32 expects this to be 0 to signal boot cpu */
|
||||
ctxt->user_regs.ecx = 0;
|
||||
ctxt->user_regs.ecx = lapic;
|
||||
ctxt->user_regs.esi = 0;
|
||||
ctxt->user_regs.edi = 0;
|
||||
ctxt->user_regs.ebp = 0;
|
||||
@@ -597,6 +598,7 @@ int xc_vmx_build(int xc_handle,
|
||||
int memsize,
|
||||
const char *image_name,
|
||||
unsigned int control_evtchn,
|
||||
unsigned int lapic,
|
||||
unsigned int vcpus,
|
||||
unsigned int store_evtchn,
|
||||
unsigned long *store_mfn)
|
||||
@@ -651,9 +653,9 @@ int xc_vmx_build(int xc_handle,
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if ( setup_guest(xc_handle, domid, memsize, image, image_size,
|
||||
nr_pages, ctxt, op.u.getdomaininfo.shared_info_frame,
|
||||
control_evtchn, vcpus, store_evtchn, store_mfn) < 0)
|
||||
if ( setup_guest(xc_handle, domid, memsize, image, image_size, nr_pages,
|
||||
ctxt, op.u.getdomaininfo.shared_info_frame, control_evtchn,
|
||||
lapic, vcpus, store_evtchn, store_mfn) < 0)
|
||||
{
|
||||
ERROR("Error constructing guest OS");
|
||||
goto error_out;
|
||||
|
||||
@@ -56,6 +56,7 @@ int xc_vmx_build(int xc_handle,
|
||||
int memsize,
|
||||
const char *image_name,
|
||||
unsigned int control_evtchn,
|
||||
unsigned int lapic,
|
||||
unsigned int vcpus,
|
||||
unsigned int store_evtchn,
|
||||
unsigned long *store_mfn);
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sched.h>
|
||||
#include <error.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/signal.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
|
||||
@@ -438,19 +438,20 @@ static PyObject *pyxc_vmx_build(PyObject *self,
|
||||
char *image;
|
||||
int control_evtchn, store_evtchn;
|
||||
int vcpus = 1;
|
||||
int lapic = 0;
|
||||
int memsize;
|
||||
unsigned long store_mfn = 0;
|
||||
|
||||
static char *kwd_list[] = { "dom", "control_evtchn", "store_evtchn",
|
||||
"memsize", "image", "vcpus", NULL };
|
||||
"memsize", "image", "lapic", "vcpus", NULL };
|
||||
|
||||
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisi", kwd_list,
|
||||
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisii", kwd_list,
|
||||
&dom, &control_evtchn, &store_evtchn,
|
||||
&memsize, &image, &vcpus) )
|
||||
&memsize, &image, &lapic, &vcpus) )
|
||||
return NULL;
|
||||
|
||||
if ( xc_vmx_build(xc->xc_handle, dom, memsize, image, control_evtchn,
|
||||
vcpus, store_evtchn, &store_mfn) != 0 )
|
||||
lapic, vcpus, store_evtchn, &store_mfn) != 0 )
|
||||
return PyErr_SetFromErrno(xc_error);
|
||||
|
||||
return Py_BuildValue("{s:i}", "store_mfn", store_mfn);
|
||||
|
||||
@@ -695,7 +695,7 @@ static PyObject *xspy_introduce_domain(PyObject *self, PyObject *args,
|
||||
PyObject *kwds)
|
||||
{
|
||||
static char *kwd_spec[] = { "dom", "page", "port", NULL };
|
||||
static char *arg_spec = "iii";
|
||||
static char *arg_spec = "ili";
|
||||
domid_t dom = 0;
|
||||
unsigned long page = 0;
|
||||
unsigned int port = 0;
|
||||
|
||||
@@ -99,7 +99,7 @@ def listenTCP(port, factory, interface='', backlog=None):
|
||||
return l
|
||||
|
||||
def SetCloExec(SocketListener):
|
||||
SocketListener.SetCloExec()
|
||||
SocketListener.setCloExec()
|
||||
|
||||
def connectTCP(host, port, factory, timeout=None, bindAddress=None):
|
||||
c = TCPConnector(host, port, factory, timeout=timeout, bindAddress=bindAddress)
|
||||
|
||||
@@ -595,6 +595,7 @@ class XendDomainInfo:
|
||||
to_store = {
|
||||
'domid': str(self.domid),
|
||||
'vm': self.vmpath,
|
||||
'name': self.info['name'],
|
||||
'console/limit': str(xroot.get_console_limit() * 1024),
|
||||
'memory/target': str(self.info['memory_KiB'])
|
||||
}
|
||||
|
||||
@@ -203,6 +203,10 @@ class VmxImageHandler(ImageHandler):
|
||||
|
||||
self.dmargs += self.configVNC(imageConfig)
|
||||
|
||||
self.lapic = 0
|
||||
lapic = sxp.child_value(imageConfig, 'lapic')
|
||||
if not lapic is None:
|
||||
self.lapic = int(lapic)
|
||||
|
||||
def buildDomain(self):
|
||||
# Create an event channel
|
||||
@@ -217,6 +221,7 @@ class VmxImageHandler(ImageHandler):
|
||||
log.debug("control_evtchn = %d", self.device_channel)
|
||||
log.debug("store_evtchn = %d", store_evtchn)
|
||||
log.debug("memsize = %d", self.vm.getMemoryTarget() / 1024)
|
||||
log.debug("lapic = %d", self.lapic)
|
||||
log.debug("vcpus = %d", self.vm.getVCpuCount())
|
||||
|
||||
return xc.vmx_build(dom = self.vm.getDomid(),
|
||||
@@ -224,6 +229,7 @@ class VmxImageHandler(ImageHandler):
|
||||
control_evtchn = self.device_channel,
|
||||
store_evtchn = store_evtchn,
|
||||
memsize = self.vm.getMemoryTarget() / 1024,
|
||||
lapic = self.lapic,
|
||||
vcpus = self.vm.getVCpuCount())
|
||||
|
||||
|
||||
|
||||
@@ -262,10 +262,7 @@ class Daemon:
|
||||
return 1
|
||||
|
||||
def stop(self):
|
||||
result = self.cleanup_xend(True)
|
||||
from xen.xend import Vifctl
|
||||
Vifctl.network("stop")
|
||||
return result
|
||||
return self.cleanup_xend(True)
|
||||
|
||||
def run(self, status):
|
||||
try:
|
||||
|
||||
@@ -25,7 +25,6 @@ from xen.xend import XendDomain
|
||||
from xen.xend.XendDomainInfo import XendDomainInfo
|
||||
from xen.xend.Args import FormFn
|
||||
from xen.xend.XendError import XendError
|
||||
from xen.xend.XendLogging import log
|
||||
|
||||
from xen.web.SrvDir import SrvDir
|
||||
from SrvDomain import SrvDomain
|
||||
@@ -52,7 +51,7 @@ class SrvDomainDir(SrvDir):
|
||||
else:
|
||||
return self.domain(x)
|
||||
|
||||
def op_create(self, op, req):
|
||||
def op_create(self, _, req):
|
||||
"""Create a domain.
|
||||
Expects the domain config in request parameter 'config' in SXP format.
|
||||
"""
|
||||
@@ -66,12 +65,12 @@ class SrvDomainDir(SrvDir):
|
||||
pin.input_eof()
|
||||
config = pin.get_val()
|
||||
ok = 1
|
||||
except sxp.ParseError, ex:
|
||||
errmsg = 'Invalid configuration ' + str(ex)
|
||||
except Exception, ex:
|
||||
print 'op_create> Exception in config', ex
|
||||
traceback.print_exc()
|
||||
errmsg = 'Configuration error ' + str(ex)
|
||||
except sxp.ParseError, ex:
|
||||
errmsg = 'Invalid configuration ' + str(ex)
|
||||
if not ok:
|
||||
raise XendError(errmsg)
|
||||
try:
|
||||
@@ -108,7 +107,7 @@ class SrvDomainDir(SrvDir):
|
||||
"""
|
||||
return req.threadRequest(self.do_restore, op, req)
|
||||
|
||||
def do_restore(self, op, req):
|
||||
def do_restore(self, _, req):
|
||||
fn = FormFn(self.xd.domain_restore,
|
||||
[['file', 'str']])
|
||||
dominfo = fn(req.args)
|
||||
|
||||
@@ -192,4 +192,5 @@ def listenEvent(daemon):
|
||||
if xroot.get_xend_http_server():
|
||||
port = xroot.get_xend_event_port()
|
||||
interface = xroot.get_xend_address()
|
||||
tcp.listenTCP(port, factory, interface=interface)
|
||||
l = tcp.listenTCP(port, factory, interface=interface)
|
||||
l.setCloExec()
|
||||
@@ -5,9 +5,6 @@
|
||||
# Public License. See the file "COPYING" in the main directory of
|
||||
# this archive for more details.
|
||||
|
||||
import errno
|
||||
import threading
|
||||
from xen.lowlevel import xs
|
||||
from xen.xend.xenstore.xsutil import xshandle
|
||||
|
||||
|
||||
|
||||
@@ -158,6 +158,10 @@ gopts.var('cpu', val='CPU',
|
||||
fn=set_int, default=None,
|
||||
use="CPU to run the domain on.")
|
||||
|
||||
gopts.var('lapic', val='LAPIC',
|
||||
fn=set_int, default=0,
|
||||
use="Disable or enable local APIC of VMX domain.")
|
||||
|
||||
gopts.var('vcpus', val='VCPUS',
|
||||
fn=set_int, default=1,
|
||||
use="# of Virtual CPUS in domain.")
|
||||
@@ -316,10 +320,6 @@ gopts.var('nfs_root', val="PATH",
|
||||
fn=set_value, default=None,
|
||||
use="Set the path of the root NFS directory.")
|
||||
|
||||
gopts.var('memmap', val='FILE',
|
||||
fn=set_value, default='',
|
||||
use="Path to memap SXP file.")
|
||||
|
||||
gopts.var('device_model', val='FILE',
|
||||
fn=set_value, default='',
|
||||
use="Path to device model program.")
|
||||
@@ -542,9 +542,9 @@ def configure_vfr(opts, config, vals):
|
||||
def configure_vmx(opts, config_image, vals):
|
||||
"""Create the config for VMX devices.
|
||||
"""
|
||||
args = [ 'memmap', 'device_model', 'vcpus', 'cdrom',
|
||||
'boot', 'fda', 'fdb', 'localtime', 'serial', 'macaddr', 'stdvga',
|
||||
'isa', 'nographic', 'vnc', 'vncviewer', 'sdl', 'display', 'ne2000']
|
||||
args = [ 'device_model', 'vcpus', 'cdrom', 'boot', 'fda', 'fdb',
|
||||
'localtime', 'serial', 'macaddr', 'stdvga', 'isa', 'nographic',
|
||||
'vnc', 'vncviewer', 'sdl', 'display', 'ne2000', 'lapic']
|
||||
for a in args:
|
||||
if (vals.__dict__[a]):
|
||||
config_image.append([a, vals.__dict__[a]])
|
||||
|
||||
@@ -61,6 +61,8 @@ xm common subcommands:
|
||||
top monitor system and domains in real-time
|
||||
unpause <DomId> unpause a paused domain
|
||||
|
||||
<DomName> can be substituted for <DomId> in xm subcommands.
|
||||
|
||||
For a complete list of subcommands run 'xm help --long'
|
||||
For more help on xm see the xm(1) man page
|
||||
For more help on xm create, see the xmdomain.cfg(5) man page"""
|
||||
@@ -119,6 +121,8 @@ xm full list of subcommands:
|
||||
vnet-create <config> create a vnet from a config file
|
||||
vnet-delete <vnetid> delete a vnet
|
||||
|
||||
<DomName> can be substituted for <DomId> in xm subcommands.
|
||||
|
||||
For a short list of subcommands run 'xm help'
|
||||
For more help on xm see the xm(1) man page
|
||||
For more help on xm create, see the xmdomain.cfg(5) man page"""
|
||||
|
||||
+15
-12
@@ -36,18 +36,21 @@ source labelfuncs.sh
|
||||
|
||||
usage ()
|
||||
{
|
||||
echo "Usage: $0 -sid <ssidref> [<policy name>] or"
|
||||
echo " $0 -dom <domid> [<policy name>] "
|
||||
echo ""
|
||||
echo "policy name : the name of the policy, i.e. 'chwall'"
|
||||
echo " If the policy name is omitted, the grub.conf"
|
||||
echo " entry of the running system is tried to be read"
|
||||
echo " and the policy name determined from there."
|
||||
echo "ssidref : an ssidref in hex or decimal format, i.e., '0x00010002'"
|
||||
echo " or '65538'"
|
||||
echo "domid : id of the domain, i.e., '1'; Use numbers from the 2nd"
|
||||
echo " column shown when invoking 'xm list'"
|
||||
echo ""
|
||||
echo "Use this tool to display the label of a domain or the label that is
|
||||
corresponding to an ssidref given the name of the running policy.
|
||||
|
||||
Usage: $0 -sid <ssidref> [<policy name>] or
|
||||
$0 -dom <domid> [<policy name>]
|
||||
|
||||
policy name : the name of the policy, i.e. 'chwall'
|
||||
If the policy name is omitted, the grub.conf
|
||||
entry of the running system is tried to be read
|
||||
and the policy name determined from there.
|
||||
ssidref : an ssidref in hex or decimal format, i.e., '0x00010002'
|
||||
or '65538'
|
||||
domid : id of the domain, i.e., '1'; Use numbers from the 2nd
|
||||
column shown when invoking 'xm list'
|
||||
"
|
||||
}
|
||||
|
||||
|
||||
|
||||
+23
-17
@@ -39,21 +39,27 @@ source labelfuncs.sh
|
||||
|
||||
usage ()
|
||||
{
|
||||
echo "Usage: $0 [Option] <vmfile> <label> [<policy name>]"
|
||||
echo " or $0 -l [<policy name>]"
|
||||
echo ""
|
||||
echo "Valid options are:"
|
||||
echo "-r : to relabel a file without being prompted"
|
||||
echo ""
|
||||
echo "vmfile : XEN vm configuration file"
|
||||
echo "label : the label to map to an ssidref"
|
||||
echo "policy name : the name of the policy, i.e. 'chwall'"
|
||||
echo " If the policy name is omitted, it is attempted"
|
||||
echo " to find the current policy's name in grub.conf."
|
||||
echo ""
|
||||
echo "-l [<policy name>] is used to show valid labels in the map file of"
|
||||
echo " the given or current policy."
|
||||
echo ""
|
||||
echo "Use this tool to put the ssidref corresponding to a label of a policy into
|
||||
the VM configuration file, or use it to display all labels of a policy.
|
||||
|
||||
Usage: $0 [Option] <vmfile> <label> [<policy name>]
|
||||
or $0 -l [<policy name>]
|
||||
|
||||
Valid options are:
|
||||
-r : to relabel a file without being prompted
|
||||
|
||||
vmfile : XEN vm configuration file; give complete path
|
||||
label : the label to map to an ssidref
|
||||
policy name : the name of the policy, i.e. 'chwall'
|
||||
If the policy name is omitted, it is attempted
|
||||
to find the current policy's name in grub.conf.
|
||||
|
||||
-l [<policy name>] is used to show valid labels in the map file of
|
||||
the given or current policy. If the policy name
|
||||
is omitted, it will be tried to determine the
|
||||
current policy from grub.conf (/boot/grub/grub.conf)
|
||||
|
||||
"
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +89,7 @@ if [ "$mode" == "show" ]; then
|
||||
exit -1;
|
||||
fi
|
||||
else
|
||||
policy=$3;
|
||||
policy=$1;
|
||||
fi
|
||||
|
||||
|
||||
@@ -92,7 +98,7 @@ if [ "$mode" == "show" ]; then
|
||||
if [ "$res" != "0" ]; then
|
||||
showLabels $mapfile
|
||||
else
|
||||
echo "Could not find map file for policy '$1'."
|
||||
echo "Could not find map file for policy '$policy'."
|
||||
fi
|
||||
elif [ "$mode" == "usage" ]; then
|
||||
usage
|
||||
|
||||
@@ -26,11 +26,16 @@ fi
|
||||
# Show usage of this program
|
||||
usage ()
|
||||
{
|
||||
echo "Usage: $0 <policy name> <root of xen repository>"
|
||||
echo ""
|
||||
echo "<policy name> : The name of the policy, i.e. xen_null"
|
||||
echo "<root of xen repository> : The root of the XEN repositrory."
|
||||
echo ""
|
||||
echo "Use this tool to add the binary policy to the Xen grub entry and
|
||||
have Xen automatically enforce the policy when starting.
|
||||
|
||||
Usage: $0 <policy name> <root of xen repository>
|
||||
|
||||
<policy name> : The name of the policy, i.e. xen_null
|
||||
<root of xen repository> : The root of the XEN repository. Give
|
||||
complete path.
|
||||
|
||||
"
|
||||
}
|
||||
|
||||
# This function sets the global variable 'linux'
|
||||
@@ -43,11 +48,24 @@ getLinuxVersion ()
|
||||
for f in $path/linux-*-xen0 ; do
|
||||
versionfile=$f/include/linux/version.h
|
||||
if [ -r $versionfile ]; then
|
||||
lnx=`cat $versionfile | \
|
||||
grep UTS_RELEASE | \
|
||||
awk '{ \
|
||||
len=length($3); \
|
||||
print substr($3,2,len-2) }'`
|
||||
lnx=`cat $versionfile | \
|
||||
grep UTS_RELEASE | \
|
||||
awk '{ \
|
||||
len=length($3); \
|
||||
version=substr($3,2,len-2); \
|
||||
split(version,numbers,"."); \
|
||||
if (numbers[4]=="") { \
|
||||
printf("%s.%s.%s", \
|
||||
numbers[1], \
|
||||
numbers[2], \
|
||||
numbers[3]); \
|
||||
} else { \
|
||||
printf("%s.%s.%s[.0-9]*-xen0",\
|
||||
numbers[1], \
|
||||
numbers[2], \
|
||||
numbers[3]); \
|
||||
} \
|
||||
}'`
|
||||
fi
|
||||
if [ "$lnx" != "" ]; then
|
||||
linux="[./0-9a-zA-z]*$lnx"
|
||||
@@ -143,10 +161,19 @@ updateGrub ()
|
||||
echo "Could not create temporary file! Aborting."
|
||||
exit -1
|
||||
fi
|
||||
mv -f $tmpfile $grubconf
|
||||
diff $tmpfile $grubconf > /dev/null
|
||||
RES=$?
|
||||
if [ "$RES" == "0" ]; then
|
||||
echo "No changes were made to $grubconf."
|
||||
else
|
||||
echo "Successfully updated $grubconf."
|
||||
mv -f $tmpfile $grubconf
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "$1" == "" -o "$2" == "" ]; then
|
||||
echo "Error: Not enough command line parameters."
|
||||
echo ""
|
||||
usage
|
||||
exit -1
|
||||
fi
|
||||
|
||||
@@ -38,13 +38,13 @@ SONAME_FLAGS=-Wl,-soname -Wl,libxenstat.so.$(MAJOR)
|
||||
|
||||
WARN_FLAGS=-Wall -Werror
|
||||
|
||||
CFLAGS+=-Isrc -I$(XEN_LIBXC)
|
||||
CFLAGS+=-Isrc -I$(XEN_LIBXC) -I$(XEN_XENSTORE)
|
||||
LDFLAGS+=-Lsrc
|
||||
|
||||
all: $(LIB)
|
||||
|
||||
$(LIB): $(OBJECTS)
|
||||
$(AR) rc $@ $^
|
||||
$(AR) rc $@ $^ $(XEN_XENSTORE)/libxenstore.so
|
||||
$(RANLIB) $@
|
||||
|
||||
$(SHLIB): $(OBJECTS)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <xen-interface.h>
|
||||
#include <xs.h>
|
||||
#include "xenstat.h"
|
||||
|
||||
/*
|
||||
@@ -31,6 +32,7 @@
|
||||
|
||||
struct xenstat_handle {
|
||||
xi_handle *xihandle;
|
||||
struct xs_handle *xshandle; /* xenstore handle */
|
||||
int page_size;
|
||||
FILE *procnetdev;
|
||||
char xen_version[VERSION_SIZE]; /* xen version running on this node */
|
||||
@@ -49,6 +51,7 @@ struct xenstat_node {
|
||||
|
||||
struct xenstat_domain {
|
||||
unsigned int id;
|
||||
char *name;
|
||||
unsigned int state;
|
||||
unsigned long long cpu_ns;
|
||||
unsigned int num_vcpus; /* No. vcpus configured for domain */
|
||||
@@ -110,6 +113,7 @@ static void xenstat_free_xen_version(xenstat_node * node);
|
||||
static void xenstat_uninit_vcpus(xenstat_handle * handle);
|
||||
static void xenstat_uninit_networks(xenstat_handle * handle);
|
||||
static void xenstat_uninit_xen_version(xenstat_handle * handle);
|
||||
static char *xenstat_get_domain_name(xenstat_handle * handle, unsigned int domain_id);
|
||||
|
||||
static xenstat_collector collectors[] = {
|
||||
{ XENSTAT_VCPU, xenstat_collect_vcpus,
|
||||
@@ -153,6 +157,13 @@ xenstat_handle *xenstat_init()
|
||||
return NULL;
|
||||
}
|
||||
|
||||
handle->xshandle = xs_daemon_open_readonly(); /* open handle to xenstore*/
|
||||
if (handle->xshandle == NULL) {
|
||||
perror("unable to open xenstore\n");
|
||||
free(handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
@@ -163,6 +174,7 @@ void xenstat_uninit(xenstat_handle * handle)
|
||||
for (i = 0; i < NUM_COLLECTORS; i++)
|
||||
collectors[i].uninit(handle);
|
||||
xi_uninit(handle->xihandle);
|
||||
xs_daemon_close(handle->xshandle);
|
||||
free(handle);
|
||||
}
|
||||
}
|
||||
@@ -228,6 +240,7 @@ xenstat_node *xenstat_get_node(xenstat_handle * handle, unsigned int flags)
|
||||
for (i = 0; i < new_domains; i++) {
|
||||
/* Fill in domain using domaininfo[i] */
|
||||
domain->id = domaininfo[i].domain;
|
||||
domain->name = xenstat_get_domain_name(handle, domaininfo[i].domain);
|
||||
domain->state = domaininfo[i].flags;
|
||||
domain->cpu_ns = domaininfo[i].cpu_time;
|
||||
domain->num_vcpus = (domaininfo[i].max_vcpu_id+1);
|
||||
@@ -339,6 +352,12 @@ unsigned xenstat_domain_id(xenstat_domain * domain)
|
||||
return domain->id;
|
||||
}
|
||||
|
||||
/* Get the domain name for the domain */
|
||||
char *xenstat_domain_name(xenstat_domain * domain)
|
||||
{
|
||||
return domain->name;
|
||||
}
|
||||
|
||||
/* Get information about how much CPU time has been used */
|
||||
unsigned long long xenstat_domain_cpu_ns(xenstat_domain * domain)
|
||||
{
|
||||
@@ -675,3 +694,25 @@ static void xenstat_free_xen_version(xenstat_node * node)
|
||||
static void xenstat_uninit_xen_version(xenstat_handle * handle)
|
||||
{
|
||||
}
|
||||
|
||||
static char *xenstat_get_domain_name(xenstat_handle *handle, unsigned int domain_id)
|
||||
{
|
||||
char path[80];
|
||||
char *name;
|
||||
unsigned int *len;
|
||||
struct xs_transaction_handle *xstranshandle;
|
||||
|
||||
snprintf(path, sizeof(path),"/local/domain/%i/name", domain_id);
|
||||
|
||||
xstranshandle = xs_transaction_start(handle->xshandle);
|
||||
if (xstranshandle == NULL) {
|
||||
perror("Unable to get transcation handle from xenstore\n");
|
||||
exit(1); /* Change this */
|
||||
}
|
||||
|
||||
name = (char *) xs_read(handle->xshandle, xstranshandle, path, len);
|
||||
|
||||
xs_transaction_end(handle->xshandle, xstranshandle, false);
|
||||
|
||||
return name;
|
||||
}
|
||||
@@ -80,6 +80,9 @@ unsigned long long xenstat_node_cpu_hz(xenstat_node * node);
|
||||
/* Get the domain ID for this domain */
|
||||
unsigned xenstat_domain_id(xenstat_domain * domain);
|
||||
|
||||
/* Set the domain name for the domain */
|
||||
char *xenstat_domain_name(xenstat_domain * domain);
|
||||
|
||||
/* Get information about how much CPU time has been used */
|
||||
unsigned long long xenstat_domain_cpu_ns(xenstat_domain * domain);
|
||||
|
||||
|
||||
@@ -67,8 +67,6 @@ static int compare_domains(xenstat_domain **, xenstat_domain **);
|
||||
static unsigned long long tot_net_bytes( xenstat_domain *, int);
|
||||
|
||||
/* Field functions */
|
||||
static int compare_domid(xenstat_domain *domain1, xenstat_domain *domain2);
|
||||
static void print_domid(xenstat_domain *domain);
|
||||
static int compare_state(xenstat_domain *domain1, xenstat_domain *domain2);
|
||||
static void print_state(xenstat_domain *domain);
|
||||
static int compare_cpu(xenstat_domain *domain1, xenstat_domain *domain2);
|
||||
@@ -91,6 +89,8 @@ static int compare_net_rx(xenstat_domain *domain1, xenstat_domain *domain2);
|
||||
static void print_net_rx(xenstat_domain *domain);
|
||||
static int compare_ssid(xenstat_domain *domain1, xenstat_domain *domain2);
|
||||
static void print_ssid(xenstat_domain *domain);
|
||||
static int compare_name(xenstat_domain *domain1, xenstat_domain *domain2);
|
||||
static void print_name(xenstat_domain *domain);
|
||||
|
||||
/* Section printing functions */
|
||||
static void do_summary(void);
|
||||
@@ -104,6 +104,7 @@ static void top(void);
|
||||
/* Field types */
|
||||
typedef enum field_id {
|
||||
FIELD_DOMID,
|
||||
FIELD_NAME,
|
||||
FIELD_STATE,
|
||||
FIELD_CPU,
|
||||
FIELD_CPU_PCT,
|
||||
@@ -127,7 +128,7 @@ typedef struct field {
|
||||
} field;
|
||||
|
||||
field fields[] = {
|
||||
{ FIELD_DOMID, "DOMID", 5, compare_domid, print_domid },
|
||||
{ FIELD_NAME, "NAME", 10, compare_name, print_name },
|
||||
{ FIELD_STATE, "STATE", 6, compare_state, print_state },
|
||||
{ FIELD_CPU, "CPU(sec)", 10, compare_cpu, print_cpu },
|
||||
{ FIELD_CPU_PCT, "CPU(%)", 6, compare_cpu_pct, print_cpu_pct },
|
||||
@@ -344,16 +345,16 @@ static int compare_domains(xenstat_domain **domain1, xenstat_domain **domain2)
|
||||
|
||||
/* Field functions */
|
||||
|
||||
/* Compares domain ids of two domains, returning -1,0,1 for <,=,> */
|
||||
int compare_domid(xenstat_domain *domain1, xenstat_domain *domain2)
|
||||
/* Compare domain names, returning -1,0,1 for <,=,> */
|
||||
int compare_name(xenstat_domain *domain1, xenstat_domain *domain2)
|
||||
{
|
||||
return compare(xenstat_domain_id(domain1), xenstat_domain_id(domain2));
|
||||
return strcasecmp(xenstat_domain_name(domain1), xenstat_domain_name(domain2));
|
||||
}
|
||||
|
||||
/* Prints domain identification number */
|
||||
void print_domid(xenstat_domain *domain)
|
||||
/* Prints domain name */
|
||||
void print_name(xenstat_domain *domain)
|
||||
{
|
||||
print("%5u", xenstat_domain_id(domain));
|
||||
print("%10s", xenstat_domain_name(domain));
|
||||
}
|
||||
|
||||
struct {
|
||||
|
||||
@@ -77,7 +77,7 @@ libxenstore.so: xs.opic xs_lib.opic
|
||||
clean: testsuite-clean
|
||||
rm -f *.o *.opic *.so
|
||||
rm -f xenstored xs_random xs_stress xs_crashme
|
||||
rm -f xs_test xenstored_test
|
||||
rm -f xs_test xenstored_test xs_tdb_dump
|
||||
$(RM) $(PROG_DEP)
|
||||
|
||||
print-dir:
|
||||
|
||||
@@ -188,7 +188,7 @@ static void trace_io(const struct connection *conn,
|
||||
tm = localtime(&now);
|
||||
|
||||
write(tracefd, prefix, strlen(prefix));
|
||||
sprintf(string, " %p %0d:%0d:%0d ", conn, tm->tm_hour, tm->tm_min,
|
||||
sprintf(string, " %p %02d:%02d:%02d ", conn, tm->tm_hour, tm->tm_min,
|
||||
tm->tm_sec);
|
||||
write(tracefd, string, strlen(string));
|
||||
write(tracefd, sockmsg_string(data->hdr.msg.type),
|
||||
|
||||
@@ -392,8 +392,11 @@ check_cache(struct domain *dom, domid_t rdom) {
|
||||
int i;
|
||||
|
||||
printkd("checking cache: %x --> %x.\n", dom->domain_id, rdom);
|
||||
|
||||
if (dom->ssid == NULL)
|
||||
return 0;
|
||||
ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
|
||||
(struct acm_ssid_domain *)(dom)->ssid);
|
||||
(struct acm_ssid_domain *)(dom->ssid));
|
||||
|
||||
for(i=0; i< ACM_TE_CACHE_SIZE; i++) {
|
||||
if ((ste_ssid->ste_cache[i].valid == VALID) &&
|
||||
@@ -412,6 +415,8 @@ cache_result(struct domain *subj, struct domain *obj) {
|
||||
struct ste_ssid *ste_ssid;
|
||||
int i;
|
||||
printkd("caching from doms: %x --> %x.\n", subj->domain_id, obj->domain_id);
|
||||
if (subj->ssid == NULL)
|
||||
return;
|
||||
ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
|
||||
(struct acm_ssid_domain *)(subj)->ssid);
|
||||
for(i=0; i< ACM_TE_CACHE_SIZE; i++)
|
||||
@@ -431,26 +436,34 @@ clean_id_from_cache(domid_t id)
|
||||
struct ste_ssid *ste_ssid;
|
||||
int i;
|
||||
struct domain **pd;
|
||||
struct acm_ssid_domain *ssid;
|
||||
|
||||
printkd("deleting cache for dom %x.\n", id);
|
||||
|
||||
read_lock(&domlist_lock); /* look through caches of all domains */
|
||||
pd = &domain_list;
|
||||
for ( pd = &domain_list; *pd != NULL; pd = &(*pd)->next_in_list ) {
|
||||
ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
|
||||
(struct acm_ssid_domain *)(*pd)->ssid);
|
||||
ssid = (struct acm_ssid_domain *)((*pd)->ssid);
|
||||
|
||||
if (ssid == NULL)
|
||||
continue; /* hanging domain structure, no ssid any more ... */
|
||||
ste_ssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY, ssid);
|
||||
if (!ste_ssid) {
|
||||
printk("%s: deleting ID from cache ERROR (no ste_ssid)!\n",
|
||||
__func__);
|
||||
goto out;
|
||||
}
|
||||
for (i=0; i<ACM_TE_CACHE_SIZE; i++)
|
||||
if ((ste_ssid->ste_cache[i].valid == VALID) &&
|
||||
(ste_ssid->ste_cache[i].id = id))
|
||||
(ste_ssid->ste_cache[i].id == id))
|
||||
ste_ssid->ste_cache[i].valid = FREE;
|
||||
}
|
||||
out:
|
||||
read_unlock(&domlist_lock);
|
||||
}
|
||||
|
||||
/***************************
|
||||
* Authorization functions
|
||||
**************************/
|
||||
|
||||
static int
|
||||
ste_pre_domain_create(void *subject_ssid, ssidref_t ssidref)
|
||||
{
|
||||
@@ -484,44 +497,13 @@ ste_post_domain_destroy(void *subject_ssid, domid_t id)
|
||||
|
||||
/* -------- EVENTCHANNEL OPERATIONS -----------*/
|
||||
static int
|
||||
ste_pre_eventchannel_unbound(domid_t id) {
|
||||
struct domain *subj, *obj;
|
||||
int ret;
|
||||
traceprintk("%s: dom%x-->dom%x.\n",
|
||||
__func__, current->domain->domain_id, id);
|
||||
|
||||
if (check_cache(current->domain, id)) {
|
||||
atomic_inc(&ste_bin_pol.ec_cachehit_count);
|
||||
return ACM_ACCESS_PERMITTED;
|
||||
}
|
||||
atomic_inc(&ste_bin_pol.ec_eval_count);
|
||||
subj = current->domain;
|
||||
obj = find_domain_by_id(id);
|
||||
|
||||
if (share_common_type(subj, obj)) {
|
||||
cache_result(subj, obj);
|
||||
ret = ACM_ACCESS_PERMITTED;
|
||||
} else {
|
||||
atomic_inc(&ste_bin_pol.ec_denied_count);
|
||||
ret = ACM_ACCESS_DENIED;
|
||||
}
|
||||
if (obj != NULL)
|
||||
put_domain(obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
ste_pre_eventchannel_interdomain(domid_t id1, domid_t id2)
|
||||
{
|
||||
ste_pre_eventchannel_unbound(domid_t id1, domid_t id2) {
|
||||
struct domain *subj, *obj;
|
||||
int ret;
|
||||
traceprintk("%s: dom%x-->dom%x.\n", __func__,
|
||||
(id1 == DOMID_SELF) ? current->domain->domain_id : id1,
|
||||
(id2 == DOMID_SELF) ? current->domain->domain_id : id2);
|
||||
|
||||
/* following is a bit longer but ensures that we
|
||||
* "put" only domains that we where "find"-ing
|
||||
*/
|
||||
if (id1 == DOMID_SELF) id1 = current->domain->domain_id;
|
||||
if (id2 == DOMID_SELF) id2 = current->domain->domain_id;
|
||||
|
||||
@@ -531,7 +513,7 @@ ste_pre_eventchannel_interdomain(domid_t id1, domid_t id2)
|
||||
ret = ACM_ACCESS_DENIED;
|
||||
goto out;
|
||||
}
|
||||
/* cache check late, but evtchn is not on performance critical path */
|
||||
/* cache check late */
|
||||
if (check_cache(subj, obj->domain_id)) {
|
||||
atomic_inc(&ste_bin_pol.ec_cachehit_count);
|
||||
ret = ACM_ACCESS_PERMITTED;
|
||||
@@ -546,7 +528,7 @@ ste_pre_eventchannel_interdomain(domid_t id1, domid_t id2)
|
||||
atomic_inc(&ste_bin_pol.ec_denied_count);
|
||||
ret = ACM_ACCESS_DENIED;
|
||||
}
|
||||
out:
|
||||
out:
|
||||
if (obj != NULL)
|
||||
put_domain(obj);
|
||||
if (subj != NULL)
|
||||
@@ -554,6 +536,50 @@ ste_pre_eventchannel_interdomain(domid_t id1, domid_t id2)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
ste_pre_eventchannel_interdomain(domid_t id)
|
||||
{
|
||||
struct domain *subj=NULL, *obj=NULL;
|
||||
int ret;
|
||||
|
||||
traceprintk("%s: dom%x-->dom%x.\n", __func__,
|
||||
current->domain->domain_id,
|
||||
(id == DOMID_SELF) ? current->domain->domain_id : id);
|
||||
|
||||
/* following is a bit longer but ensures that we
|
||||
* "put" only domains that we where "find"-ing
|
||||
*/
|
||||
if (id == DOMID_SELF) id = current->domain->domain_id;
|
||||
|
||||
subj = current->domain;
|
||||
obj = find_domain_by_id(id);
|
||||
if (obj == NULL) {
|
||||
ret = ACM_ACCESS_DENIED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* cache check late, but evtchn is not on performance critical path */
|
||||
if (check_cache(subj, obj->domain_id)) {
|
||||
atomic_inc(&ste_bin_pol.ec_cachehit_count);
|
||||
ret = ACM_ACCESS_PERMITTED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
atomic_inc(&ste_bin_pol.ec_eval_count);
|
||||
|
||||
if (share_common_type(subj, obj)) {
|
||||
cache_result(subj, obj);
|
||||
ret = ACM_ACCESS_PERMITTED;
|
||||
} else {
|
||||
atomic_inc(&ste_bin_pol.ec_denied_count);
|
||||
ret = ACM_ACCESS_DENIED;
|
||||
}
|
||||
out:
|
||||
if (obj != NULL)
|
||||
put_domain(obj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* -------- SHARED MEMORY OPERATIONS -----------*/
|
||||
|
||||
static int
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <xen/event.h>
|
||||
//#include <xen/shadow.h>
|
||||
#include <xen/console.h>
|
||||
#include <xen/compile.h>
|
||||
|
||||
#include <xen/elf.h>
|
||||
//#include <asm/page.h>
|
||||
@@ -948,6 +949,7 @@ int construct_dom0(struct domain *d,
|
||||
si = (start_info_t *)alloc_xenheap_page();
|
||||
memset(si, 0, PAGE_SIZE);
|
||||
d->shared_info->arch.start_info_pfn = __pa(si) >> PAGE_SHIFT;
|
||||
sprintf(si->magic, "Xen-%i.%i", XEN_VERSION, XEN_SUBVERSION);
|
||||
|
||||
#if 0
|
||||
si->nr_pages = d->tot_pages;
|
||||
|
||||
@@ -815,6 +815,10 @@ int __init calibrate_APIC_clock(void)
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned int get_apic_bus_scale(void)
|
||||
{
|
||||
return bus_scale;
|
||||
}
|
||||
|
||||
static unsigned int calibration_result;
|
||||
|
||||
|
||||
+11
-4
@@ -32,8 +32,8 @@
|
||||
#include <public/io/ioreq.h>
|
||||
#include <asm/vmx.h>
|
||||
#include <public/io/vmx_vpic.h>
|
||||
#include <public/io/vmx_vlapic.h>
|
||||
#include <asm/current.h>
|
||||
#include <asm/vmx_vlapic.h>
|
||||
|
||||
/* set irq level. If an edge is detected, then the IRR is set to 1 */
|
||||
static inline void pic_set_irq1(PicState *s, int irq, int level)
|
||||
@@ -135,7 +135,6 @@ void do_pic_irqs (struct vmx_virpic *s, uint16_t irqs)
|
||||
{
|
||||
s->pics[1].irr |= (uint8_t)(irqs >> 8);
|
||||
s->pics[0].irr |= (uint8_t) irqs;
|
||||
/* TODO for alt_irq_func */
|
||||
pic_update_irq(s);
|
||||
}
|
||||
|
||||
@@ -505,14 +504,22 @@ int cpu_get_pic_interrupt(struct vcpu *v, int *type)
|
||||
{
|
||||
int intno;
|
||||
struct vmx_virpic *s = &v->domain->arch.vmx_platform.vmx_pic;
|
||||
|
||||
struct vmx_platform *plat = &v->domain->arch.vmx_platform;
|
||||
|
||||
if ( !vlapic_accept_pic_intr(v) )
|
||||
return -1;
|
||||
|
||||
if ( !plat->interrupt_request )
|
||||
return -1;
|
||||
|
||||
/* read the irq from the PIC */
|
||||
intno = pic_read_irq(s);
|
||||
*type = VLAPIC_DELIV_MODE_EXT;
|
||||
plat->interrupt_request = 0;
|
||||
return intno;
|
||||
}
|
||||
|
||||
int is_pit_irq(struct vcpu *v, int irq)
|
||||
int is_pit_irq(struct vcpu *v, int irq, int type)
|
||||
{
|
||||
int pit_vec = v->domain->arch.vmx_platform.vmx_pic.pics[0].irq_base;
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <xen/elf.h>
|
||||
#include <xen/kernel.h>
|
||||
#include <xen/domain.h>
|
||||
#include <xen/compile.h>
|
||||
#include <asm/regs.h>
|
||||
#include <asm/system.h>
|
||||
#include <asm/io.h>
|
||||
@@ -582,26 +583,23 @@ int construct_dom0(struct domain *d,
|
||||
_initrd_start, (_initrd_start+initrd_len+PAGE_SIZE-1) & PAGE_MASK);
|
||||
}
|
||||
|
||||
d->next_io_page = max_page;
|
||||
|
||||
/* Set up start info area. */
|
||||
si = (start_info_t *)vstartinfo_start;
|
||||
memset(si, 0, PAGE_SIZE);
|
||||
si->nr_pages = nr_pages;
|
||||
|
||||
si->shared_info = virt_to_phys(d->shared_info);
|
||||
if ( opt_dom0_translate )
|
||||
{
|
||||
si->shared_info = d->next_io_page << PAGE_SHIFT;
|
||||
set_pfn_from_mfn(virt_to_phys(d->shared_info) >> PAGE_SHIFT, d->next_io_page);
|
||||
d->next_io_page++;
|
||||
si->shared_info = max_page << PAGE_SHIFT;
|
||||
set_pfn_from_mfn(virt_to_phys(d->shared_info) >> PAGE_SHIFT, max_page);
|
||||
}
|
||||
else
|
||||
si->shared_info = virt_to_phys(d->shared_info);
|
||||
|
||||
si->flags = SIF_PRIVILEGED | SIF_INITDOMAIN;
|
||||
si->pt_base = vpt_start;
|
||||
si->nr_pt_frames = nr_pt_pages;
|
||||
si->mfn_list = vphysmap_start;
|
||||
sprintf(si->magic, "Xen-%i.%i", XEN_VERSION, XEN_SUBVERSION);
|
||||
|
||||
/* Write the phys->machine and machine->phys table entries. */
|
||||
for ( pfn = 0; pfn < d->tot_pages; pfn++ )
|
||||
|
||||
+4
-1
@@ -1164,6 +1164,7 @@ static int mod_l3_entry(l3_pgentry_t *pl3e,
|
||||
{
|
||||
l3_pgentry_t ol3e;
|
||||
unsigned long vaddr;
|
||||
int okay;
|
||||
|
||||
if ( unlikely(!is_guest_l3_slot(pgentry_ptr_to_slot(pl3e))) )
|
||||
{
|
||||
@@ -1218,7 +1219,9 @@ static int mod_l3_entry(l3_pgentry_t *pl3e,
|
||||
return 0;
|
||||
}
|
||||
|
||||
BUG_ON(!create_pae_xen_mappings(pl3e));
|
||||
okay = create_pae_xen_mappings(pl3e);
|
||||
BUG_ON(!okay);
|
||||
|
||||
put_page_from_l3e(ol3e, pfn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
+2
-4
@@ -323,7 +323,7 @@ static u64 read_pit_count(void)
|
||||
return pit_counter64 + (u16)(pit_stamp - pit_read_counter());
|
||||
}
|
||||
|
||||
static int init_pit(void)
|
||||
static void init_pit(void)
|
||||
{
|
||||
read_platform_count = read_pit_count;
|
||||
|
||||
@@ -333,8 +333,6 @@ static int init_pit(void)
|
||||
|
||||
printk("Platform timer is %s PIT\n", freq_string(CLOCK_TICK_RATE));
|
||||
using_pit = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
@@ -563,7 +561,7 @@ static void platform_time_calibration(void)
|
||||
static void init_platform_timer(void)
|
||||
{
|
||||
if ( !init_cyclone() && !init_hpet() )
|
||||
BUG_ON(!init_pit());
|
||||
init_pit();
|
||||
}
|
||||
|
||||
|
||||
|
||||
+24
-1
@@ -65,6 +65,11 @@ void vmx_final_setup_guest(struct vcpu *v)
|
||||
|
||||
if ( v == v->domain->vcpu[0] )
|
||||
{
|
||||
v->domain->arch.vmx_platform.lapic_enable =
|
||||
v->arch.guest_context.user_regs.ecx;
|
||||
v->arch.guest_context.user_regs.ecx = 0;
|
||||
VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "lapic enable is %d.\n",
|
||||
v->domain->arch.vmx_platform.lapic_enable);
|
||||
/*
|
||||
* Required to do this once per domain
|
||||
* XXX todo: add a seperate function to do these.
|
||||
@@ -96,6 +101,10 @@ void vmx_relinquish_resources(struct vcpu *v)
|
||||
destroy_vmcs(&v->arch.arch_vmx);
|
||||
free_monitor_pagetable(v);
|
||||
rem_ac_timer(&v->domain->arch.vmx_platform.vmx_pit.pit_timer);
|
||||
if ( vmx_apic_support(v->domain) ) {
|
||||
rem_ac_timer( &(VLAPIC(v)->vlapic_timer) );
|
||||
xfree( VLAPIC(v) );
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __x86_64__
|
||||
@@ -442,7 +451,9 @@ static int vmx_do_page_fault(unsigned long va, struct cpu_user_regs *regs)
|
||||
|
||||
/* Use 1:1 page table to identify MMIO address space */
|
||||
if ( mmio_space(gpa) ){
|
||||
if (gpa >= 0xFEE00000) { /* workaround for local APIC */
|
||||
struct vcpu *v = current;
|
||||
/* No support for APIC */
|
||||
if (!vmx_apic_support(v->domain) && gpa >= 0xFEC00000) {
|
||||
u32 inst_len;
|
||||
__vmread(VM_EXIT_INSTRUCTION_LEN, &(inst_len));
|
||||
__update_guest_eip(inst_len);
|
||||
@@ -487,6 +498,7 @@ static void vmx_vmexit_do_cpuid(unsigned long input, struct cpu_user_regs *regs)
|
||||
{
|
||||
unsigned int eax, ebx, ecx, edx;
|
||||
unsigned long eip;
|
||||
struct vcpu *v = current;
|
||||
|
||||
__vmread(GUEST_RIP, &eip);
|
||||
|
||||
@@ -500,6 +512,9 @@ static void vmx_vmexit_do_cpuid(unsigned long input, struct cpu_user_regs *regs)
|
||||
cpuid(input, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
if (input == 1) {
|
||||
if ( vmx_apic_support(v->domain) &&
|
||||
!vlapic_global_enabled((VLAPIC(v))) )
|
||||
clear_bit(X86_FEATURE_APIC, &edx);
|
||||
#ifdef __i386__
|
||||
clear_bit(X86_FEATURE_PSE, &edx);
|
||||
clear_bit(X86_FEATURE_PAE, &edx);
|
||||
@@ -1441,6 +1456,7 @@ static int vmx_cr_access(unsigned long exit_qualification, struct cpu_user_regs
|
||||
static inline void vmx_do_msr_read(struct cpu_user_regs *regs)
|
||||
{
|
||||
u64 msr_content = 0;
|
||||
struct vcpu *v = current;
|
||||
|
||||
VMX_DBG_LOG(DBG_LEVEL_1, "vmx_do_msr_read: ecx=%lx, eax=%lx, edx=%lx",
|
||||
(unsigned long)regs->ecx, (unsigned long)regs->eax,
|
||||
@@ -1455,6 +1471,9 @@ static inline void vmx_do_msr_read(struct cpu_user_regs *regs)
|
||||
case MSR_IA32_SYSENTER_EIP:
|
||||
__vmread(GUEST_SYSENTER_EIP, &msr_content);
|
||||
break;
|
||||
case MSR_IA32_APICBASE:
|
||||
msr_content = VLAPIC(v) ? VLAPIC(v)->apic_base_msr : 0;
|
||||
break;
|
||||
default:
|
||||
if(long_mode_do_msr_read(regs))
|
||||
return;
|
||||
@@ -1474,6 +1493,7 @@ static inline void vmx_do_msr_read(struct cpu_user_regs *regs)
|
||||
static inline void vmx_do_msr_write(struct cpu_user_regs *regs)
|
||||
{
|
||||
u64 msr_content;
|
||||
struct vcpu *v = current;
|
||||
|
||||
VMX_DBG_LOG(DBG_LEVEL_1, "vmx_do_msr_write: ecx=%lx, eax=%lx, edx=%lx",
|
||||
(unsigned long)regs->ecx, (unsigned long)regs->eax,
|
||||
@@ -1491,6 +1511,9 @@ static inline void vmx_do_msr_write(struct cpu_user_regs *regs)
|
||||
case MSR_IA32_SYSENTER_EIP:
|
||||
__vmwrite(GUEST_SYSENTER_EIP, msr_content);
|
||||
break;
|
||||
case MSR_IA32_APICBASE:
|
||||
vlapic_msr_set(VLAPIC(v), msr_content);
|
||||
break;
|
||||
default:
|
||||
long_mode_do_msr_write(regs);
|
||||
break;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <asm/vmx_platform.h>
|
||||
#include <asm/vmx_virpit.h>
|
||||
#include <asm/vmx_intercept.h>
|
||||
#include <asm/vmx_vlapic.h>
|
||||
#include <public/io/ioreq.h>
|
||||
#include <xen/lib.h>
|
||||
#include <xen/sched.h>
|
||||
@@ -32,6 +33,123 @@
|
||||
|
||||
#ifdef CONFIG_VMX
|
||||
|
||||
struct vmx_mmio_handler vmx_mmio_handers[VMX_MMIO_HANDLER_NR] =
|
||||
{
|
||||
{
|
||||
.check_handler = vlapic_range,
|
||||
.read_handler = vlapic_read,
|
||||
.write_handler = vlapic_write
|
||||
}
|
||||
};
|
||||
|
||||
static inline void vmx_mmio_access(struct vcpu *v,
|
||||
ioreq_t *p,
|
||||
vmx_mmio_read_t read_handler,
|
||||
vmx_mmio_write_t write_handler)
|
||||
{
|
||||
ioreq_t *req;
|
||||
vcpu_iodata_t *vio = get_vio(v->domain, v->vcpu_id);
|
||||
unsigned int tmp1, tmp2;
|
||||
unsigned long data;
|
||||
|
||||
if (vio == NULL) {
|
||||
printk("vlapic_access: bad shared page\n");
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
|
||||
req = &vio->vp_ioreq;
|
||||
|
||||
switch (req->type) {
|
||||
case IOREQ_TYPE_COPY:
|
||||
{
|
||||
int sign = (req->df) ? -1 : 1, i;
|
||||
|
||||
if (!req->pdata_valid) {
|
||||
if (req->dir == IOREQ_READ){
|
||||
req->u.data = read_handler(v, req->addr, req->size);
|
||||
} else { /* req->dir != IOREQ_READ */
|
||||
write_handler(v, req->addr, req->size, req->u.data);
|
||||
}
|
||||
} else { /* !req->pdata_valid */
|
||||
if (req->dir == IOREQ_READ) {
|
||||
for (i = 0; i < req->count; i++) {
|
||||
data = read_handler(v,
|
||||
req->addr + (sign * i * req->size),
|
||||
req->size);
|
||||
vmx_copy(&data,
|
||||
(unsigned long)p->u.pdata + (sign * i * req->size),
|
||||
p->size,
|
||||
VMX_COPY_OUT);
|
||||
}
|
||||
} else { /* !req->dir == IOREQ_READ */
|
||||
for (i = 0; i < req->count; i++) {
|
||||
vmx_copy(&data,
|
||||
(unsigned long)p->u.pdata + (sign * i * req->size),
|
||||
p->size,
|
||||
VMX_COPY_IN);
|
||||
write_handler(v,
|
||||
req->addr + (sign * i * req->size),
|
||||
req->size, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case IOREQ_TYPE_AND:
|
||||
tmp1 = read_handler(v, req->addr, req->size);
|
||||
if (req->dir == IOREQ_WRITE) {
|
||||
tmp2 = tmp1 & (unsigned long) req->u.data;
|
||||
write_handler(v, req->addr, req->size, tmp2);
|
||||
}
|
||||
req->u.data = tmp1;
|
||||
break;
|
||||
|
||||
case IOREQ_TYPE_OR:
|
||||
tmp1 = read_handler(v, req->addr, req->size);
|
||||
if (req->dir == IOREQ_WRITE) {
|
||||
tmp2 = tmp1 | (unsigned long) req->u.data;
|
||||
write_handler(v, req->addr, req->size, tmp2);
|
||||
}
|
||||
req->u.data = tmp1;
|
||||
break;
|
||||
|
||||
case IOREQ_TYPE_XOR:
|
||||
tmp1 = read_handler(v, req->addr, req->size);
|
||||
if (req->dir == IOREQ_WRITE) {
|
||||
tmp2 = tmp1 ^ (unsigned long) req->u.data;
|
||||
write_handler(v, req->addr, req->size, tmp2);
|
||||
}
|
||||
req->u.data = tmp1;
|
||||
break;
|
||||
|
||||
default:
|
||||
printk("error ioreq type for local APIC %x\n", req->type);
|
||||
domain_crash_synchronous();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int vmx_mmio_intercept(ioreq_t *p)
|
||||
{
|
||||
struct vcpu *v = current;
|
||||
int i;
|
||||
struct vmx_mmio_handler *handler = vmx_mmio_handers;
|
||||
|
||||
/* XXX currently only APIC use intercept */
|
||||
if ( !vmx_apic_support(v->domain) )
|
||||
return 0;
|
||||
|
||||
for ( i = 0; i < VMX_MMIO_HANDLER_NR; i++ ) {
|
||||
if ( handler[i].check_handler(v, p->addr) ) {
|
||||
vmx_mmio_access(v, p,
|
||||
handler[i].read_handler, handler[i].write_handler);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the request is handled inside xen
|
||||
* return value: 0 --not handled; 1 --handled
|
||||
|
||||
+47
-71
@@ -36,9 +36,9 @@
|
||||
#include <asm/apic.h>
|
||||
#include <asm/shadow.h>
|
||||
|
||||
#include <asm/vmx_vlapic.h>
|
||||
#include <public/io/ioreq.h>
|
||||
#include <public/io/vmx_vpic.h>
|
||||
#include <public/io/vmx_vlapic.h>
|
||||
|
||||
#ifdef CONFIG_VMX
|
||||
#if defined (__i386__)
|
||||
@@ -732,48 +732,6 @@ void vmx_wait_io()
|
||||
} while(1);
|
||||
}
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
static inline int __fls(u32 word)
|
||||
{
|
||||
int bit;
|
||||
|
||||
__asm__("bsrl %1,%0"
|
||||
:"=r" (bit)
|
||||
:"rm" (word));
|
||||
return word ? bit : -1;
|
||||
}
|
||||
#else
|
||||
#define __fls(x) generic_fls(x)
|
||||
static __inline__ int generic_fls(u32 x)
|
||||
{
|
||||
int r = 31;
|
||||
|
||||
if (!x)
|
||||
return -1;
|
||||
if (!(x & 0xffff0000u)) {
|
||||
x <<= 16;
|
||||
r -= 16;
|
||||
}
|
||||
if (!(x & 0xff000000u)) {
|
||||
x <<= 8;
|
||||
r -= 8;
|
||||
}
|
||||
if (!(x & 0xf0000000u)) {
|
||||
x <<= 4;
|
||||
r -= 4;
|
||||
}
|
||||
if (!(x & 0xc0000000u)) {
|
||||
x <<= 2;
|
||||
r -= 2;
|
||||
}
|
||||
if (!(x & 0x80000000u)) {
|
||||
x <<= 1;
|
||||
r -= 1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Simple minded Local APIC priority implementation. Fix later */
|
||||
static __inline__ int find_highest_irq(u32 *pintr)
|
||||
{
|
||||
@@ -801,31 +759,31 @@ interrupt_post_injection(struct vcpu * v, int vector, int type)
|
||||
struct vmx_virpit *vpit = &(v->domain->arch.vmx_platform.vmx_pit);
|
||||
u64 drift;
|
||||
|
||||
if ( is_pit_irq(v, vector, type) ) {
|
||||
if ( !vpit->first_injected ) {
|
||||
vpit->first_injected = 1;
|
||||
vpit->pending_intr_nr = 0;
|
||||
} else {
|
||||
vpit->pending_intr_nr--;
|
||||
}
|
||||
vpit->inject_point = NOW();
|
||||
drift = vpit->period_cycles * vpit->pending_intr_nr;
|
||||
drift = v->arch.arch_vmx.tsc_offset - drift;
|
||||
__vmwrite(TSC_OFFSET, drift);
|
||||
|
||||
#if defined (__i386__)
|
||||
__vmwrite(TSC_OFFSET_HIGH, (drift >> 32));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case VLAPIC_DELIV_MODE_EXT:
|
||||
if ( is_pit_irq(v, vector) ) {
|
||||
if ( !vpit->first_injected ) {
|
||||
vpit->first_injected = 1;
|
||||
vpit->pending_intr_nr = 0;
|
||||
}
|
||||
else {
|
||||
vpit->pending_intr_nr--;
|
||||
}
|
||||
vpit->inject_point = NOW();
|
||||
drift = vpit->period_cycles * vpit->pending_intr_nr;
|
||||
drift = v->arch.arch_vmx.tsc_offset - drift;
|
||||
__vmwrite(TSC_OFFSET, drift);
|
||||
|
||||
#if defined (__i386__)
|
||||
__vmwrite(TSC_OFFSET_HIGH, (drift >> 32));
|
||||
#endif
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printk("Not support interrupt type\n");
|
||||
vlapic_post_injection(v, vector, type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -885,6 +843,24 @@ void vmx_pic_assist(struct vcpu *v)
|
||||
|
||||
}
|
||||
|
||||
int cpu_get_interrupt(struct vcpu *v, int *type)
|
||||
{
|
||||
int intno;
|
||||
struct vmx_virpic *s = &v->domain->arch.vmx_platform.vmx_pic;
|
||||
|
||||
if ( (intno = cpu_get_apic_interrupt(v, type)) != -1 ) {
|
||||
/* set irq request if a PIC irq is still pending */
|
||||
/* XXX: improve that */
|
||||
pic_update_irq(s);
|
||||
return intno;
|
||||
}
|
||||
/* read the irq from the PIC */
|
||||
if ( (intno = cpu_get_pic_interrupt(v, type)) != -1 )
|
||||
return intno;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
asmlinkage void vmx_intr_assist(void)
|
||||
{
|
||||
int intr_type = 0;
|
||||
@@ -902,11 +878,6 @@ asmlinkage void vmx_intr_assist(void)
|
||||
pic_set_irq(pic, 0, 1);
|
||||
}
|
||||
|
||||
if ( !plat->interrupt_request ) {
|
||||
disable_irq_window(cpu_exec_control);
|
||||
return;
|
||||
}
|
||||
|
||||
__vmread(VM_ENTRY_INTR_INFO_FIELD, &intr_fields);
|
||||
|
||||
if (intr_fields & INTR_INFO_VALID_MASK) {
|
||||
@@ -928,16 +899,21 @@ asmlinkage void vmx_intr_assist(void)
|
||||
enable_irq_window(cpu_exec_control);
|
||||
return;
|
||||
}
|
||||
plat->interrupt_request = 0;
|
||||
highest_vector = cpu_get_pic_interrupt(v, &intr_type);
|
||||
|
||||
highest_vector = cpu_get_interrupt(v, &intr_type);
|
||||
|
||||
if (highest_vector == -1) {
|
||||
disable_irq_window(cpu_exec_control);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (intr_type) {
|
||||
case VLAPIC_DELIV_MODE_EXT:
|
||||
case VLAPIC_DELIV_MODE_FIXED:
|
||||
case VLAPIC_DELIV_MODE_LPRI:
|
||||
vmx_inject_extint(v, highest_vector, VMX_INVALID_ERROR_CODE);
|
||||
TRACE_3D(TRC_VMX_INT, v->domain->domain_id, highest_vector, 0);
|
||||
break;
|
||||
case VLAPIC_DELIV_MODE_FIXED:
|
||||
case VLAPIC_DELIV_MODE_LPRI:
|
||||
case VLAPIC_DELIV_MODE_SMI:
|
||||
case VLAPIC_DELIV_MODE_NMI:
|
||||
case VLAPIC_DELIV_MODE_INIT:
|
||||
|
||||
@@ -0,0 +1,997 @@
|
||||
/*
|
||||
* vmx_vlapic.c: virtualize LAPIC for VMX vcpus.
|
||||
* Copyright (c) 2004, Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
* Place - Suite 330, Boston, MA 02111-1307 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <xen/config.h>
|
||||
#include <xen/types.h>
|
||||
#include <xen/mm.h>
|
||||
#include <xen/xmalloc.h>
|
||||
#include <asm/shadow.h>
|
||||
#include <asm/page.h>
|
||||
#include <xen/event.h>
|
||||
#include <xen/trace.h>
|
||||
#include <asm/vmx.h>
|
||||
#include <asm/vmx_platform.h>
|
||||
#include <asm/vmx_vlapic.h>
|
||||
|
||||
#include <xen/lib.h>
|
||||
#include <xen/sched.h>
|
||||
#include <asm/current.h>
|
||||
#include <public/io/ioreq.h>
|
||||
|
||||
#ifdef CONFIG_VMX
|
||||
|
||||
/* XXX remove this definition after GFW enabled */
|
||||
#define VLAPIC_NO_BIOS
|
||||
|
||||
extern unsigned int get_apic_bus_scale(void);
|
||||
|
||||
static unsigned int vlapic_lvt_mask[VLAPIC_LVT_NUM] =
|
||||
{
|
||||
0x310ff, 0x117ff, 0x117ff, 0x1f7ff, 0x1f7ff, 0x117ff
|
||||
};
|
||||
|
||||
int vlapic_find_highest_irr(struct vlapic *vlapic)
|
||||
{
|
||||
int result;
|
||||
|
||||
result = find_highest_bit((uint32_t *)&vlapic->irr[0], INTR_LEN_32);
|
||||
|
||||
if (result != -1 && result < 16) {
|
||||
printk("VLAPIC: irr on reserved bits %d\n ", result);
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline int vmx_apic_support(struct domain *d)
|
||||
{
|
||||
return d->arch.vmx_platform.lapic_enable;
|
||||
}
|
||||
|
||||
int vlapic_find_highest_isr(struct vlapic *vlapic)
|
||||
{
|
||||
int result;
|
||||
|
||||
result = find_highest_bit((uint32_t *)&vlapic->isr[0], INTR_LEN_32);
|
||||
|
||||
if (result != -1 && result < 16) {
|
||||
int i = 0;
|
||||
printk("VLAPIC: isr on reserved bits %d, isr is\n ", result);
|
||||
for (i = 0; i < INTR_LEN_32; i += 2)
|
||||
printk("%d: 0x%08x%08x\n", i, vlapic->isr[i], vlapic->isr[i+1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t vlapic_update_ppr(struct vlapic *vlapic)
|
||||
{
|
||||
uint32_t tpr, isrv, ppr;
|
||||
int isr;
|
||||
|
||||
tpr = (vlapic->task_priority >> 4) & 0xf; /* we want 7:4 */
|
||||
|
||||
isr = vlapic_find_highest_isr(vlapic);
|
||||
if (isr != -1)
|
||||
isrv = (isr >> 4) & 0xf; /* ditto */
|
||||
else
|
||||
isrv = 0;
|
||||
|
||||
if (tpr >= isrv)
|
||||
ppr = vlapic->task_priority & 0xff;
|
||||
else
|
||||
ppr = isrv << 4; /* low 4 bits of PPR have to be cleared */
|
||||
|
||||
vlapic->processor_priority = ppr;
|
||||
|
||||
VMX_DBG_LOG(DBG_LEVEL_VLAPIC_INTERRUPT,
|
||||
"vlapic_update_ppr: vlapic %p ppr %x isr %x isrv %x",
|
||||
vlapic, ppr, isr, isrv);
|
||||
|
||||
return ppr;
|
||||
}
|
||||
|
||||
/* This only for fixed delivery mode */
|
||||
int vlapic_match_dest(struct vlapic *target, struct vlapic *source,
|
||||
int short_hand, int dest, int dest_mode,
|
||||
int delivery_mode)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_match_dest: "
|
||||
"target %p source %p dest %x dest_mode %x short_hand %x "
|
||||
"delivery_mode %x",
|
||||
target, source, dest, dest_mode, short_hand, delivery_mode);
|
||||
|
||||
switch (short_hand) {
|
||||
case VLAPIC_NO_SHORTHAND:
|
||||
if (!dest_mode) { /* Physical */
|
||||
result = (target->id == dest);
|
||||
} else { /* Logical */
|
||||
if (((target->dest_format >> 28) & 0xf) == 0xf) { /* Flat mode */
|
||||
result = (target->logical_dest >> 24) & dest;
|
||||
} else {
|
||||
if ((delivery_mode == VLAPIC_DELIV_MODE_LPRI) &&
|
||||
(dest == 0xff)) {
|
||||
/* What shall we do now? */
|
||||
printk("Broadcast IPI with lowest priority "
|
||||
"delivery mode\n");
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
result = (target->logical_dest == (dest & 0xf)) ?
|
||||
((target->logical_dest >> 4) & (dest >> 4)) : 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case VLAPIC_SHORTHAND_SELF:
|
||||
if (target == source)
|
||||
result = 1;
|
||||
break;
|
||||
|
||||
case VLAPIC_SHORTHAND_INCLUDE_SELF:
|
||||
result = 1;
|
||||
break;
|
||||
|
||||
case VLAPIC_SHORTHAND_EXCLUDE_SELF:
|
||||
if (target != source)
|
||||
result = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a pending IRQ into lapic.
|
||||
* Return 1 if successfully added and 0 if discarded.
|
||||
*/
|
||||
int vlapic_accept_irq(struct vlapic *vlapic, int delivery_mode,
|
||||
int vector, int level, int trig_mode)
|
||||
{
|
||||
int result = 1;
|
||||
|
||||
switch (delivery_mode) {
|
||||
case VLAPIC_DELIV_MODE_FIXED:
|
||||
case VLAPIC_DELIV_MODE_LPRI:
|
||||
/* FIXME add logic for vcpu on reset */
|
||||
if (!vlapic->vcpu || !vlapic_enabled(vlapic))
|
||||
return 0;
|
||||
|
||||
if (test_and_set_bit(vector, &vlapic->irr[0])) {
|
||||
printk("<vlapic_accept_irq>"
|
||||
"level trig mode repeatedly for vector %d\n", vector);
|
||||
result = 0;
|
||||
} else {
|
||||
if (level) {
|
||||
printk("<vlapic_accept_irq> level trig mode for vector %d\n", vector);
|
||||
set_bit(vector, &vlapic->tmr[0]);
|
||||
}
|
||||
}
|
||||
evtchn_set_pending(vlapic->vcpu, iopacket_port(vlapic->domain));
|
||||
break;
|
||||
|
||||
case VLAPIC_DELIV_MODE_RESERVED:
|
||||
printk("Ignore deliver mode 3 in vlapic_accept_irq\n");
|
||||
break;
|
||||
|
||||
case VLAPIC_DELIV_MODE_SMI:
|
||||
case VLAPIC_DELIV_MODE_NMI:
|
||||
/* Fixme */
|
||||
printk("TODO: for guest SMI/NMI\n");
|
||||
break;
|
||||
|
||||
case VLAPIC_DELIV_MODE_INIT:
|
||||
if (!level && trig_mode == 1) { //Deassert
|
||||
printk("This vmx_vlapic is for P4, no work for De-assert init\n");
|
||||
} else {
|
||||
/* FIXME How to check the situation after vcpu reset? */
|
||||
vlapic->init_sipi_sipi_state = VLAPIC_INIT_SIPI_SIPI_STATE_WAIT_SIPI;
|
||||
if (vlapic->vcpu) {
|
||||
vcpu_pause(vlapic->vcpu);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case VLAPIC_DELIV_MODE_STARTUP:
|
||||
if (vlapic->init_sipi_sipi_state != VLAPIC_INIT_SIPI_SIPI_STATE_WAIT_SIPI)
|
||||
break;
|
||||
vlapic->init_sipi_sipi_state = VLAPIC_INIT_SIPI_SIPI_STATE_NORM;
|
||||
if (!vlapic->vcpu) {
|
||||
/* XXX Call vmx_bringup_ap here */
|
||||
result = 0;
|
||||
}else{
|
||||
//vmx_vcpu_reset(vlapic->vcpu);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printk("TODO: not support interrup type %x\n", delivery_mode);
|
||||
domain_crash_synchronous();
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
/*
|
||||
This function is used by both ioapic and local APIC
|
||||
The bitmap is for vcpu_id
|
||||
*/
|
||||
struct vlapic* apic_round_robin(struct domain *d,
|
||||
uint8_t dest_mode,
|
||||
uint8_t vector,
|
||||
uint32_t bitmap)
|
||||
{
|
||||
int next, old;
|
||||
struct vlapic* target = NULL;
|
||||
|
||||
if (dest_mode == 0) { //Physical mode
|
||||
printk("<apic_round_robin> lowest priority for physical mode\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!bitmap) {
|
||||
printk("<apic_round_robin> no bit on bitmap\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
spin_lock(&d->arch.vmx_platform.round_robin_lock);
|
||||
|
||||
old = next = d->arch.vmx_platform.round_info[vector];
|
||||
|
||||
next++;
|
||||
if (next == MAX_VIRT_CPUS || !d->vcpu[next])
|
||||
next = 0;
|
||||
|
||||
do {
|
||||
/* the vcpu array is arranged according to vcpu_id */
|
||||
if (test_bit(next, &bitmap)) {
|
||||
target = d->vcpu[next]->arch.arch_vmx.vlapic;
|
||||
if (!vlapic_enabled(target)) {
|
||||
printk("warning: targe round robin local apic disabled\n");
|
||||
/* XXX should we domain crash?? Or should we return NULL */
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
next ++;
|
||||
if (next == MAX_VIRT_CPUS || !d->vcpu[next])
|
||||
next = 0;
|
||||
}while(next != old);
|
||||
|
||||
d->arch.vmx_platform.round_info[vector] = next;
|
||||
spin_unlock(&d->arch.vmx_platform.round_robin_lock);
|
||||
return target;
|
||||
}
|
||||
|
||||
void
|
||||
vlapic_EOI_set(struct vlapic *vlapic)
|
||||
{
|
||||
int vector = vlapic_find_highest_isr(vlapic);
|
||||
|
||||
/* Not every write EOI will has correpsoning ISR,
|
||||
one example is when Kernel check timer on setup_IO_APIC */
|
||||
if (vector == -1) {
|
||||
return ;
|
||||
}
|
||||
|
||||
vlapic_clear_isr(vlapic, vector);
|
||||
vlapic_update_ppr(vlapic);
|
||||
}
|
||||
|
||||
int vlapic_check_vector(struct vlapic *vlapic,
|
||||
unsigned char dm, int vector)
|
||||
{
|
||||
if ((dm == VLAPIC_DELIV_MODE_FIXED) && (vector < 16)) {
|
||||
vlapic->err_status |= 0x40;
|
||||
vlapic_accept_irq(vlapic, VLAPIC_DELIV_MODE_FIXED,
|
||||
vlapic_lvt_vector(vlapic, VLAPIC_LVT_ERROR), 0, 0);
|
||||
printk("<vlapic_check_vector>: check fail\n");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void vlapic_ipi(struct vlapic *vlapic)
|
||||
{
|
||||
unsigned int dest = (vlapic->icr_high >> 24) & 0xff;
|
||||
unsigned int short_hand = (vlapic->icr_low >> 18) & 3;
|
||||
unsigned int trig_mode = (vlapic->icr_low >> 15) & 1;
|
||||
unsigned int level = (vlapic->icr_low >> 14) & 1;
|
||||
unsigned int dest_mode = (vlapic->icr_low >> 11) & 1;
|
||||
unsigned int delivery_mode = (vlapic->icr_low >> 8) & 7;
|
||||
unsigned int vector = (vlapic->icr_low & 0xff);
|
||||
|
||||
struct vlapic *target;
|
||||
struct vcpu *v = NULL;
|
||||
int result = 0;
|
||||
uint32_t lpr_map;
|
||||
|
||||
VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_ipi: "
|
||||
"icr_high %x icr_low %x "
|
||||
"short_hand %x dest %x trig_mode %x level %x "
|
||||
"dest_mode %x delivery_mode %x vector %x",
|
||||
vlapic->icr_high, vlapic->icr_low,
|
||||
short_hand, dest, trig_mode, level, dest_mode,
|
||||
delivery_mode, vector);
|
||||
|
||||
for_each_vcpu ( vlapic->domain, v ) {
|
||||
target = VLAPIC(v);
|
||||
if (vlapic_match_dest(target, vlapic, short_hand,
|
||||
dest, dest_mode, delivery_mode)) {
|
||||
if (delivery_mode == VLAPIC_DELIV_MODE_LPRI) {
|
||||
set_bit(v->vcpu_id, &lpr_map);
|
||||
}else
|
||||
result = vlapic_accept_irq(target, delivery_mode,
|
||||
vector, level, trig_mode);
|
||||
}
|
||||
}
|
||||
|
||||
if (delivery_mode == VLAPIC_DELIV_MODE_LPRI) {
|
||||
extern struct vlapic*
|
||||
apic_round_robin(struct domain *d,
|
||||
uint8_t dest_mode, uint8_t vector, uint32_t bitmap);
|
||||
|
||||
v = vlapic->vcpu;
|
||||
target = apic_round_robin(v->domain, dest_mode, vector, lpr_map);
|
||||
|
||||
if (target)
|
||||
vlapic_accept_irq(target, delivery_mode,
|
||||
vector, level, trig_mode);
|
||||
}
|
||||
}
|
||||
|
||||
void vlapic_begin_timer(struct vlapic *vlapic)
|
||||
{
|
||||
s_time_t cur = NOW(), offset;
|
||||
|
||||
offset = vlapic->timer_current *
|
||||
(262144 / get_apic_bus_scale()) * vlapic->timer_divide_counter;
|
||||
vlapic->vlapic_timer.expires = cur + offset;
|
||||
|
||||
set_ac_timer(&(vlapic->vlapic_timer), vlapic->vlapic_timer.expires );
|
||||
|
||||
VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_begin_timer: "
|
||||
"bus_scale %x now %08x%08x expire %08x%08x "
|
||||
"offset %08x%08x current %x",
|
||||
get_apic_bus_scale(), (uint32_t)(cur >> 32), (uint32_t)cur,
|
||||
(uint32_t)(vlapic->vlapic_timer.expires >> 32),
|
||||
(uint32_t) vlapic->vlapic_timer.expires,
|
||||
(uint32_t)(offset >> 32), (uint32_t)offset,
|
||||
vlapic->timer_current);
|
||||
}
|
||||
|
||||
void vlapic_read_aligned(struct vlapic *vlapic, unsigned int offset,
|
||||
unsigned int len, unsigned int *result)
|
||||
{
|
||||
if (len != 4) {
|
||||
VMX_DBG_LOG(DBG_LEVEL_VLAPIC,
|
||||
"local apic read with len=%d (should be 4)", len);
|
||||
}
|
||||
|
||||
*result = 0;
|
||||
|
||||
switch (offset) {
|
||||
case APIC_ID:
|
||||
*result = (vlapic->id) << 24;
|
||||
break;
|
||||
|
||||
case APIC_LVR:
|
||||
*result = vlapic->version;
|
||||
break;
|
||||
|
||||
case APIC_TASKPRI:
|
||||
*result = vlapic->task_priority;
|
||||
break;
|
||||
|
||||
case APIC_ARBPRI:
|
||||
printk("Access local APIC ARBPRI register which is for P6\n");
|
||||
break;
|
||||
|
||||
case APIC_PROCPRI:
|
||||
*result = vlapic->processor_priority;
|
||||
break;
|
||||
|
||||
case APIC_EOI: /* EOI is write only */
|
||||
break;
|
||||
|
||||
case APIC_LDR:
|
||||
*result = vlapic->logical_dest;
|
||||
break;
|
||||
|
||||
case APIC_DFR:
|
||||
*result = vlapic->dest_format;
|
||||
break;
|
||||
|
||||
case APIC_SPIV:
|
||||
*result = vlapic->spurious_vec;
|
||||
break;
|
||||
|
||||
case APIC_ISR:
|
||||
case 0x110:
|
||||
case 0x120:
|
||||
case 0x130:
|
||||
case 0x140:
|
||||
case 0x150:
|
||||
case 0x160:
|
||||
case 0x170:
|
||||
*result = vlapic->isr[(offset - APIC_ISR) >> 4];
|
||||
break;
|
||||
|
||||
case APIC_TMR:
|
||||
case 0x190:
|
||||
case 0x1a0:
|
||||
case 0x1b0:
|
||||
case 0x1c0:
|
||||
case 0x1d0:
|
||||
case 0x1e0:
|
||||
case 0x1f0:
|
||||
*result = vlapic->tmr[(offset - APIC_TMR) >> 4];
|
||||
break;
|
||||
|
||||
case APIC_IRR:
|
||||
case 0x210:
|
||||
case 0x220:
|
||||
case 0x230:
|
||||
case 0x240:
|
||||
case 0x250:
|
||||
case 0x260:
|
||||
case 0x270:
|
||||
*result = vlapic->irr[(offset - APIC_IRR) >> 4];
|
||||
break;
|
||||
|
||||
case APIC_ESR:
|
||||
if (vlapic->err_write_count)
|
||||
*result = vlapic->err_status;
|
||||
break;
|
||||
|
||||
case APIC_ICR:
|
||||
*result = vlapic->icr_low;
|
||||
break;
|
||||
|
||||
case APIC_ICR2:
|
||||
*result = vlapic->icr_high;
|
||||
break;
|
||||
|
||||
case APIC_LVTT: /* LVT Timer Reg */
|
||||
case APIC_LVTTHMR: /* LVT Thermal Monitor */
|
||||
case APIC_LVTPC: /* LVT Performance Counter */
|
||||
case APIC_LVT0: /* LVT LINT0 Reg */
|
||||
case APIC_LVT1: /* LVT Lint1 Reg */
|
||||
case APIC_LVTERR: /* LVT Error Reg */
|
||||
*result = vlapic->lvt[(offset - APIC_LVTT) >> 4];
|
||||
break;
|
||||
|
||||
case APIC_TMICT:
|
||||
*result = vlapic->timer_initial;
|
||||
break;
|
||||
|
||||
case APIC_TMCCT: //Timer CCR
|
||||
{
|
||||
uint32_t counter;
|
||||
s_time_t passed, cur = NOW();
|
||||
|
||||
if (cur <= vlapic->timer_current_update) {
|
||||
passed = ~0x0LL - vlapic->timer_current_update + cur;
|
||||
VMX_DBG_LOG(DBG_LEVEL_VLAPIC,"time elapsed");
|
||||
}else
|
||||
passed = cur - vlapic->timer_current_update;
|
||||
|
||||
counter = (passed * get_apic_bus_scale()) / (262144* vlapic->timer_divide_counter);
|
||||
if (vlapic->timer_current > counter)
|
||||
*result = vlapic->timer_current - counter;
|
||||
else {
|
||||
if (!vlapic_lvt_timer_period(vlapic))
|
||||
*result = 0;
|
||||
//FIXME should we add interrupt here?
|
||||
else
|
||||
//*result = counter % vlapic->timer_initial;
|
||||
*result = vlapic->timer_initial - (counter - vlapic->timer_current);
|
||||
}
|
||||
vlapic->timer_current = *result;
|
||||
vlapic->timer_current_update = NOW();
|
||||
|
||||
VMX_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
|
||||
"initial %x timer current %x "
|
||||
"update %08x%08x cur %08x%08x offset %d",
|
||||
vlapic->timer_initial, vlapic->timer_current,
|
||||
(uint32_t)(vlapic->timer_current_update >> 32),
|
||||
(uint32_t)vlapic->timer_current_update ,
|
||||
(uint32_t)(cur >> 32), (uint32_t)cur, counter);
|
||||
}
|
||||
break;
|
||||
|
||||
case APIC_TDCR:
|
||||
*result = vlapic->timer_divconf;
|
||||
break;
|
||||
|
||||
default:
|
||||
printk("Read local APIC address %x not implemented\n",offset);
|
||||
*result = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long vlapic_read(struct vcpu *v, unsigned long address,
|
||||
unsigned long len)
|
||||
{
|
||||
unsigned int alignment;
|
||||
unsigned int tmp;
|
||||
unsigned long result;
|
||||
struct vlapic *vlapic = VLAPIC(v);
|
||||
unsigned int offset = address - vlapic->base_address;
|
||||
|
||||
if ( len != 4) {
|
||||
/* some bugs on kernel cause read this with byte*/
|
||||
printk("Local APIC read with len = %lx, should be 4 instead\n", len);
|
||||
}
|
||||
|
||||
alignment = offset & 0x3;
|
||||
|
||||
vlapic_read_aligned(vlapic, offset & ~0x3, 4, &tmp);
|
||||
switch (len) {
|
||||
case 1:
|
||||
result = *((unsigned char *)&tmp + alignment);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
result = *(unsigned short *)((unsigned char *)&tmp + alignment);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
result = *(unsigned int *)((unsigned char *)&tmp + alignment);
|
||||
break;
|
||||
|
||||
default:
|
||||
printk("Local APIC read with len = %lx, should be 4 instead\n", len);
|
||||
domain_crash_synchronous();
|
||||
break;
|
||||
}
|
||||
|
||||
VMX_DBG_LOG(DBG_LEVEL_VLAPIC,
|
||||
"vlapic_read offset %x with length %lx and the result is %lx",
|
||||
offset, len, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned long vlapic_write(struct vcpu *v, unsigned long address,
|
||||
unsigned long len, unsigned long val)
|
||||
{
|
||||
struct vlapic *vlapic = VLAPIC(v);
|
||||
unsigned int offset = address - vlapic->base_address;
|
||||
|
||||
if (offset != 0xb0)
|
||||
VMX_DBG_LOG(DBG_LEVEL_VLAPIC,
|
||||
"vlapic_write offset %x with length %lx source %lx",
|
||||
offset, len, val);
|
||||
|
||||
/*
|
||||
* According to IA 32 Manual, all resgiters should be accessed with
|
||||
* 32 bits alignment.
|
||||
*/
|
||||
if (len != 4) {
|
||||
unsigned int tmp;
|
||||
unsigned char alignment;
|
||||
|
||||
/* Some kernel do will access with byte/word alignment*/
|
||||
printk("Notice: Local APIC write with len = %lx\n",len);
|
||||
alignment = offset & 0x3;
|
||||
tmp = vlapic_read(v, offset & (~0x3), 4);
|
||||
switch (len) {
|
||||
case 1:
|
||||
/* XXX the saddr is a tmp variable from caller, so should be ok
|
||||
But we should still change the following ref to val to
|
||||
local variable later */
|
||||
val = (tmp & ~(0xff << alignment)) |
|
||||
((val & 0xff) << alignment);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (alignment != 0x0 && alignment != 0x2) {
|
||||
printk("alignment error for vlapic with len == 2\n");
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
|
||||
val = (tmp & ~(0xffff << alignment)) |
|
||||
((val & 0xffff) << alignment);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
/* will it happen? */
|
||||
printk("vlapic_write with len = 3 !!!\n");
|
||||
domain_crash_synchronous();
|
||||
break;
|
||||
|
||||
default:
|
||||
printk("Local APIC write with len = %lx, should be 4 instead\n", len);
|
||||
domain_crash_synchronous();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
offset &= 0xff0;
|
||||
|
||||
switch (offset) {
|
||||
case APIC_ID: /* Local APIC ID */
|
||||
vlapic->id = ((val) >> 24) & VAPIC_ID_MASK;
|
||||
break;
|
||||
|
||||
case APIC_TASKPRI:
|
||||
vlapic->task_priority = val & 0xff;
|
||||
vlapic_update_ppr(vlapic);
|
||||
break;
|
||||
|
||||
case APIC_EOI:
|
||||
vlapic_EOI_set(vlapic);
|
||||
break;
|
||||
|
||||
case APIC_LDR:
|
||||
vlapic->logical_dest = val & VAPIC_LDR_MASK;
|
||||
break;
|
||||
|
||||
case APIC_DFR:
|
||||
vlapic->dest_format = val ;
|
||||
break;
|
||||
|
||||
case APIC_SPIV:
|
||||
vlapic->spurious_vec = val & 0x1ff;
|
||||
if (!(vlapic->spurious_vec & 0x100)) {
|
||||
int i = 0;
|
||||
for (i=0; i < VLAPIC_LVT_NUM; i++)
|
||||
vlapic->lvt[i] |= 0x10000;
|
||||
vlapic->status |= VLAPIC_SOFTWARE_DISABLE_MASK;
|
||||
}
|
||||
else
|
||||
vlapic->status &= ~VLAPIC_SOFTWARE_DISABLE_MASK;
|
||||
break;
|
||||
|
||||
case APIC_ESR:
|
||||
vlapic->err_write_count = !vlapic->err_write_count;
|
||||
if (!vlapic->err_write_count)
|
||||
vlapic->err_status = 0;
|
||||
break;
|
||||
|
||||
case APIC_ICR:
|
||||
/* No delay here, so we always clear the pending bit*/
|
||||
vlapic->icr_low = val & ~(1 << 12);
|
||||
vlapic_ipi(vlapic);
|
||||
break;
|
||||
|
||||
case APIC_ICR2:
|
||||
vlapic->icr_high = val & 0xff000000;
|
||||
break;
|
||||
|
||||
case APIC_LVTT: // LVT Timer Reg
|
||||
case APIC_LVTTHMR: // LVT Thermal Monitor
|
||||
case APIC_LVTPC: // LVT Performance Counter
|
||||
case APIC_LVT0: // LVT LINT0 Reg
|
||||
case APIC_LVT1: // LVT Lint1 Reg
|
||||
case APIC_LVTERR: // LVT Error Reg
|
||||
{
|
||||
int vt = (offset - APIC_LVTT) >> 4;
|
||||
|
||||
vlapic->lvt[vt] = val & vlapic_lvt_mask[vt];
|
||||
if (vlapic->status & VLAPIC_SOFTWARE_DISABLE_MASK)
|
||||
vlapic->lvt[vt] |= VLAPIC_LVT_BIT_MASK;
|
||||
|
||||
/* On hardware, when write vector less than 0x20 will error */
|
||||
vlapic_check_vector(vlapic, vlapic_lvt_dm(vlapic->lvt[vt]),
|
||||
vlapic_lvt_vector(vlapic, vt));
|
||||
|
||||
if (!vlapic->vcpu_id && (offset == APIC_LVT0)) {
|
||||
if ((vlapic->lvt[VLAPIC_LVT_LINT0] & VLAPIC_LVT_BIT_DELIMOD)
|
||||
== 0x700) {
|
||||
if (!(vlapic->lvt[VLAPIC_LVT_LINT0] & VLAPIC_LVT_BIT_MASK)) {
|
||||
set_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
|
||||
}else
|
||||
clear_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
|
||||
}
|
||||
else
|
||||
clear_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case APIC_TMICT:
|
||||
if (vlapic_timer_active(vlapic))
|
||||
rem_ac_timer(&(vlapic->vlapic_timer));
|
||||
|
||||
vlapic->timer_initial = val;
|
||||
vlapic->timer_current = val;
|
||||
vlapic->timer_current_update = NOW();
|
||||
|
||||
VMX_DBG_LOG(DBG_LEVEL_VLAPIC,
|
||||
"timer_init %x timer_current %x timer_current_update %08x%08x",
|
||||
vlapic->timer_initial, vlapic->timer_current, (uint32_t)(vlapic->timer_current_update>>32), (uint32_t)vlapic->timer_current_update);
|
||||
vlapic_begin_timer(vlapic);
|
||||
break;
|
||||
|
||||
case APIC_TDCR:
|
||||
{
|
||||
//FIXME clean this code
|
||||
unsigned char tmp1,tmp2;
|
||||
tmp1 = (val & 0xf);
|
||||
tmp2 = ((tmp1 & 0x3 )|((tmp1 & 0x8) >>1)) + 1;
|
||||
vlapic->timer_divide_counter = 0x1<<tmp2;
|
||||
|
||||
VMX_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
|
||||
"timer divider is 0x%x",
|
||||
vlapic->timer_divide_counter);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
printk("Local APIC Write to read-only register\n");
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int vlapic_range(struct vcpu *v, unsigned long addr)
|
||||
{
|
||||
struct vlapic *vlapic = VLAPIC(v);
|
||||
|
||||
if (vlapic_global_enabled(vlapic) &&
|
||||
(addr >= vlapic->base_address) &&
|
||||
(addr <= (vlapic->base_address + VLOCAL_APIC_MEM_LENGTH)))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vlapic_msr_set(struct vlapic *vlapic, uint64_t value)
|
||||
{
|
||||
/* When apic disabled */
|
||||
if (!vlapic)
|
||||
return;
|
||||
|
||||
if (vlapic->vcpu_id)
|
||||
value &= ~MSR_IA32_APICBASE_BSP;
|
||||
|
||||
vlapic->apic_base_msr = value;
|
||||
vlapic->base_address = vlapic_get_base_address(vlapic);
|
||||
|
||||
if (!(value & 0x800))
|
||||
set_bit(_VLAPIC_GLOB_DISABLE, &vlapic->status );
|
||||
|
||||
VMX_DBG_LOG(DBG_LEVEL_VLAPIC,
|
||||
"apic base msr = 0x%08x%08x,\nbase address = 0x%lx",
|
||||
(uint32_t)(vlapic->apic_base_msr >> 32),
|
||||
(uint32_t)vlapic->apic_base_msr,
|
||||
vlapic->base_address);
|
||||
}
|
||||
|
||||
static inline int vlapic_get_init_id(struct vcpu *v)
|
||||
{
|
||||
return v->vcpu_id;
|
||||
}
|
||||
|
||||
void vlapic_timer_fn(void *data)
|
||||
{
|
||||
struct vlapic *vlapic;
|
||||
|
||||
vlapic = data;
|
||||
if (!vlapic_enabled(vlapic)) return;
|
||||
|
||||
vlapic->timer_current_update = NOW();
|
||||
|
||||
if (vlapic_lvt_timer_enabled(vlapic)) {
|
||||
if (!vlapic_irr_status(vlapic,
|
||||
vlapic_lvt_vector(vlapic, VLAPIC_LVT_TIMER))) {
|
||||
test_and_set_bit(vlapic_lvt_vector(vlapic, VLAPIC_LVT_TIMER),
|
||||
&vlapic->irr[0]);
|
||||
}
|
||||
else
|
||||
vlapic->intr_pending_count[vlapic_lvt_vector(vlapic, VLAPIC_LVT_TIMER)]++;
|
||||
}
|
||||
|
||||
vlapic->timer_current_update = NOW();
|
||||
if (vlapic_lvt_timer_period(vlapic)) {
|
||||
s_time_t offset;
|
||||
|
||||
vlapic->timer_current = vlapic->timer_initial;
|
||||
offset = vlapic->timer_current * (262144/get_apic_bus_scale()) * vlapic->timer_divide_counter;
|
||||
vlapic->vlapic_timer.expires = NOW() + offset;
|
||||
set_ac_timer(&(vlapic->vlapic_timer), vlapic->vlapic_timer.expires);
|
||||
}else {
|
||||
vlapic->timer_current = 0;
|
||||
}
|
||||
|
||||
VMX_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
|
||||
"vlapic_timer_fn: now: %08x%08x expire %08x%08x init %x current %x",
|
||||
(uint32_t)(NOW() >> 32),(uint32_t)NOW(),
|
||||
(uint32_t)(vlapic->vlapic_timer.expires >> 32),
|
||||
(uint32_t)vlapic->vlapic_timer.expires,
|
||||
vlapic->timer_initial,vlapic->timer_current);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int
|
||||
vlapic_check_direct_intr(struct vcpu *v, int * mode)
|
||||
{
|
||||
struct vlapic *vlapic = VLAPIC(v);
|
||||
int type;
|
||||
|
||||
type = __fls(vlapic->direct_intr.deliver_mode);
|
||||
if (type == -1)
|
||||
return -1;
|
||||
|
||||
*mode = type;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
vlapic_accept_pic_intr(struct vcpu *v)
|
||||
{
|
||||
struct vlapic *vlapic = VLAPIC(v);
|
||||
|
||||
return vlapic ? test_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status) : 1;
|
||||
}
|
||||
|
||||
int cpu_get_apic_interrupt(struct vcpu* v, int *mode)
|
||||
{
|
||||
struct vlapic *vlapic = VLAPIC(v);
|
||||
|
||||
if (vlapic && vlapic_enabled(vlapic)) {
|
||||
int highest_irr = vlapic_find_highest_irr(vlapic);
|
||||
|
||||
if (highest_irr != -1 && highest_irr >= vlapic->processor_priority) {
|
||||
if (highest_irr < 0x10) {
|
||||
vlapic->err_status |= 0x20;
|
||||
/* XXX What will happen if this vector illegal stil */
|
||||
VMX_DBG_LOG(DBG_LEVEL_VLAPIC,
|
||||
"vmx_intr_assist: illegal vector number %x err_status %x",
|
||||
highest_irr, vlapic_lvt_vector(vlapic, VLAPIC_LVT_ERROR));
|
||||
|
||||
set_bit(vlapic_lvt_vector(vlapic, VLAPIC_LVT_ERROR), &vlapic->irr[0]);
|
||||
highest_irr = vlapic_lvt_vector(vlapic, VLAPIC_LVT_ERROR);
|
||||
}
|
||||
|
||||
*mode = VLAPIC_DELIV_MODE_FIXED;
|
||||
return highest_irr;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void vlapic_post_injection(struct vcpu *v, int vector, int deliver_mode) {
|
||||
struct vlapic *vlapic = VLAPIC(v);
|
||||
|
||||
if (!vlapic)
|
||||
return;
|
||||
|
||||
switch (deliver_mode) {
|
||||
case VLAPIC_DELIV_MODE_FIXED:
|
||||
case VLAPIC_DELIV_MODE_LPRI:
|
||||
vlapic_set_isr(vlapic, vector);
|
||||
vlapic_clear_irr(vlapic, vector);
|
||||
vlapic_update_ppr(vlapic);
|
||||
|
||||
if (vector == vlapic_lvt_vector(vlapic, VLAPIC_LVT_TIMER)) {
|
||||
vlapic->intr_pending_count[vector]--;
|
||||
if (vlapic->intr_pending_count[vector] > 0)
|
||||
test_and_set_bit(vlapic_lvt_vector(vlapic, VLAPIC_LVT_TIMER),
|
||||
&vlapic->irr[0]);
|
||||
}
|
||||
|
||||
break;
|
||||
/*XXX deal with these later */
|
||||
|
||||
case VLAPIC_DELIV_MODE_RESERVED:
|
||||
printk("Ignore deliver mode 3 in vlapic_post_injection\n");
|
||||
break;
|
||||
|
||||
case VLAPIC_DELIV_MODE_SMI:
|
||||
case VLAPIC_DELIV_MODE_NMI:
|
||||
case VLAPIC_DELIV_MODE_INIT:
|
||||
case VLAPIC_DELIV_MODE_STARTUP:
|
||||
vlapic->direct_intr.deliver_mode &= ~(1 << deliver_mode);
|
||||
break;
|
||||
|
||||
default:
|
||||
printk("<vlapic_post_injection> error deliver mode\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int vlapic_reset(struct vlapic *vlapic)
|
||||
{
|
||||
struct vcpu *v = vlapic->vcpu;
|
||||
int apic_id = v->vcpu_id, i;
|
||||
|
||||
if (!v || !vlapic)
|
||||
return 0;
|
||||
|
||||
memset(vlapic, 0,sizeof(struct vlapic));
|
||||
|
||||
v->arch.arch_vmx.vlapic = vlapic;
|
||||
|
||||
vlapic->domain = v->domain;
|
||||
|
||||
vlapic->id = apic_id;
|
||||
|
||||
vlapic->version = VLAPIC_VERSION;
|
||||
|
||||
vlapic->apic_base_msr = VLAPIC_BASE_MSR_INIT_VALUE;
|
||||
|
||||
if (apic_id == 0)
|
||||
vlapic->apic_base_msr |= MSR_IA32_APICBASE_BSP;
|
||||
vlapic->base_address = vlapic_get_base_address(vlapic);
|
||||
|
||||
for (i = 0; i < VLAPIC_LVT_NUM; i++)
|
||||
vlapic->lvt[i] = VLAPIC_LVT_BIT_MASK;
|
||||
|
||||
vlapic->dest_format = 0xffffffffU;
|
||||
|
||||
vlapic->spurious_vec = 0xff;
|
||||
|
||||
|
||||
init_ac_timer(&vlapic->vlapic_timer,
|
||||
vlapic_timer_fn, vlapic, v->processor);
|
||||
|
||||
#ifdef VLAPIC_NO_BIOS
|
||||
/*
|
||||
* XXX According to mp sepcific, BIOS will enable LVT0/1,
|
||||
* remove it after BIOS enabled
|
||||
*/
|
||||
if (!v->vcpu_id) {
|
||||
vlapic->lvt[VLAPIC_LVT_LINT0] = 0x700;
|
||||
vlapic->lvt[VLAPIC_LVT_LINT1] = 0x500;
|
||||
set_bit(_VLAPIC_BSP_ACCEPT_PIC, &vlapic->status);
|
||||
}
|
||||
#endif
|
||||
|
||||
VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_reset: "
|
||||
"vcpu=%p id=%d vlapic_apic_base_msr=%08x%08x "
|
||||
"vlapic_base_address=%0lx",
|
||||
v, vlapic->id, (uint32_t)(vlapic->apic_base_msr >> 32),
|
||||
(uint32_t)vlapic->apic_base_msr, vlapic->base_address);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int vlapic_init(struct vcpu *v)
|
||||
{
|
||||
struct vlapic *vlapic = NULL;
|
||||
|
||||
VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_init %d", v->vcpu_id);
|
||||
|
||||
vlapic = xmalloc_bytes(sizeof(struct vlapic));
|
||||
|
||||
if (!vlapic) {
|
||||
printk("malloc vlapic error for vcpu %x\n", v->vcpu_id);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
vlapic->vcpu = v;
|
||||
|
||||
vlapic_reset(vlapic);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_VMX */
|
||||
@@ -252,6 +252,10 @@ static void vmx_setup_platform(struct domain* d)
|
||||
pic_init(&platform->vmx_pic, pic_irq_request,
|
||||
&platform->interrupt_request);
|
||||
register_pic_io_hook();
|
||||
|
||||
if ( vmx_apic_support(d) ) {
|
||||
spin_lock_init(&d->arch.vmx_platform.round_robin_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void vmx_set_host_env(struct vcpu *v)
|
||||
@@ -313,6 +317,9 @@ static void vmx_do_launch(struct vcpu *v)
|
||||
|
||||
vmx_stts();
|
||||
|
||||
if(vmx_apic_support(v->domain))
|
||||
vlapic_init(v);
|
||||
|
||||
vmx_set_host_env(v);
|
||||
|
||||
error |= __vmwrite(GUEST_LDTR_SELECTOR, 0);
|
||||
|
||||
+12
-1
@@ -133,7 +133,10 @@ long do_acm_op(struct acm_op * u_acm_op)
|
||||
struct domain *subj = find_domain_by_id(op->u.getssid.id.domainid);
|
||||
if (!subj)
|
||||
return -ESRCH; /* domain not found */
|
||||
|
||||
if (subj->ssid == NULL) {
|
||||
put_domain(subj);
|
||||
return -ESRCH;
|
||||
}
|
||||
ssidref = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
|
||||
put_domain(subj);
|
||||
} else
|
||||
@@ -167,6 +170,10 @@ long do_acm_op(struct acm_op * u_acm_op)
|
||||
ret = -ESRCH; /* domain not found */
|
||||
goto out;
|
||||
}
|
||||
if (subj->ssid == NULL) {
|
||||
put_domain(subj);
|
||||
ret = -ESRCH;
|
||||
}
|
||||
ssidref1 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
|
||||
put_domain(subj);
|
||||
} else {
|
||||
@@ -182,6 +189,10 @@ long do_acm_op(struct acm_op * u_acm_op)
|
||||
ret = -ESRCH; /* domain not found */
|
||||
goto out;
|
||||
}
|
||||
if (subj->ssid == NULL) {
|
||||
put_domain(subj);
|
||||
return -ESRCH;
|
||||
}
|
||||
ssidref2 = ((struct acm_ssid_domain *)(subj->ssid))->ssidref;
|
||||
put_domain(subj);
|
||||
} else {
|
||||
|
||||
@@ -514,7 +514,7 @@ static void dom_timer_fn(void *data)
|
||||
/* Initialise the data structures. */
|
||||
void __init scheduler_init(void)
|
||||
{
|
||||
int i;
|
||||
int i, rc;
|
||||
|
||||
open_softirq(SCHEDULE_SOFTIRQ, __enter_scheduler);
|
||||
|
||||
@@ -540,7 +540,9 @@ void __init scheduler_init(void)
|
||||
|
||||
printk("Using scheduler: %s (%s)\n", ops.name, ops.opt_name);
|
||||
|
||||
BUG_ON(SCHED_OP(alloc_task, idle_task[0]) < 0);
|
||||
rc = SCHED_OP(alloc_task, idle_task[0]);
|
||||
BUG_ON(rc < 0);
|
||||
|
||||
sched_add_domain(idle_task[0]);
|
||||
}
|
||||
|
||||
|
||||
+32
-18
@@ -100,10 +100,10 @@ struct acm_operations {
|
||||
void (*fail_domain_create) (void *subject_ssid, ssidref_t ssidref);
|
||||
void (*post_domain_destroy) (void *object_ssid, domid_t id);
|
||||
/* event channel control hooks (can be NULL) */
|
||||
int (*pre_eventchannel_unbound) (domid_t id);
|
||||
void (*fail_eventchannel_unbound) (domid_t id);
|
||||
int (*pre_eventchannel_interdomain) (domid_t id1, domid_t id2);
|
||||
int (*fail_eventchannel_interdomain) (domid_t id1, domid_t id2);
|
||||
int (*pre_eventchannel_unbound) (domid_t id1, domid_t id2);
|
||||
void (*fail_eventchannel_unbound) (domid_t id1, domid_t id2);
|
||||
int (*pre_eventchannel_interdomain) (domid_t id);
|
||||
void (*fail_eventchannel_interdomain) (domid_t id);
|
||||
/* grant table control hooks (can be NULL) */
|
||||
int (*pre_grant_map_ref) (domid_t id);
|
||||
void (*fail_grant_map_ref) (domid_t id);
|
||||
@@ -193,31 +193,31 @@ static inline void acm_post_domain_destroy(void *object_ssid, domid_t id)
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int acm_pre_eventchannel_unbound(domid_t id)
|
||||
static inline int acm_pre_eventchannel_unbound(domid_t id1, domid_t id2)
|
||||
{
|
||||
if ((acm_primary_ops->pre_eventchannel_unbound != NULL) &&
|
||||
acm_primary_ops->pre_eventchannel_unbound(id))
|
||||
acm_primary_ops->pre_eventchannel_unbound(id1, id2))
|
||||
return ACM_ACCESS_DENIED;
|
||||
else if ((acm_secondary_ops->pre_eventchannel_unbound != NULL) &&
|
||||
acm_secondary_ops->pre_eventchannel_unbound(id)) {
|
||||
acm_secondary_ops->pre_eventchannel_unbound(id1, id2)) {
|
||||
/* roll-back primary */
|
||||
if (acm_primary_ops->fail_eventchannel_unbound != NULL)
|
||||
acm_primary_ops->fail_eventchannel_unbound(id);
|
||||
acm_primary_ops->fail_eventchannel_unbound(id1, id2);
|
||||
return ACM_ACCESS_DENIED;
|
||||
} else
|
||||
return ACM_ACCESS_PERMITTED;
|
||||
}
|
||||
|
||||
static inline int acm_pre_eventchannel_interdomain(domid_t id1, domid_t id2)
|
||||
static inline int acm_pre_eventchannel_interdomain(domid_t id)
|
||||
{
|
||||
if ((acm_primary_ops->pre_eventchannel_interdomain != NULL) &&
|
||||
acm_primary_ops->pre_eventchannel_interdomain(id1, id2))
|
||||
acm_primary_ops->pre_eventchannel_interdomain(id))
|
||||
return ACM_ACCESS_DENIED;
|
||||
else if ((acm_secondary_ops->pre_eventchannel_interdomain != NULL) &&
|
||||
acm_secondary_ops->pre_eventchannel_interdomain(id1, id2)) {
|
||||
acm_secondary_ops->pre_eventchannel_interdomain(id)) {
|
||||
/* roll-back primary */
|
||||
if (acm_primary_ops->fail_eventchannel_interdomain != NULL)
|
||||
acm_primary_ops->fail_eventchannel_interdomain(id1, id2);
|
||||
acm_primary_ops->fail_eventchannel_interdomain(id);
|
||||
return ACM_ACCESS_DENIED;
|
||||
} else
|
||||
return ACM_ACCESS_PERMITTED;
|
||||
@@ -234,10 +234,22 @@ static inline int acm_pre_dom0_op(dom0_op_t *op, void **ssid)
|
||||
current->domain->ssid, op->u.createdomain.ssidref);
|
||||
break;
|
||||
case DOM0_DESTROYDOMAIN:
|
||||
if (*ssid != NULL) {
|
||||
printkd("%s: Warning. Overlapping destruction.\n",
|
||||
__func__);
|
||||
return -EACCES;
|
||||
}
|
||||
d = find_domain_by_id(op->u.destroydomain.domain);
|
||||
if (d != NULL) {
|
||||
*ssid = d->ssid; /* save for post destroy when d is gone */
|
||||
/* no policy-specific hook */
|
||||
if (*ssid == NULL) {
|
||||
printk("%s: Warning. Destroying domain without ssid pointer.\n",
|
||||
__func__);
|
||||
put_domain(d);
|
||||
return -EACCES;
|
||||
}
|
||||
d->ssid = NULL; /* make sure it's not used any more */
|
||||
/* no policy-specific hook */
|
||||
put_domain(d);
|
||||
ret = 0;
|
||||
}
|
||||
@@ -248,7 +260,7 @@ static inline int acm_pre_dom0_op(dom0_op_t *op, void **ssid)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void acm_post_dom0_op(dom0_op_t *op, void *ssid)
|
||||
static inline void acm_post_dom0_op(dom0_op_t *op, void **ssid)
|
||||
{
|
||||
switch(op->cmd) {
|
||||
case DOM0_CREATEDOMAIN:
|
||||
@@ -261,7 +273,8 @@ static inline void acm_post_dom0_op(dom0_op_t *op, void *ssid)
|
||||
case DOM0_DESTROYDOMAIN:
|
||||
acm_post_domain_destroy(ssid, op->u.destroydomain.domain);
|
||||
/* free security ssid for the destroyed domain (also if null policy */
|
||||
acm_free_domain_ssid((struct acm_ssid_domain *)ssid);
|
||||
acm_free_domain_ssid((struct acm_ssid_domain *)(*ssid));
|
||||
*ssid = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -282,12 +295,13 @@ static inline int acm_pre_event_channel(evtchn_op_t *op)
|
||||
|
||||
switch(op->cmd) {
|
||||
case EVTCHNOP_alloc_unbound:
|
||||
ret = acm_pre_eventchannel_unbound(op->u.alloc_unbound.dom);
|
||||
ret = acm_pre_eventchannel_unbound(
|
||||
op->u.alloc_unbound.dom,
|
||||
op->u.alloc_unbound.remote_dom);
|
||||
break;
|
||||
case EVTCHNOP_bind_interdomain:
|
||||
ret = acm_pre_eventchannel_interdomain(
|
||||
current->domain->domain_id,
|
||||
op->u.bind_interdomain.remote_dom);
|
||||
op->u.bind_interdomain.remote_dom);
|
||||
break;
|
||||
default:
|
||||
ret = 0; /* ok */
|
||||
|
||||
@@ -14,6 +14,16 @@
|
||||
#define VMX_MMIO 1
|
||||
|
||||
typedef int (*intercept_action_t)(ioreq_t *);
|
||||
typedef unsigned long (*vmx_mmio_read_t)(struct vcpu *v,
|
||||
unsigned long addr,
|
||||
unsigned long length);
|
||||
|
||||
typedef unsigned long (*vmx_mmio_write_t)(struct vcpu *v,
|
||||
unsigned long addr,
|
||||
unsigned long length,
|
||||
unsigned long val);
|
||||
|
||||
typedef int (*vmx_mmio_check_t)(struct vcpu *v, unsigned long addr);
|
||||
|
||||
struct io_handler {
|
||||
int type;
|
||||
@@ -27,6 +37,16 @@ struct vmx_io_handler {
|
||||
struct io_handler hdl_list[MAX_IO_HANDLER];
|
||||
};
|
||||
|
||||
struct vmx_mmio_handler {
|
||||
vmx_mmio_check_t check_handler;
|
||||
vmx_mmio_read_t read_handler;
|
||||
vmx_mmio_write_t write_handler;
|
||||
};
|
||||
|
||||
#define VMX_MMIO_HANDLER_NR 1
|
||||
|
||||
extern struct vmx_mmio_handler vmx_mmio_handers[VMX_MMIO_HANDLER_NR];
|
||||
|
||||
/* global io interception point in HV */
|
||||
extern int vmx_io_intercept(ioreq_t *p, int type);
|
||||
extern int register_io_handler(unsigned long addr, unsigned long size,
|
||||
@@ -37,10 +57,7 @@ static inline int vmx_portio_intercept(ioreq_t *p)
|
||||
return vmx_io_intercept(p, VMX_PORTIO);
|
||||
}
|
||||
|
||||
static inline int vmx_mmio_intercept(ioreq_t *p)
|
||||
{
|
||||
return vmx_io_intercept(p, VMX_MMIO);
|
||||
}
|
||||
int vmx_mmio_intercept(ioreq_t *p);
|
||||
|
||||
static inline int register_portio_handler(unsigned long addr,
|
||||
unsigned long size,
|
||||
@@ -49,11 +66,4 @@ static inline int register_portio_handler(unsigned long addr,
|
||||
return register_io_handler(addr, size, action, VMX_PORTIO);
|
||||
}
|
||||
|
||||
static inline int register_mmio_handler(unsigned long addr,
|
||||
unsigned long size,
|
||||
intercept_action_t action)
|
||||
{
|
||||
return register_io_handler(addr, size, action, VMX_MMIO);
|
||||
}
|
||||
|
||||
#endif /* _VMX_INTERCEPT_H */
|
||||
@@ -80,10 +80,13 @@ struct instruction {
|
||||
struct vmx_platform {
|
||||
unsigned long shared_page_va;
|
||||
unsigned int nr_vcpu;
|
||||
unsigned int lapic_enable;
|
||||
|
||||
struct vmx_virpit vmx_pit;
|
||||
struct vmx_io_handler vmx_io_handler;
|
||||
struct vmx_virpic vmx_pic;
|
||||
unsigned char round_info[256];
|
||||
spinlock_t round_robin_lock;
|
||||
int interrupt_request;
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* vmx_vlapic.h: virtualize LAPIC definitions.
|
||||
* Copyright (c) 2004, Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
||||
* Place - Suite 330, Boston, MA 02111-1307 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef VMX_VLAPIC_H
|
||||
#define VMX_VLAPIC_H
|
||||
|
||||
#include <asm/msr.h>
|
||||
#include <public/io/ioreq.h>
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
static inline int __fls(uint32_t word)
|
||||
{
|
||||
int bit;
|
||||
|
||||
__asm__("bsrl %1,%0"
|
||||
:"=r" (bit)
|
||||
:"rm" (word));
|
||||
return word ? bit : -1;
|
||||
}
|
||||
#else
|
||||
#define __fls(x) generic_fls(x)
|
||||
static __inline__ int generic_fls(uint32_t x)
|
||||
{
|
||||
int r = 31;
|
||||
|
||||
if (!x)
|
||||
return -1;
|
||||
if (!(x & 0xffff0000u)) {
|
||||
x <<= 16;
|
||||
r -= 16;
|
||||
}
|
||||
if (!(x & 0xff000000u)) {
|
||||
x <<= 8;
|
||||
r -= 8;
|
||||
}
|
||||
if (!(x & 0xf0000000u)) {
|
||||
x <<= 4;
|
||||
r -= 4;
|
||||
}
|
||||
if (!(x & 0xc0000000u)) {
|
||||
x <<= 2;
|
||||
r -= 2;
|
||||
}
|
||||
if (!(x & 0x80000000u)) {
|
||||
x <<= 1;
|
||||
r -= 1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
static __inline__ int find_highest_bit(uint32_t *data, int length)
|
||||
{
|
||||
while(length && !data[--length]);
|
||||
return __fls(data[length]) + 32 * length;
|
||||
}
|
||||
|
||||
#define VLAPIC(v) (v->arch.arch_vmx.vlapic)
|
||||
|
||||
#define VAPIC_ID_MASK 0xff
|
||||
#define VAPIC_LDR_MASK (VAPIC_ID_MASK << 24)
|
||||
#define VLAPIC_VERSION 0x00050014
|
||||
|
||||
#define VLAPIC_BASE_MSR_MASK 0x00000000fffff900ULL
|
||||
#define VLAPIC_BASE_MSR_INIT_BASE_ADDR 0xfee00000U
|
||||
#define VLAPIC_BASE_MSR_BASE_ADDR_MASK 0xfffff000U
|
||||
#define VLAPIC_BASE_MSR_INIT_VALUE (VLAPIC_BASE_MSR_INIT_BASE_ADDR | \
|
||||
MSR_IA32_APICBASE_ENABLE)
|
||||
#define VLOCAL_APIC_MEM_LENGTH (1 << 12)
|
||||
|
||||
#define VLAPIC_LVT_TIMER 0
|
||||
#define VLAPIC_LVT_THERMAL 1
|
||||
#define VLAPIC_LVT_PERFORM 2
|
||||
#define VLAPIC_LVT_LINT0 3
|
||||
#define VLAPIC_LVT_LINT1 4
|
||||
#define VLAPIC_LVT_ERROR 5
|
||||
#define VLAPIC_LVT_NUM 6
|
||||
|
||||
#define VLAPIC_LVT_BIT_MASK (1 << 16)
|
||||
#define VLAPIC_LVT_BIT_VECTOR 0xff
|
||||
#define VLAPIC_LVT_BIT_DELIMOD (0x7 << 8)
|
||||
#define VLAPIC_LVT_BIT_DELISTATUS (1 << 12)
|
||||
#define VLAPIC_LVT_BIT_POLARITY (1 << 13)
|
||||
#define VLAPIC_LVT_BIT_IRR (1 << 14)
|
||||
#define VLAPIC_LVT_BIT_TRIG (1 << 15)
|
||||
#define VLAPIC_LVT_TIMERMODE (1 << 17)
|
||||
|
||||
#define VLAPIC_DELIV_MODE_FIXED 0x0
|
||||
#define VLAPIC_DELIV_MODE_LPRI 0x1
|
||||
#define VLAPIC_DELIV_MODE_SMI 0x2
|
||||
#define VLAPIC_DELIV_MODE_RESERVED 0x3
|
||||
#define VLAPIC_DELIV_MODE_NMI 0x4
|
||||
#define VLAPIC_DELIV_MODE_INIT 0x5
|
||||
#define VLAPIC_DELIV_MODE_STARTUP 0x6
|
||||
#define VLAPIC_DELIV_MODE_EXT 0x7
|
||||
|
||||
|
||||
|
||||
#define VLAPIC_NO_SHORTHAND 0x0
|
||||
#define VLAPIC_SHORTHAND_SELF 0x1
|
||||
#define VLAPIC_SHORTHAND_INCLUDE_SELF 0x2
|
||||
#define VLAPIC_SHORTHAND_EXCLUDE_SELF 0x3
|
||||
|
||||
#define vlapic_lvt_timer_enabled(vlapic) \
|
||||
(!(vlapic->lvt[VLAPIC_LVT_TIMER] & VLAPIC_LVT_BIT_MASK))
|
||||
|
||||
#define vlapic_lvt_vector(vlapic, type) \
|
||||
(vlapic->lvt[type] & VLAPIC_LVT_BIT_VECTOR)
|
||||
|
||||
#define vlapic_lvt_dm(value) ((value >> 8) && 7)
|
||||
#define vlapic_lvt_timer_period(vlapic) \
|
||||
(vlapic->lvt[VLAPIC_LVT_TIMER] & VLAPIC_LVT_TIMERMODE)
|
||||
|
||||
#define vlapic_isr_status(vlapic,vector) \
|
||||
test_bit(vector, &vlapic->isr[0])
|
||||
|
||||
#define vlapic_irr_status(vlapic,vector) \
|
||||
test_bit(vector, &vlapic->irr[0])
|
||||
|
||||
#define vlapic_set_isr(vlapic,vector) \
|
||||
test_and_set_bit(vector, &vlapic->isr[0])
|
||||
|
||||
#define vlapic_set_irr(vlapic,vector) \
|
||||
test_and_set_bit(vector, &vlapic->irr[0])
|
||||
|
||||
#define vlapic_clear_irr(vlapic,vector) \
|
||||
clear_bit(vector, &vlapic->irr[0])
|
||||
#define vlapic_clear_isr(vlapic,vector) \
|
||||
clear_bit(vector, &vlapic->isr[0])
|
||||
|
||||
#define vlapic_enabled(vlapic) \
|
||||
(!(vlapic->status & \
|
||||
(VLAPIC_GLOB_DISABLE_MASK | VLAPIC_SOFTWARE_DISABLE_MASK)))
|
||||
|
||||
#define vlapic_global_enabled(vlapic) \
|
||||
!(test_bit(_VLAPIC_GLOB_DISABLE, &(vlapic)->status))
|
||||
|
||||
typedef struct direct_intr_info {
|
||||
int deliver_mode;
|
||||
int source[6];
|
||||
} direct_intr_info_t;
|
||||
|
||||
#define VLAPIC_INIT_SIPI_SIPI_STATE_NORM 0
|
||||
#define VLAPIC_INIT_SIPI_SIPI_STATE_WAIT_SIPI 1
|
||||
|
||||
struct vlapic
|
||||
{
|
||||
//FIXME check what would be 64 bit on EM64T
|
||||
uint32_t version;
|
||||
#define _VLAPIC_GLOB_DISABLE 0x0
|
||||
#define VLAPIC_GLOB_DISABLE_MASK 0x1
|
||||
#define VLAPIC_SOFTWARE_DISABLE_MASK 0x2
|
||||
#define _VLAPIC_BSP_ACCEPT_PIC 0x3
|
||||
uint32_t status;
|
||||
uint32_t id;
|
||||
uint32_t vcpu_id;
|
||||
unsigned long base_address;
|
||||
uint32_t isr[8];
|
||||
uint32_t irr[INTR_LEN_32];
|
||||
uint32_t tmr[INTR_LEN_32];
|
||||
uint32_t task_priority;
|
||||
uint32_t processor_priority;
|
||||
uint32_t logical_dest;
|
||||
uint32_t dest_format;
|
||||
uint32_t spurious_vec;
|
||||
uint32_t lvt[6];
|
||||
uint32_t timer_initial;
|
||||
uint32_t timer_current;
|
||||
uint32_t timer_divconf;
|
||||
uint32_t timer_divide_counter;
|
||||
struct ac_timer vlapic_timer;
|
||||
int intr_pending_count[MAX_VECTOR];
|
||||
s_time_t timer_current_update;
|
||||
uint32_t icr_high;
|
||||
uint32_t icr_low;
|
||||
direct_intr_info_t direct_intr;
|
||||
uint32_t err_status;
|
||||
unsigned long init_ticks;
|
||||
uint32_t err_write_count;
|
||||
uint64_t apic_base_msr;
|
||||
uint32_t init_sipi_sipi_state;
|
||||
struct vcpu *vcpu;
|
||||
struct domain *domain;
|
||||
};
|
||||
|
||||
static inline int vlapic_timer_active(struct vlapic *vlapic)
|
||||
{
|
||||
return active_ac_timer(&(vlapic->vlapic_timer));
|
||||
}
|
||||
|
||||
int vlapic_find_highest_irr(struct vlapic *vlapic);
|
||||
|
||||
int vlapic_find_highest_isr(struct vlapic *vlapic);
|
||||
|
||||
static uint32_t inline vlapic_get_base_address(struct vlapic *vlapic)
|
||||
{
|
||||
return (vlapic->apic_base_msr & VLAPIC_BASE_MSR_BASE_ADDR_MASK);
|
||||
}
|
||||
|
||||
void vlapic_post_injection(struct vcpu* v, int vector, int deliver_mode);
|
||||
|
||||
int cpu_get_apic_interrupt(struct vcpu* v, int *mode);
|
||||
|
||||
extern uint32_t vlapic_update_ppr(struct vlapic *vlapic);
|
||||
|
||||
int vlapic_update(struct vcpu *v);
|
||||
|
||||
extern int vlapic_init(struct vcpu *vc);
|
||||
|
||||
extern void vlapic_msr_set(struct vlapic *vlapic, uint64_t value);
|
||||
|
||||
int vlapic_range(struct vcpu *v, unsigned long addr);
|
||||
|
||||
unsigned long vlapic_write(struct vcpu *v, unsigned long address,
|
||||
unsigned long len, unsigned long val);
|
||||
|
||||
unsigned long vlapic_read(struct vcpu *v, unsigned long address,
|
||||
unsigned long len);
|
||||
|
||||
int vlapic_accept_pic_intr(struct vcpu *v);
|
||||
|
||||
struct vlapic* apic_round_robin(struct domain *d,
|
||||
uint8_t dest_mode,
|
||||
uint8_t vector,
|
||||
uint32_t bitmap);
|
||||
|
||||
int vmx_apic_support(struct domain *d);
|
||||
|
||||
#endif /* VMX_VLAPIC_H */
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <asm/config.h>
|
||||
#include <asm/vmx_cpu.h>
|
||||
#include <asm/vmx_platform.h>
|
||||
#include <asm/vmx_vlapic.h>
|
||||
#include <public/vmx_assist.h>
|
||||
|
||||
extern int start_vmx(void);
|
||||
@@ -96,6 +97,7 @@ struct arch_vmx_struct {
|
||||
struct msr_state msr_content;
|
||||
struct mmio_op mmio_op; /* MMIO */
|
||||
void *io_bitmap_a, *io_bitmap_b;
|
||||
struct vlapic *vlapic;
|
||||
u64 tsc_offset;
|
||||
};
|
||||
|
||||
@@ -272,18 +274,21 @@ enum vmcs_field {
|
||||
|
||||
#define VMX_DEBUG 1
|
||||
#if VMX_DEBUG
|
||||
#define DBG_LEVEL_0 (1 << 0)
|
||||
#define DBG_LEVEL_1 (1 << 1)
|
||||
#define DBG_LEVEL_2 (1 << 2)
|
||||
#define DBG_LEVEL_3 (1 << 3)
|
||||
#define DBG_LEVEL_IO (1 << 4)
|
||||
#define DBG_LEVEL_VMMU (1 << 5)
|
||||
#define DBG_LEVEL_0 (1 << 0)
|
||||
#define DBG_LEVEL_1 (1 << 1)
|
||||
#define DBG_LEVEL_2 (1 << 2)
|
||||
#define DBG_LEVEL_3 (1 << 3)
|
||||
#define DBG_LEVEL_IO (1 << 4)
|
||||
#define DBG_LEVEL_VMMU (1 << 5)
|
||||
#define DBG_LEVEL_VLAPIC (1 << 6)
|
||||
#define DBG_LEVEL_VLAPIC_TIMER (1 << 7)
|
||||
#define DBG_LEVEL_VLAPIC_INTERRUPT (1 << 7)
|
||||
|
||||
extern unsigned int opt_vmx_debug_level;
|
||||
#define VMX_DBG_LOG(level, _f, _a...) \
|
||||
if ((level) & opt_vmx_debug_level) \
|
||||
printk("[VMX:%d.%d] " _f "\n", \
|
||||
current->domain->domain_id, current->vcpu_id, ## _a)
|
||||
current->domain->domain_id, current->vcpu_id, ## _a)
|
||||
#else
|
||||
#define VMX_DBG_LOG(level, _f, _a...)
|
||||
#endif
|
||||
|
||||
@@ -29,11 +29,11 @@
|
||||
#define STATE_IORESP_READY 3
|
||||
#define STATE_IORESP_HOOK 4
|
||||
|
||||
#define IOREQ_TYPE_PIO 0 /* pio */
|
||||
#define IOREQ_TYPE_COPY 1 /* mmio ops */
|
||||
#define IOREQ_TYPE_AND 2
|
||||
#define IOREQ_TYPE_OR 3
|
||||
#define IOREQ_TYPE_XOR 4
|
||||
#define IOREQ_TYPE_PIO 0 /* pio */
|
||||
#define IOREQ_TYPE_COPY 1 /* mmio ops */
|
||||
#define IOREQ_TYPE_AND 2
|
||||
#define IOREQ_TYPE_OR 3
|
||||
#define IOREQ_TYPE_XOR 4
|
||||
|
||||
/*
|
||||
* VMExit dispatcher should cooperate with instruction decoder to
|
||||
@@ -55,9 +55,10 @@ typedef struct {
|
||||
uint8_t type; /* I/O type */
|
||||
} ioreq_t;
|
||||
|
||||
#define MAX_VECTOR 256
|
||||
#define MAX_VECTOR 256
|
||||
#define BITS_PER_BYTE 8
|
||||
#define INTR_LEN (MAX_VECTOR/(BITS_PER_BYTE * sizeof(uint64_t)))
|
||||
#define INTR_LEN_32 (MAX_VECTOR/(BITS_PER_BYTE * sizeof(uint32_t)))
|
||||
|
||||
typedef struct {
|
||||
uint16_t pic_elcr;
|
||||
|
||||
@@ -76,7 +76,7 @@ void pic_update_irq(struct vmx_virpic *s);
|
||||
uint32_t pic_intack_read(struct vmx_virpic *s);
|
||||
void register_pic_io_hook (void);
|
||||
int cpu_get_pic_interrupt(struct vcpu *v, int *type);
|
||||
int is_pit_irq(struct vcpu *v, int irq);
|
||||
int is_pit_irq(struct vcpu *v, int irq, int type);
|
||||
void do_pic_irqs (struct vmx_virpic *s, uint16_t irqs);
|
||||
void do_pic_irqs_clear (struct vmx_virpic *s, uint16_t irqs);
|
||||
|
||||
|
||||
@@ -410,6 +410,7 @@ typedef struct shared_info {
|
||||
#define MAX_GUEST_CMDLINE 1024
|
||||
typedef struct start_info {
|
||||
/* THE FOLLOWING ARE FILLED IN BOTH ON INITIAL BOOT AND ON RESUME. */
|
||||
char magic[32]; /* "Xen-<version>.<subversion>". */
|
||||
unsigned long nr_pages; /* Total pages allocated to this domain. */
|
||||
unsigned long shared_info; /* MACHINE address of shared info struct. */
|
||||
uint32_t flags; /* SIF_xxx flags. */
|
||||
|
||||
@@ -101,7 +101,6 @@ struct domain
|
||||
struct list_head xenpage_list; /* linked list, of size xenheap_pages */
|
||||
unsigned int tot_pages; /* number of pages currently possesed */
|
||||
unsigned int max_pages; /* maximum value for tot_pages */
|
||||
unsigned int next_io_page; /* next io pfn to give to domain */
|
||||
unsigned int xenheap_pages; /* # pages allocated from Xen heap */
|
||||
|
||||
/* Scheduling. */
|
||||
|
||||