mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
Merged.
This commit is contained in:
commit
ff9465e411
116 files changed
+3690
-1399
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)
|
||||
|
||||
@@ -29,7 +29,7 @@ unsigned int bind_virq_to_evtchn(int virq)
|
||||
return op.u.bind_virq.port;
|
||||
}
|
||||
|
||||
int bind_virq_to_irq(int virq)
|
||||
int bind_virq_to_irq(int virq, int cpu)
|
||||
{
|
||||
printk("bind_virq_to_irq called... FIXME??\n");
|
||||
while(1);
|
||||
@@ -66,7 +66,11 @@ int bind_evtchn_to_irqhandler(unsigned int evtchn,
|
||||
evtchns[evtchn].handler = handler;
|
||||
evtchns[evtchn].dev_id = dev_id;
|
||||
unmask_evtchn(evtchn);
|
||||
return 0;
|
||||
//return 0;
|
||||
/* On ia64, there's only one irq vector allocated for all event channels,
|
||||
* so let's just return evtchn as handle for later communication
|
||||
*/
|
||||
return evtchn;
|
||||
}
|
||||
|
||||
void unbind_evtchn_from_irqhandler(unsigned int evtchn, void *dev_id)
|
||||
|
||||
@@ -46,8 +46,6 @@ GLOBAL_ENTRY(ia64_switch_to)
|
||||
.prologue
|
||||
alloc r16=ar.pfs,1,0,0,0
|
||||
#endif
|
||||
.prologue
|
||||
alloc r16=ar.pfs,1,0,0,0
|
||||
DO_SAVE_SWITCH_STACK
|
||||
.body
|
||||
|
||||
|
||||
@@ -653,7 +653,7 @@ ENTRY(simd_coprocessor_error)
|
||||
ENTRY(device_not_available)
|
||||
pushl $-1 # mark this as an int
|
||||
SAVE_ALL
|
||||
preempt_stop
|
||||
#preempt_stop /* This is already an interrupt gate on Xen. */
|
||||
call math_state_restore
|
||||
jmp ret_from_exception
|
||||
|
||||
|
||||
@@ -483,6 +483,9 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas
|
||||
mcl->args[0] = 1;
|
||||
mcl++;
|
||||
}
|
||||
#if 0 /* lazy fpu sanity check */
|
||||
else BUG_ON(!(read_cr0() & 8));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Reload esp0, LDT and the page table pointer:
|
||||
|
||||
@@ -648,6 +648,12 @@ fastcall void do_int3(struct pt_regs *regs, long error_code)
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void conditional_sti(struct pt_regs *regs)
|
||||
{
|
||||
if ((uint8_t)(regs->xcs >> 16) == 0)
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
/*
|
||||
* Our handling of the processor debug registers is non-trivial.
|
||||
* We do not clear them on entry and exit from the kernel. Therefore
|
||||
@@ -680,11 +686,9 @@ fastcall void do_debug(struct pt_regs * regs, long error_code)
|
||||
if (notify_die(DIE_DEBUG, "debug", regs, condition, error_code,
|
||||
SIGTRAP) == NOTIFY_STOP)
|
||||
return;
|
||||
#if 0
|
||||
|
||||
/* It's safe to allow irq's after DR6 has been saved */
|
||||
if (regs->eflags & X86_EFLAGS_IF)
|
||||
local_irq_enable();
|
||||
#endif
|
||||
conditional_sti(regs);
|
||||
|
||||
/* Mask out spurious debug traps due to lazy DR7 setting */
|
||||
if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
|
||||
@@ -967,15 +971,18 @@ void __init trap_init_f00f_bug(void)
|
||||
#endif
|
||||
|
||||
|
||||
/* NB. All these are "trap gates" (i.e. events_mask isn't cleared). */
|
||||
/*
|
||||
* NB. All these are "trap gates" (i.e. events_mask isn't cleared) except
|
||||
* for those that specify <dpl>|4 in the second field.
|
||||
*/
|
||||
static trap_info_t trap_table[] = {
|
||||
{ 0, 0, __KERNEL_CS, (unsigned long)divide_error },
|
||||
{ 1, 0, __KERNEL_CS, (unsigned long)debug },
|
||||
{ 3, 3, __KERNEL_CS, (unsigned long)int3 },
|
||||
{ 1, 0|4, __KERNEL_CS, (unsigned long)debug },
|
||||
{ 3, 3|4, __KERNEL_CS, (unsigned long)int3 },
|
||||
{ 4, 3, __KERNEL_CS, (unsigned long)overflow },
|
||||
{ 5, 3, __KERNEL_CS, (unsigned long)bounds },
|
||||
{ 6, 0, __KERNEL_CS, (unsigned long)invalid_op },
|
||||
{ 7, 0, __KERNEL_CS, (unsigned long)device_not_available },
|
||||
{ 7, 0|4, __KERNEL_CS, (unsigned long)device_not_available },
|
||||
{ 9, 0, __KERNEL_CS, (unsigned long)coprocessor_segment_overrun },
|
||||
{ 10, 0, __KERNEL_CS, (unsigned long)invalid_TSS },
|
||||
{ 11, 0, __KERNEL_CS, (unsigned long)segment_not_present },
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -191,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;
|
||||
}
|
||||
@@ -213,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);
|
||||
@@ -242,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,
|
||||
@@ -268,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 {
|
||||
@@ -295,8 +301,8 @@ 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;
|
||||
@@ -501,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,
|
||||
@@ -510,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;
|
||||
}
|
||||
|
||||
@@ -519,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)
|
||||
@@ -527,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) {
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/tlb.h>
|
||||
#include <asm-xen/linux-public/privcmd.h>
|
||||
#include <asm/hypervisor.h>
|
||||
#include <asm-xen/linux-public/privcmd.h>
|
||||
#include <asm-xen/xen-public/xen.h>
|
||||
#include <asm-xen/xen-public/dom0_ops.h>
|
||||
#include <asm-xen/xen_proc.h>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -714,11 +714,7 @@ static int xsd_port_read(char *page, char **start, off_t off,
|
||||
|
||||
static int __init xenbus_probe_init(void)
|
||||
{
|
||||
int err = 0;
|
||||
/*
|
||||
** Domain0 doesn't have a store_evtchn or store_mfn yet.
|
||||
*/
|
||||
int dom0 = (xen_start_info->store_evtchn == 0);
|
||||
int err = 0, dom0;
|
||||
|
||||
printk("xenbus_probe_init\n");
|
||||
|
||||
@@ -733,10 +729,16 @@ static int __init xenbus_probe_init(void)
|
||||
device_register(&xenbus_frontend.dev);
|
||||
device_register(&xenbus_backend.dev);
|
||||
|
||||
/*
|
||||
** Domain0 doesn't have a store_evtchn or store_mfn yet.
|
||||
*/
|
||||
dom0 = (xen_start_info->store_evtchn == 0);
|
||||
|
||||
if (dom0) {
|
||||
|
||||
unsigned long page;
|
||||
evtchn_op_t op = { 0 };
|
||||
int ret;
|
||||
|
||||
|
||||
/* Allocate page. */
|
||||
@@ -757,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 */
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/uio.h>
|
||||
|
||||
@@ -17,6 +17,7 @@ XEN_CONFIGS = xend-config.sxp
|
||||
XEN_CONFIGS += xmexample1
|
||||
XEN_CONFIGS += xmexample2
|
||||
XEN_CONFIGS += xmexample.vmx
|
||||
XEN_CONFIGS += xmexample.vti
|
||||
|
||||
# Xen script dir and scripts to go there.
|
||||
XEN_SCRIPT_DIR = /etc/xen/scripts
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
# -*- mode: python; -*-
|
||||
#============================================================================
|
||||
# Python configuration setup for 'xm create'.
|
||||
# This script sets the parameters used when a domain is created using 'xm create'.
|
||||
# You use a separate script for each domain you want to create, or
|
||||
# you can set the parameters for the domain on the xm command line.
|
||||
#============================================================================
|
||||
|
||||
import os, re
|
||||
arch = os.uname()[4]
|
||||
arch_libdir = 'lib'
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Kernel image file.
|
||||
kernel = "/boot/Flash.fd"
|
||||
|
||||
# The domain build function. VMX domain uses 'vmx'.
|
||||
builder='vmx'
|
||||
|
||||
# Initial memory allocation (in megabytes) for the new domain.
|
||||
memory = 256
|
||||
|
||||
# A name for your domain. All domains must have different names.
|
||||
name = "ExampleVMXDomain"
|
||||
|
||||
# Which CPU to start domain on?
|
||||
#cpu = -1 # leave to Xen to pick
|
||||
|
||||
# Optionally define mac and/or bridge for the network interfaces.
|
||||
# Random MACs are assigned if not given.
|
||||
#vif = [ 'mac=aa:00:00:00:00:11, bridge=xen-br0' ]
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Define the disk devices you want the domain to have access to, and
|
||||
# what you want them accessible as.
|
||||
# Each disk entry is of the form phy:UNAME,DEV,MODE
|
||||
# where UNAME is the device, DEV is the device name the domain will see,
|
||||
# and MODE is r for read-only, w for read-write.
|
||||
|
||||
#disk = [ 'phy:hda1,hda1,r' ]
|
||||
disk = [ 'file:/var/images/xenia64.img,ioemu:hda,w' ]
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# Set according to whether you want the domain restarted when it exits.
|
||||
# The default is 'onreboot', which restarts the domain when it shuts down
|
||||
# with exit code reboot.
|
||||
# Other values are 'always', and 'never'.
|
||||
|
||||
#restart = 'onreboot'
|
||||
|
||||
#============================================================================
|
||||
|
||||
# New stuff
|
||||
device_model = '/usr/' + arch_libdir + '/xen/bin/qemu-dm.debug'
|
||||
|
||||
# Advanced users only. Don't touch if you don't know what you're doing
|
||||
memmap = '/usr/lib/xen/boot/mem-map.sxp'
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# Disk image for
|
||||
#cdrom=
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# boot on floppy (a), hard disk (c) or CD-ROM (d)
|
||||
#boot=[a|c|d]
|
||||
#-----------------------------------------------------------------------------
|
||||
# write to temporary files instead of disk image files
|
||||
#snapshot=1
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# enable SDL library for graphics, default = 0
|
||||
sdl=1
|
||||
|
||||
stdvga=1
|
||||
#----------------------------------------------------------------------------
|
||||
# enable VNC library for graphics, default = 1
|
||||
vnc=0
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# enable spawning vncviewer(only valid when vnc=1), default = 1
|
||||
vncviewer=0
|
||||
|
||||
#----------------------------------------------------------------------------
|
||||
# no graphics, use serial port
|
||||
#nographic=0
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# enable audio support
|
||||
#enable-audio=1
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# set the real time clock to local time [default=0 i.e. set to utc]
|
||||
#localtime=1
|
||||
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# start in full screen
|
||||
#full-screen=1 diff -r 42cab8724273 tools/libxc/xc_ia64_stubs.c
|
||||
@@ -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
|
||||
|
||||
+653
-16
@@ -1,5 +1,11 @@
|
||||
#include "xg_private.h"
|
||||
#include "xenguest.h"
|
||||
#include "xc_private.h"
|
||||
#include "xc_elf.h"
|
||||
#include <stdlib.h>
|
||||
#include <zlib.h>
|
||||
#include "xen/arch-ia64.h"
|
||||
#include <xen/io/ioreq.h>
|
||||
|
||||
int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
|
||||
uint32_t max_factor, uint32_t flags)
|
||||
@@ -16,22 +22,6 @@ int xc_linux_restore(int xc_handle, int io_fd, uint32_t dom, unsigned long nr_pf
|
||||
return -1;
|
||||
}
|
||||
|
||||
int xc_vmx_build(int xc_handle,
|
||||
uint32_t domid,
|
||||
int memsize,
|
||||
const char *image_name,
|
||||
struct mem_map *mem_mapp,
|
||||
const char *ramdisk_name,
|
||||
const char *cmdline,
|
||||
unsigned int control_evtchn,
|
||||
unsigned int vcpus,
|
||||
unsigned int store_evtchn,
|
||||
unsigned long *store_mfn)
|
||||
{
|
||||
PERROR("xc_vmx_build not implemented\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
xc_plan9_build(int xc_handle,
|
||||
uint32_t domid,
|
||||
@@ -43,6 +33,653 @@ xc_plan9_build(int xc_handle,
|
||||
return -1;
|
||||
}
|
||||
|
||||
int xc_ia64_get_pfn_list(int xc_handle,
|
||||
uint32_t domid,
|
||||
unsigned long *pfn_buf,
|
||||
unsigned int start_page,
|
||||
unsigned int nr_pages)
|
||||
{
|
||||
dom0_op_t op;
|
||||
int ret;
|
||||
unsigned long max_pfns = ((unsigned long)start_page << 32) | nr_pages;
|
||||
|
||||
op.cmd = DOM0_GETMEMLIST;
|
||||
op.u.getmemlist.domain = (domid_t)domid;
|
||||
op.u.getmemlist.max_pfns = max_pfns;
|
||||
op.u.getmemlist.buffer = pfn_buf;
|
||||
|
||||
if ( (max_pfns != -1UL)
|
||||
&& mlock(pfn_buf, nr_pages * sizeof(unsigned long)) != 0 )
|
||||
{
|
||||
PERROR("Could not lock pfn list buffer");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = do_dom0_op(xc_handle, &op);
|
||||
|
||||
if (max_pfns != -1UL)
|
||||
(void)munlock(pfn_buf, nr_pages * sizeof(unsigned long));
|
||||
|
||||
return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
|
||||
}
|
||||
|
||||
long xc_get_max_pages(int xc_handle, uint32_t domid)
|
||||
{
|
||||
dom0_op_t op;
|
||||
op.cmd = DOM0_GETDOMAININFO;
|
||||
op.u.getdomaininfo.domain = (domid_t)domid;
|
||||
return (do_dom0_op(xc_handle, &op) < 0) ?
|
||||
-1 : op.u.getdomaininfo.max_pages;
|
||||
}
|
||||
|
||||
int xc_ia64_copy_to_domain_pages(int xc_handle, uint32_t domid,
|
||||
void* src_page, unsigned long dst_pfn, int nr_pages)
|
||||
{
|
||||
// N.B. gva should be page aligned
|
||||
|
||||
unsigned long *page_array=NULL;
|
||||
int i;
|
||||
|
||||
if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL ){
|
||||
PERROR("Could not allocate memory");
|
||||
goto error_out;
|
||||
}
|
||||
if ( xc_ia64_get_pfn_list(xc_handle, domid, page_array,
|
||||
dst_pfn>>PAGE_SHIFT, nr_pages) != nr_pages ){
|
||||
PERROR("Could not get the page frame list");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
for ( i=0; i< nr_pages; i++ ){
|
||||
if (xc_copy_to_domain_page(xc_handle, domid, page_array[i],
|
||||
src_page + (i << PAGE_SHIFT)))
|
||||
goto error_out;
|
||||
}
|
||||
free(page_array);
|
||||
return 0;
|
||||
|
||||
error_out:
|
||||
if (page_array)
|
||||
free(page_array);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#define HOB_SIGNATURE 0x3436474953424f48 // "HOBSIG64"
|
||||
#define GFW_HOB_START ((4UL<<30)-(14UL<<20)) //4G -14M
|
||||
#define GFW_HOB_SIZE (1UL<<20) //1M
|
||||
#define MEM_G (1UL << 30)
|
||||
#define MEM_M (1UL << 20)
|
||||
|
||||
typedef struct {
|
||||
unsigned long signature;
|
||||
unsigned int type;
|
||||
unsigned int length;
|
||||
} HOB_GENERIC_HEADER;
|
||||
|
||||
/*
|
||||
* INFO HOB is the first data data in one HOB list
|
||||
* it contains the control information of the HOB list
|
||||
*/
|
||||
typedef struct {
|
||||
HOB_GENERIC_HEADER header;
|
||||
unsigned long length; // current length of hob
|
||||
unsigned long cur_pos; // current poisiton of hob
|
||||
unsigned long buf_size; // size of hob buffer
|
||||
}HOB_INFO;
|
||||
|
||||
typedef struct{
|
||||
unsigned long start;
|
||||
unsigned long size;
|
||||
}hob_mem_t;
|
||||
|
||||
typedef enum {
|
||||
HOB_TYPE_INFO=0,
|
||||
HOB_TYPE_TERMINAL,
|
||||
HOB_TYPE_MEM,
|
||||
HOB_TYPE_PAL_BUS_GET_FEATURES_DATA,
|
||||
HOB_TYPE_PAL_CACHE_SUMMARY,
|
||||
HOB_TYPE_PAL_MEM_ATTRIB,
|
||||
HOB_TYPE_PAL_CACHE_INFO,
|
||||
HOB_TYPE_PAL_CACHE_PROT_INFO,
|
||||
HOB_TYPE_PAL_DEBUG_INFO,
|
||||
HOB_TYPE_PAL_FIXED_ADDR,
|
||||
HOB_TYPE_PAL_FREQ_BASE,
|
||||
HOB_TYPE_PAL_FREQ_RATIOS,
|
||||
HOB_TYPE_PAL_HALT_INFO,
|
||||
HOB_TYPE_PAL_PERF_MON_INFO,
|
||||
HOB_TYPE_PAL_PROC_GET_FEATURES,
|
||||
HOB_TYPE_PAL_PTCE_INFO,
|
||||
HOB_TYPE_PAL_REGISTER_INFO,
|
||||
HOB_TYPE_PAL_RSE_INFO,
|
||||
HOB_TYPE_PAL_TEST_INFO,
|
||||
HOB_TYPE_PAL_VM_SUMMARY,
|
||||
HOB_TYPE_PAL_VM_INFO,
|
||||
HOB_TYPE_PAL_VM_PAGE_SIZE,
|
||||
HOB_TYPE_MAX
|
||||
}hob_type_t;
|
||||
|
||||
static int hob_init( void *buffer ,unsigned long buf_size);
|
||||
static int add_pal_hob(void* hob_buf);
|
||||
static int add_mem_hob(void* hob_buf, unsigned long dom_mem_size);
|
||||
static int build_hob (void* hob_buf, unsigned long hob_buf_size,
|
||||
unsigned long dom_mem_size);
|
||||
static int load_hob(int xc_handle,uint32_t dom, void *hob_buf);
|
||||
|
||||
int xc_ia64_build_hob(int xc_handle, uint32_t dom, unsigned long memsize){
|
||||
|
||||
char hob_buf[GFW_HOB_SIZE];
|
||||
|
||||
if ( build_hob( hob_buf, GFW_HOB_SIZE, memsize<<20) < 0){
|
||||
PERROR("Could not build hob");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( load_hob( xc_handle, dom, hob_buf) <0){
|
||||
PERROR("Could not load hob");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
static int
|
||||
hob_init( void *buffer ,unsigned long buf_size)
|
||||
{
|
||||
HOB_INFO *phit;
|
||||
HOB_GENERIC_HEADER *terminal;
|
||||
|
||||
if (sizeof(HOB_INFO) + sizeof(HOB_GENERIC_HEADER) > buf_size){
|
||||
// buffer too small
|
||||
return -1;
|
||||
}
|
||||
|
||||
phit = (HOB_INFO*)buffer;
|
||||
phit->header.signature = HOB_SIGNATURE;
|
||||
phit->header.type = HOB_TYPE_INFO;
|
||||
phit->header.length = sizeof(HOB_INFO);
|
||||
phit->length = sizeof(HOB_INFO) + sizeof(HOB_GENERIC_HEADER);
|
||||
phit->cur_pos = 0;
|
||||
phit->buf_size = buf_size;
|
||||
|
||||
terminal = (HOB_GENERIC_HEADER*) (buffer + sizeof(HOB_INFO));
|
||||
terminal->signature= HOB_SIGNATURE;
|
||||
terminal->type = HOB_TYPE_TERMINAL;
|
||||
terminal->length = sizeof(HOB_GENERIC_HEADER);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a new HOB to the HOB List.
|
||||
*
|
||||
* hob_start - start address of hob buffer
|
||||
* type - type of the hob to be added
|
||||
* data - data of the hob to be added
|
||||
* data_size - size of the data
|
||||
*/
|
||||
static int
|
||||
hob_add(
|
||||
void* hob_start,
|
||||
int type,
|
||||
void* data,
|
||||
int data_size
|
||||
)
|
||||
{
|
||||
HOB_INFO *phit;
|
||||
HOB_GENERIC_HEADER *newhob,*tail;
|
||||
|
||||
phit = (HOB_INFO*)hob_start;
|
||||
|
||||
if (phit->length + data_size > phit->buf_size){
|
||||
// no space for new hob
|
||||
return -1;
|
||||
}
|
||||
|
||||
//append new HOB
|
||||
newhob = (HOB_GENERIC_HEADER*)
|
||||
(hob_start + phit->length - sizeof(HOB_GENERIC_HEADER));
|
||||
newhob->signature = HOB_SIGNATURE;
|
||||
newhob->type = type;
|
||||
newhob->length = data_size + sizeof(HOB_GENERIC_HEADER);
|
||||
memcpy((void*)newhob + sizeof(HOB_GENERIC_HEADER), data, data_size);
|
||||
|
||||
// append terminal HOB
|
||||
tail = (HOB_GENERIC_HEADER*) ( hob_start + phit->length + data_size);
|
||||
tail->signature = HOB_SIGNATURE;
|
||||
tail->type = HOB_TYPE_TERMINAL;
|
||||
tail->length = sizeof(HOB_GENERIC_HEADER);
|
||||
|
||||
// adjust HOB list length
|
||||
phit->length += sizeof(HOB_GENERIC_HEADER)+ data_size;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int get_hob_size(void* hob_buf){
|
||||
|
||||
HOB_INFO *phit = (HOB_INFO*)hob_buf;
|
||||
|
||||
if (phit->header.signature != HOB_SIGNATURE){
|
||||
PERROR("xc_get_hob_size:Incorrect signature");
|
||||
return -1;
|
||||
}
|
||||
return phit->length;
|
||||
}
|
||||
|
||||
int build_hob (void* hob_buf, unsigned long hob_buf_size,
|
||||
unsigned long dom_mem_size)
|
||||
{
|
||||
//Init HOB List
|
||||
if (hob_init (hob_buf, hob_buf_size)<0){
|
||||
PERROR("buffer too small");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if ( add_mem_hob( hob_buf,dom_mem_size) < 0){
|
||||
PERROR("Add memory hob failed, buffer too small");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
if ( add_pal_hob( hob_buf ) < 0 ){
|
||||
PERROR("Add PAL hob failed, buffer too small");
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
load_hob(int xc_handle, uint32_t dom, void *hob_buf)
|
||||
{
|
||||
// hob_buf should be page aligned
|
||||
int hob_size;
|
||||
int nr_pages;
|
||||
|
||||
if ((hob_size = get_hob_size(hob_buf)) < 0){
|
||||
PERROR("Invalid hob data");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hob_size > GFW_HOB_SIZE){
|
||||
PERROR("No enough memory for hob data");
|
||||
return -1;
|
||||
}
|
||||
|
||||
nr_pages = (hob_size + PAGE_SIZE -1) >> PAGE_SHIFT;
|
||||
|
||||
return xc_ia64_copy_to_domain_pages(xc_handle, dom,
|
||||
hob_buf, GFW_HOB_START, nr_pages );
|
||||
}
|
||||
|
||||
#define MIN(x, y) ((x) < (y)) ? (x) : (y)
|
||||
static int
|
||||
add_mem_hob(void* hob_buf, unsigned long dom_mem_size){
|
||||
hob_mem_t memhob;
|
||||
|
||||
// less than 3G
|
||||
memhob.start = 0;
|
||||
memhob.size = MIN(dom_mem_size, 0xC0000000);
|
||||
|
||||
if (hob_add(hob_buf, HOB_TYPE_MEM, &memhob, sizeof(memhob)) < 0){
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (dom_mem_size > 0xC0000000) {
|
||||
// 4G ~ 4G+remain
|
||||
memhob.start = 0x100000000; //4G
|
||||
memhob.size = dom_mem_size - 0xC0000000;
|
||||
if (hob_add(hob_buf, HOB_TYPE_MEM, &memhob, sizeof(memhob)) < 0)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char config_pal_bus_get_features_data[24] = {
|
||||
0, 0, 0, 32, 0, 0, 240, 189, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
unsigned char config_pal_cache_summary[16] = {
|
||||
3, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0};
|
||||
unsigned char config_pal_mem_attrib[8] = {
|
||||
241, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
unsigned char config_pal_cache_info[152] = {
|
||||
3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
6, 4, 6, 7, 255, 1, 0, 1, 0, 64, 0, 0, 12, 12,
|
||||
49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 7, 0, 1,
|
||||
0, 1, 0, 64, 0, 0, 12, 12, 49, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 6, 8, 7, 7, 255, 7, 0, 11, 0, 0, 16, 0,
|
||||
12, 17, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 7,
|
||||
7, 7, 5, 9, 11, 0, 0, 4, 0, 12, 15, 49, 0, 254, 255,
|
||||
255, 255, 255, 255, 255, 255, 2, 8, 7, 7, 7, 5, 9,
|
||||
11, 0, 0, 4, 0, 12, 15, 49, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 3, 12, 7, 7, 7, 14, 1, 3, 0, 0, 192, 0, 12, 20, 49, 0
|
||||
};
|
||||
unsigned char config_pal_cache_prot_info[200] = {
|
||||
3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
45, 0, 16, 8, 0, 76, 12, 64, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
8, 0, 16, 4, 0, 76, 44, 68, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32,
|
||||
0, 16, 8, 0, 81, 44, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0,
|
||||
112, 12, 0, 79, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 254, 255, 255, 255, 255, 255, 255, 255,
|
||||
32, 0, 112, 12, 0, 79, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 160,
|
||||
12, 0, 84, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0
|
||||
};
|
||||
unsigned char config_pal_debug_info[16] = {
|
||||
2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
unsigned char config_pal_fixed_addr[8] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
unsigned char config_pal_freq_base[8] = {
|
||||
109, 219, 182, 13, 0, 0, 0, 0
|
||||
};
|
||||
unsigned char config_pal_freq_ratios[24] = {
|
||||
11, 1, 0, 0, 77, 7, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 4,
|
||||
0, 0, 0, 7, 0, 0, 0
|
||||
};
|
||||
unsigned char config_pal_halt_info[64] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
unsigned char config_pal_perf_mon_info[136] = {
|
||||
12, 47, 18, 8, 0, 0, 0, 0, 241, 255, 0, 0, 255, 7, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 241, 255, 0, 0, 223, 0, 255, 255,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 240, 255, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 240, 255, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
unsigned char config_pal_proc_get_features[104] = {
|
||||
3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 64, 6, 64, 49, 0, 0, 0, 0, 64, 6, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0,
|
||||
231, 0, 0, 0, 0, 0, 0, 0, 228, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0,
|
||||
63, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
unsigned char config_pal_ptce_info[24] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
unsigned char config_pal_register_info[64] = {
|
||||
255, 0, 47, 127, 17, 17, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
255, 208, 128, 238, 238, 0, 0, 248, 255, 255, 255, 255, 255, 0, 0, 7, 3,
|
||||
251, 3, 0, 0, 0, 0, 255, 7, 3, 0, 0, 0, 0, 0, 248, 252, 4,
|
||||
252, 255, 255, 255, 255, 2, 248, 252, 255, 255, 255, 255, 255
|
||||
};
|
||||
unsigned char config_pal_rse_info[16] = {
|
||||
96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
unsigned char config_pal_test_info[48] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
unsigned char config_pal_vm_summary[16] = {
|
||||
101, 18, 15, 2, 7, 7, 4, 2, 59, 18, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
unsigned char config_pal_vm_info[104] = {
|
||||
2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||
32, 32, 0, 0, 0, 0, 0, 0, 112, 85, 21, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 1, 32, 32, 0, 0, 0, 0, 0, 0, 112, 85,
|
||||
21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 128, 128, 0,
|
||||
4, 0, 0, 0, 0, 112, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 1, 128, 128, 0, 4, 0, 0, 0, 0, 112, 85, 0, 0, 0, 0, 0
|
||||
};
|
||||
unsigned char config_pal_vm_page_size[16] = {
|
||||
0, 112, 85, 21, 0, 0, 0, 0, 0, 112, 85, 21, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
typedef struct{
|
||||
hob_type_t type;
|
||||
void* data;
|
||||
unsigned long size;
|
||||
}hob_batch_t;
|
||||
|
||||
hob_batch_t hob_batch[]={
|
||||
{ HOB_TYPE_PAL_BUS_GET_FEATURES_DATA,
|
||||
&config_pal_bus_get_features_data,
|
||||
sizeof(config_pal_bus_get_features_data)
|
||||
},
|
||||
{ HOB_TYPE_PAL_CACHE_SUMMARY,
|
||||
&config_pal_cache_summary,
|
||||
sizeof(config_pal_cache_summary)
|
||||
},
|
||||
{ HOB_TYPE_PAL_MEM_ATTRIB,
|
||||
&config_pal_mem_attrib,
|
||||
sizeof(config_pal_mem_attrib)
|
||||
},
|
||||
{ HOB_TYPE_PAL_CACHE_INFO,
|
||||
&config_pal_cache_info,
|
||||
sizeof(config_pal_cache_info)
|
||||
},
|
||||
{ HOB_TYPE_PAL_CACHE_PROT_INFO,
|
||||
&config_pal_cache_prot_info,
|
||||
sizeof(config_pal_cache_prot_info)
|
||||
},
|
||||
{ HOB_TYPE_PAL_DEBUG_INFO,
|
||||
&config_pal_debug_info,
|
||||
sizeof(config_pal_debug_info)
|
||||
},
|
||||
{ HOB_TYPE_PAL_FIXED_ADDR,
|
||||
&config_pal_fixed_addr,
|
||||
sizeof(config_pal_fixed_addr)
|
||||
},
|
||||
{ HOB_TYPE_PAL_FREQ_BASE,
|
||||
&config_pal_freq_base,
|
||||
sizeof(config_pal_freq_base)
|
||||
},
|
||||
{ HOB_TYPE_PAL_FREQ_RATIOS,
|
||||
&config_pal_freq_ratios,
|
||||
sizeof(config_pal_freq_ratios)
|
||||
},
|
||||
{ HOB_TYPE_PAL_HALT_INFO,
|
||||
&config_pal_halt_info,
|
||||
sizeof(config_pal_halt_info)
|
||||
},
|
||||
{ HOB_TYPE_PAL_PERF_MON_INFO,
|
||||
&config_pal_perf_mon_info,
|
||||
sizeof(config_pal_perf_mon_info)
|
||||
},
|
||||
{ HOB_TYPE_PAL_PROC_GET_FEATURES,
|
||||
&config_pal_proc_get_features,
|
||||
sizeof(config_pal_proc_get_features)
|
||||
},
|
||||
{ HOB_TYPE_PAL_PTCE_INFO,
|
||||
&config_pal_ptce_info,
|
||||
sizeof(config_pal_ptce_info)
|
||||
},
|
||||
{ HOB_TYPE_PAL_REGISTER_INFO,
|
||||
&config_pal_register_info,
|
||||
sizeof(config_pal_register_info)
|
||||
},
|
||||
{ HOB_TYPE_PAL_RSE_INFO,
|
||||
&config_pal_rse_info,
|
||||
sizeof(config_pal_rse_info)
|
||||
},
|
||||
{ HOB_TYPE_PAL_TEST_INFO,
|
||||
&config_pal_test_info,
|
||||
sizeof(config_pal_test_info)
|
||||
},
|
||||
{ HOB_TYPE_PAL_VM_SUMMARY,
|
||||
&config_pal_vm_summary,
|
||||
sizeof(config_pal_vm_summary)
|
||||
},
|
||||
{ HOB_TYPE_PAL_VM_INFO,
|
||||
&config_pal_vm_info,
|
||||
sizeof(config_pal_vm_info)
|
||||
},
|
||||
{ HOB_TYPE_PAL_VM_PAGE_SIZE,
|
||||
&config_pal_vm_page_size,
|
||||
sizeof(config_pal_vm_page_size)
|
||||
},
|
||||
};
|
||||
|
||||
static int add_pal_hob(void* hob_buf){
|
||||
int i;
|
||||
for (i=0; i<sizeof(hob_batch)/sizeof(hob_batch_t); i++){
|
||||
if (hob_add(hob_buf, hob_batch[i].type,
|
||||
hob_batch[i].data,
|
||||
hob_batch[i].size)<0)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setup_guest( int xc_handle,
|
||||
uint32_t dom, unsigned long memsize,
|
||||
char *image, unsigned long image_size,
|
||||
unsigned int control_evtchn,
|
||||
unsigned int store_evtchn,
|
||||
unsigned long *store_mfn)
|
||||
{
|
||||
unsigned long page_array[2];
|
||||
shared_iopage_t *sp;
|
||||
// FIXME: initialize pfn list for a temp hack
|
||||
if (xc_ia64_get_pfn_list(xc_handle, dom, NULL, -1, -1) == -1) {
|
||||
PERROR("Could not allocate continuous memory");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if ((image_size > 12 * MEM_M) || (image_size & (PAGE_SIZE - 1))) {
|
||||
PERROR("Guest firmware size is incorrect [%ld]?", image_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Load guest firmware */
|
||||
if( xc_ia64_copy_to_domain_pages( xc_handle, dom,
|
||||
image, 4*MEM_G-image_size, image_size>>PAGE_SHIFT)) {
|
||||
PERROR("Could not load guest firmware into domain");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
/* Hand-off state passed to guest firmware */
|
||||
if (xc_ia64_build_hob(xc_handle, dom, memsize) < 0){
|
||||
PERROR("Could not build hob\n");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
/* Retrieve special pages like io, xenstore, etc. */
|
||||
if ( xc_ia64_get_pfn_list(xc_handle, dom, page_array, IO_PAGE_START>>PAGE_SHIFT, 2) != 2 )
|
||||
{
|
||||
PERROR("Could not get the page frame list");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
*store_mfn = page_array[1];
|
||||
if ((sp = (shared_iopage_t *) xc_map_foreign_range(
|
||||
xc_handle, dom, PAGE_SIZE, PROT_READ|PROT_WRITE,
|
||||
page_array[0])) == 0)
|
||||
goto error_out;
|
||||
memset(sp, 0, PAGE_SIZE);
|
||||
sp->sp_global.eport = control_evtchn;
|
||||
munmap(sp, PAGE_SIZE);
|
||||
|
||||
return 0;
|
||||
|
||||
error_out:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int xc_vmx_build(int xc_handle,
|
||||
uint32_t domid,
|
||||
int memsize,
|
||||
const char *image_name,
|
||||
unsigned int control_evtchn,
|
||||
unsigned int vcpus,
|
||||
unsigned int store_evtchn,
|
||||
unsigned long *store_mfn)
|
||||
{
|
||||
dom0_op_t launch_op, op;
|
||||
int rc ;
|
||||
vcpu_guest_context_t st_ctxt, *ctxt = &st_ctxt;
|
||||
char *image = NULL;
|
||||
unsigned long image_size;
|
||||
unsigned long nr_pages;
|
||||
|
||||
if ( (nr_pages = xc_get_max_pages(xc_handle, domid)) < 0 )
|
||||
{
|
||||
PERROR("Could not find total pages for domain");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if ( (image = xc_read_kernel_image(image_name, &image_size)) == NULL ){
|
||||
PERROR("Could not read guest firmware image %s",image_name);
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
image_size = (image_size + PAGE_SIZE - 1) & PAGE_MASK;
|
||||
|
||||
if ( mlock(&st_ctxt, sizeof(st_ctxt) ) ){
|
||||
PERROR("Unable to mlock ctxt");
|
||||
return 1;
|
||||
}
|
||||
|
||||
op.cmd = DOM0_GETDOMAININFO;
|
||||
op.u.getdomaininfo.domain = (domid_t)domid;
|
||||
if ( (do_dom0_op(xc_handle, &op) < 0) ||
|
||||
((uint16_t)op.u.getdomaininfo.domain != domid) ) {
|
||||
PERROR("Could not get info on domain");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if ( xc_domain_get_vcpu_context(xc_handle, domid, 0, ctxt) ){
|
||||
PERROR("Could not get vcpu context");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if ( !(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) ) {
|
||||
ERROR("Domain is already constructed");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if ( setup_guest(xc_handle, domid, (unsigned long)memsize, image, image_size,
|
||||
control_evtchn, store_evtchn, store_mfn ) < 0 ){
|
||||
ERROR("Error constructing guest OS");
|
||||
goto error_out;
|
||||
}
|
||||
|
||||
if ( image != NULL )
|
||||
free(image);
|
||||
|
||||
ctxt->flags = VGCF_VMX_GUEST;
|
||||
ctxt->regs.cr_iip = 0x80000000ffffffb0UL;
|
||||
ctxt->vcpu.privregs = 0;
|
||||
|
||||
memset( &launch_op, 0, sizeof(launch_op) );
|
||||
|
||||
launch_op.u.setdomaininfo.domain = (domid_t)domid;
|
||||
launch_op.u.setdomaininfo.vcpu = 0;
|
||||
launch_op.u.setdomaininfo.ctxt = ctxt;
|
||||
|
||||
launch_op.cmd = DOM0_SETDOMAININFO;
|
||||
rc = do_dom0_op(xc_handle, &launch_op);
|
||||
return rc;
|
||||
|
||||
error_out:
|
||||
if ( image != NULL )
|
||||
free(image);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -313,46 +313,6 @@ int xc_get_pfn_list(int xc_handle,
|
||||
return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
|
||||
}
|
||||
|
||||
#ifdef __ia64__
|
||||
int xc_ia64_get_pfn_list(int xc_handle,
|
||||
uint32_t domid,
|
||||
unsigned long *pfn_buf,
|
||||
unsigned int start_page,
|
||||
unsigned int nr_pages)
|
||||
{
|
||||
dom0_op_t op;
|
||||
int ret;
|
||||
|
||||
op.cmd = DOM0_GETMEMLIST;
|
||||
op.u.getmemlist.domain = (domid_t)domid;
|
||||
op.u.getmemlist.max_pfns = ((unsigned long)start_page << 32) | nr_pages;
|
||||
op.u.getmemlist.buffer = pfn_buf;
|
||||
|
||||
if ( mlock(pfn_buf, nr_pages * sizeof(unsigned long)) != 0 )
|
||||
{
|
||||
PERROR("Could not lock pfn list buffer");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* XXX Hack to put pages in TLB, hypervisor should be able to handle this */
|
||||
memset(pfn_buf, 0, nr_pages * sizeof(unsigned long));
|
||||
ret = do_dom0_op(xc_handle, &op);
|
||||
|
||||
(void)munlock(pfn_buf, nr_pages * sizeof(unsigned long));
|
||||
|
||||
return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
|
||||
}
|
||||
|
||||
long xc_get_max_pages(int xc_handle, uint32_t domid)
|
||||
{
|
||||
dom0_op_t op;
|
||||
op.cmd = DOM0_GETDOMAININFO;
|
||||
op.u.getdomaininfo.domain = (domid_t)domid;
|
||||
return (do_dom0_op(xc_handle, &op) < 0) ?
|
||||
-1 : op.u.getdomaininfo.max_pages;
|
||||
}
|
||||
#endif
|
||||
|
||||
long xc_get_tot_pages(int xc_handle, uint32_t domid)
|
||||
{
|
||||
dom0_op_t op;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -414,6 +414,12 @@ int xc_ia64_get_pfn_list(int xc_handle, uint32_t domid,
|
||||
unsigned long *pfn_buf,
|
||||
unsigned int start_page, unsigned int nr_pages);
|
||||
|
||||
int xc_copy_to_domain_page(int xc_handle, uint32_t domid,
|
||||
unsigned long dst_pfn, void *src_page);
|
||||
|
||||
int xc_ia64_copy_to_domain_pages(int xc_handle, uint32_t domid,
|
||||
void* src_page, unsigned long dst_pfn, int nr_pages);
|
||||
|
||||
long xc_get_max_pages(int xc_handle, uint32_t domid);
|
||||
|
||||
int xc_mmuext_op(int xc_handle, struct mmuext_op *op, unsigned int nr_ops,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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())
|
||||
|
||||
|
||||
@@ -342,12 +348,15 @@ class VmxImageHandler(ImageHandler):
|
||||
|
||||
def getDomainMemory(self, mem):
|
||||
"""@see ImageHandler.getDomainMemory"""
|
||||
page_kb = 4
|
||||
if os.uname()[4] == 'ia64':
|
||||
page_kb = 16
|
||||
# for ioreq_t and xenstore
|
||||
static_pages = 2
|
||||
return mem + self.getPageTableSize(mem / 1024) + 4 * static_pages
|
||||
return mem + (self.getPageTableSize(mem / 1024) + static_pages) * page_kb
|
||||
|
||||
def getPageTableSize(self, mem_mb):
|
||||
"""Return the size of memory needed for 1:1 page tables for physical
|
||||
"""Return the pages of memory needed for 1:1 page tables for physical
|
||||
mode.
|
||||
|
||||
@param mem_mb: size in MB
|
||||
@@ -355,13 +364,13 @@ class VmxImageHandler(ImageHandler):
|
||||
"""
|
||||
# 1 page for the PGD + 1 pte page for 4MB of memory (rounded)
|
||||
if os.uname()[4] == 'x86_64':
|
||||
return (5 + ((mem_mb + 1) >> 1)) * 4
|
||||
return 5 + ((mem_mb + 1) >> 1)
|
||||
elif os.uname()[4] == 'ia64':
|
||||
# XEN/IA64 has p2m table allocated on demand, so only return
|
||||
# guest firmware size here.
|
||||
return 16 * 1024
|
||||
# 1:1 pgtable is allocated on demand ia64, so just return rom size
|
||||
# for guest firmware
|
||||
return 1024
|
||||
else:
|
||||
return (1 + ((mem_mb + 3) >> 2)) * 4
|
||||
return 1 + ((mem_mb + 3) >> 2)
|
||||
|
||||
|
||||
"""Table of image handler classes for virtual machine images. Indexed by
|
||||
|
||||
@@ -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()
|
||||
Whitespace-only changes.
@@ -157,6 +157,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.")
|
||||
@@ -315,10 +319,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.")
|
||||
@@ -556,9 +556,9 @@ def configure_vfr(config, vals):
|
||||
def configure_vmx(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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -59,6 +59,8 @@ void foo(void)
|
||||
DEFINE(XSI_BANKNUM_OFS, offsetof(mapped_regs_t, banknum));
|
||||
DEFINE(XSI_BANK0_OFS, offsetof(mapped_regs_t, bank0_regs[0]));
|
||||
DEFINE(XSI_BANK1_OFS, offsetof(mapped_regs_t, bank1_regs[0]));
|
||||
DEFINE(XSI_B0NATS_OFS, offsetof(mapped_regs_t, vbnat));
|
||||
DEFINE(XSI_B1NATS_OFS, offsetof(mapped_regs_t, vnat));
|
||||
DEFINE(XSI_RR0_OFS, offsetof(mapped_regs_t, rrs[0]));
|
||||
DEFINE(XSI_METAPHYS_OFS, offsetof(mapped_regs_t, metaphysical_mode));
|
||||
DEFINE(XSI_PRECOVER_IFS_OFS, offsetof(mapped_regs_t, precover_ifs));
|
||||
@@ -79,13 +81,17 @@ void foo(void)
|
||||
//DEFINE(IA64_TASK_SIGHAND_OFFSET,offsetof (struct task_struct, sighand));
|
||||
//DEFINE(IA64_TASK_SIGNAL_OFFSET,offsetof (struct task_struct, signal));
|
||||
//DEFINE(IA64_TASK_TGID_OFFSET, offsetof (struct task_struct, tgid));
|
||||
DEFINE(IA64_PGD, offsetof(struct domain, arch.mm));
|
||||
DEFINE(IA64_TASK_THREAD_KSP_OFFSET, offsetof (struct vcpu, arch._thread.ksp));
|
||||
DEFINE(IA64_TASK_THREAD_ON_USTACK_OFFSET, offsetof (struct vcpu, arch._thread.on_ustack));
|
||||
|
||||
DEFINE(IA64_VCPU_DOMAIN_OFFSET, offsetof (struct vcpu, domain));
|
||||
DEFINE(IA64_VCPU_META_RR0_OFFSET, offsetof (struct vcpu, arch.metaphysical_rr0));
|
||||
DEFINE(IA64_VCPU_META_SAVED_RR0_OFFSET, offsetof (struct vcpu, arch.metaphysical_saved_rr0));
|
||||
DEFINE(IA64_VCPU_BREAKIMM_OFFSET, offsetof (struct vcpu, arch.breakimm));
|
||||
DEFINE(IA64_VCPU_IVA_OFFSET, offsetof (struct vcpu, arch.iva));
|
||||
DEFINE(IA64_VCPU_DTLB_PTE_OFFSET, offsetof (struct vcpu, arch.dtlb_pte));
|
||||
DEFINE(IA64_VCPU_ITLB_PTE_OFFSET, offsetof (struct vcpu, arch.itlb_pte));
|
||||
DEFINE(IA64_VCPU_IRR0_OFFSET, offsetof (struct vcpu, arch.irr[0]));
|
||||
DEFINE(IA64_VCPU_IRR3_OFFSET, offsetof (struct vcpu, arch.irr[3]));
|
||||
DEFINE(IA64_VCPU_INSVC3_OFFSET, offsetof (struct vcpu, arch.insvc[3]));
|
||||
|
||||
@@ -900,10 +900,17 @@ GLOBAL_ENTRY(ia64_leave_kernel)
|
||||
adds r7 = PT(EML_UNAT)+16,r12
|
||||
;;
|
||||
ld8 r7 = [r7]
|
||||
;;
|
||||
#if 0
|
||||
leave_kernel_self:
|
||||
cmp.ne p8,p0 = r0, r7
|
||||
(p8) br.sptk.few leave_kernel_self
|
||||
;;
|
||||
#endif
|
||||
(p6) br.call.sptk.many b0=deliver_pending_interrupt
|
||||
;;
|
||||
mov ar.pfs=loc0
|
||||
mov ar.unat=r7 /* load eml_unat */
|
||||
mov ar.unat=r7 /* load eml_unat */
|
||||
mov r31=r0
|
||||
|
||||
|
||||
|
||||
@@ -324,6 +324,9 @@ start_ap:
|
||||
mov r16=-1
|
||||
(isBP) br.cond.dpnt .load_current // BP stack is on region 5 --- no need to map it
|
||||
|
||||
#ifndef XEN
|
||||
// XEN: stack is allocated in xenheap, which is currently always
|
||||
// mapped.
|
||||
// load mapping for stack (virtaddr in r2, physaddr in r3)
|
||||
rsm psr.ic
|
||||
movl r17=PAGE_KERNEL
|
||||
@@ -353,7 +356,8 @@ start_ap:
|
||||
ssm psr.ic
|
||||
srlz.d
|
||||
;;
|
||||
|
||||
#endif
|
||||
|
||||
.load_current:
|
||||
// load the "current" pointer (r13) and ar.k6 with the current task
|
||||
#if defined(XEN) && defined(VALIDATE_VT)
|
||||
|
||||
@@ -281,5 +281,8 @@ ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect)
|
||||
ipi_data = (delivery_mode << 8) | (vector & 0xff);
|
||||
ipi_addr = ipi_base_addr + ((phys_cpu_id << 4) | ((redirect & 1) << 3));
|
||||
|
||||
#ifdef XEN
|
||||
printf ("send_ipi to %d (%x)\n", cpu, phys_cpu_id);
|
||||
#endif
|
||||
writeq(ipi_data, ipi_addr);
|
||||
}
|
||||
@@ -193,8 +193,8 @@ per_cpu_init (void)
|
||||
*/
|
||||
if (smp_processor_id() == 0) {
|
||||
#ifdef XEN
|
||||
cpu_data = alloc_xenheap_pages(PERCPU_PAGE_SHIFT -
|
||||
PAGE_SHIFT + get_order(NR_CPUS));
|
||||
cpu_data = alloc_xenheap_pages(get_order(NR_CPUS
|
||||
* PERCPU_PAGE_SIZE));
|
||||
#else
|
||||
cpu_data = __alloc_bootmem(PERCPU_PAGE_SIZE * NR_CPUS,
|
||||
PERCPU_PAGE_SIZE, __pa(MAX_DMA_ADDRESS));
|
||||
|
||||
@@ -366,6 +366,7 @@ check_for_logical_procs (void)
|
||||
}
|
||||
#endif
|
||||
|
||||
void __init
|
||||
#ifdef XEN
|
||||
early_setup_arch (char **cmdline_p)
|
||||
#else
|
||||
@@ -377,14 +378,12 @@ setup_arch (char **cmdline_p)
|
||||
ia64_patch_vtop((u64) __start___vtop_patchlist, (u64) __end___vtop_patchlist);
|
||||
|
||||
*cmdline_p = __va(ia64_boot_param->command_line);
|
||||
#ifdef XEN
|
||||
efi_init();
|
||||
#else
|
||||
#ifndef XEN
|
||||
strlcpy(saved_command_line, *cmdline_p, COMMAND_LINE_SIZE);
|
||||
#endif
|
||||
|
||||
efi_init();
|
||||
io_port_init();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IA64_GENERIC
|
||||
{
|
||||
@@ -414,11 +413,17 @@ setup_arch (char **cmdline_p)
|
||||
#ifdef XEN
|
||||
early_cmdline_parse(cmdline_p);
|
||||
cmdline_parse(*cmdline_p);
|
||||
#undef CONFIG_ACPI_BOOT
|
||||
#endif
|
||||
if (early_console_setup(*cmdline_p) == 0)
|
||||
mark_bsp_online();
|
||||
|
||||
#ifdef XEN
|
||||
}
|
||||
|
||||
void __init
|
||||
late_setup_arch (char **cmdline_p)
|
||||
{
|
||||
#endif
|
||||
#ifdef CONFIG_ACPI_BOOT
|
||||
/* Initialize the ACPI boot-time table parser */
|
||||
acpi_table_init();
|
||||
@@ -433,20 +438,16 @@ setup_arch (char **cmdline_p)
|
||||
|
||||
#ifndef XEN
|
||||
find_memory();
|
||||
#else
|
||||
io_port_init();
|
||||
}
|
||||
|
||||
void __init
|
||||
late_setup_arch (char **cmdline_p)
|
||||
{
|
||||
#undef CONFIG_ACPI_BOOT
|
||||
acpi_table_init();
|
||||
#endif
|
||||
|
||||
/* process SAL system table: */
|
||||
ia64_sal_init(efi.sal_systab);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#ifdef XEN
|
||||
init_smp_config ();
|
||||
#endif
|
||||
|
||||
cpu_physical_id(0) = hard_smp_processor_id();
|
||||
|
||||
cpu_set(0, cpu_sibling_map[0]);
|
||||
@@ -768,6 +769,11 @@ cpu_init (void)
|
||||
|
||||
cpu_data = per_cpu_init();
|
||||
|
||||
#ifdef XEN
|
||||
printf ("cpu_init: current=%p, current->domain->arch.mm=%p\n",
|
||||
current, current->domain->arch.mm);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* We set ar.k3 so that assembly code in MCA handler can compute
|
||||
* physical addresses of per cpu variables with a simple:
|
||||
@@ -887,6 +893,16 @@ cpu_init (void)
|
||||
#ifndef XEN
|
||||
pm_idle = default_idle;
|
||||
#endif
|
||||
|
||||
#ifdef XEN
|
||||
/* surrender usage of kernel registers to domain, use percpu area instead */
|
||||
__get_cpu_var(cpu_kr)._kr[IA64_KR_IO_BASE] = ia64_get_kr(IA64_KR_IO_BASE);
|
||||
__get_cpu_var(cpu_kr)._kr[IA64_KR_PER_CPU_DATA] = ia64_get_kr(IA64_KR_PER_CPU_DATA);
|
||||
__get_cpu_var(cpu_kr)._kr[IA64_KR_CURRENT_STACK] = ia64_get_kr(IA64_KR_CURRENT_STACK);
|
||||
__get_cpu_var(cpu_kr)._kr[IA64_KR_FPU_OWNER] = ia64_get_kr(IA64_KR_FPU_OWNER);
|
||||
__get_cpu_var(cpu_kr)._kr[IA64_KR_CURRENT] = ia64_get_kr(IA64_KR_CURRENT);
|
||||
__get_cpu_var(cpu_kr)._kr[IA64_KR_PT_BASE] = ia64_get_kr(IA64_KR_PT_BASE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -63,9 +63,18 @@ void flush_tlb_mask(cpumask_t mask)
|
||||
//Huh? This seems to be used on ia64 even if !CONFIG_SMP
|
||||
void smp_send_event_check_mask(cpumask_t mask)
|
||||
{
|
||||
printf("smp_send_event_check_mask called\n");
|
||||
//dummy();
|
||||
//send_IPI_mask(cpu_mask, EVENT_CHECK_VECTOR);
|
||||
int cpu;
|
||||
|
||||
/* Not for me. */
|
||||
cpu_clear(smp_processor_id(), mask);
|
||||
if (cpus_empty(mask))
|
||||
return;
|
||||
|
||||
printf("smp_send_event_check_mask called\n");
|
||||
|
||||
for (cpu = 0; cpu < NR_CPUS; ++cpu)
|
||||
if (cpu_isset(cpu, mask))
|
||||
platform_send_ipi(cpu, IA64_IPI_RESCHEDULE, IA64_IPI_DM_INT, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -249,6 +258,7 @@ send_IPI_self (int op)
|
||||
send_IPI_single(smp_processor_id(), op);
|
||||
}
|
||||
|
||||
#ifndef XEN
|
||||
/*
|
||||
* Called with preeemption disabled.
|
||||
*/
|
||||
@@ -257,6 +267,7 @@ smp_send_reschedule (int cpu)
|
||||
{
|
||||
platform_send_ipi(cpu, IA64_IPI_RESCHEDULE, IA64_IPI_DM_INT, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
smp_flush_tlb_all (void)
|
||||
@@ -395,15 +406,14 @@ smp_call_function (void (*func) (void *info), void *info, int nonatomic, int wai
|
||||
if (wait)
|
||||
atomic_set(&data.finished, 0);
|
||||
|
||||
printk("smp_call_function: about to spin_lock \n");
|
||||
spin_lock(&call_lock);
|
||||
printk("smp_call_function: done with spin_lock \n");
|
||||
#if 0 //def XEN
|
||||
printk("smp_call_function: %d lock\n", smp_processor_id ());
|
||||
#endif
|
||||
|
||||
call_data = &data;
|
||||
mb(); /* ensure store to call_data precedes setting of IPI_CALL_FUNC */
|
||||
printk("smp_call_function: about to send_IPI \n");
|
||||
send_IPI_allbutself(IPI_CALL_FUNC);
|
||||
printk("smp_call_function: done with send_IPI \n");
|
||||
|
||||
/* Wait for response */
|
||||
while (atomic_read(&data.started) != cpus)
|
||||
@@ -414,9 +424,10 @@ smp_call_function (void (*func) (void *info), void *info, int nonatomic, int wai
|
||||
cpu_relax();
|
||||
call_data = NULL;
|
||||
|
||||
printk("smp_call_function: about to spin_unlock \n");
|
||||
spin_unlock(&call_lock);
|
||||
#if 0 //def XEN
|
||||
printk("smp_call_function: DONE WITH spin_unlock, returning \n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(smp_call_function);
|
||||
|
||||
@@ -477,6 +477,22 @@ do_boot_cpu (int sapicid, int cpu)
|
||||
|
||||
do_rest:
|
||||
task_for_booting_cpu = c_idle.idle;
|
||||
#else
|
||||
struct domain *idle;
|
||||
struct vcpu *v;
|
||||
void *stack;
|
||||
|
||||
if ( (idle = do_createdomain(IDLE_DOMAIN_ID, cpu)) == NULL )
|
||||
panic("failed 'createdomain' for CPU %d", cpu);
|
||||
set_bit(_DOMF_idle_domain, &idle->domain_flags);
|
||||
v = idle->vcpu[0];
|
||||
|
||||
printf ("do_boot_cpu: cpu=%d, domain=%p, vcpu=%p\n", cpu, idle, v);
|
||||
|
||||
task_for_booting_cpu = v;
|
||||
|
||||
/* Set cpu number. */
|
||||
get_thread_info(v)->cpu = cpu;
|
||||
#endif
|
||||
|
||||
Dprintk("Sending wakeup vector %lu to AP 0x%x/0x%x.\n", ap_wakeup_vector, cpu, sapicid);
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
*/
|
||||
|
||||
#include <xen/config.h>
|
||||
#include <public/xen.h>
|
||||
//#include <public/xen.h>
|
||||
#include <xen/init.h>
|
||||
#include <xen/lib.h>
|
||||
#include <xen/mm.h>
|
||||
|
||||
@@ -720,11 +720,11 @@ GLOBAL_ENTRY(vmx_switch_rr7)
|
||||
|
||||
// re-pin mappings for guest_vhpt
|
||||
|
||||
mov r24=IA64_TR_VHPT
|
||||
mov r24=IA64_TR_PERVP_VHPT
|
||||
movl r25=PAGE_KERNEL
|
||||
;;
|
||||
or loc5 = r25,loc5 // construct PA | page properties
|
||||
mov r23 = VCPU_TLB_SHIFT<<2
|
||||
mov r23 = IA64_GRANULE_SHIFT <<2
|
||||
;;
|
||||
ptr.d in3,r23
|
||||
;;
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include <xen/config.h>
|
||||
#include <xen/errno.h>
|
||||
#include <asm/vmx_vcpu.h>
|
||||
#include <public/xen.h>
|
||||
//#include <public/xen.h>
|
||||
#include <public/event_channel.h>
|
||||
#include <asm/vmmu.h>
|
||||
#include <asm/tlb.h>
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include <asm/processor.h>
|
||||
#include <asm/vmx.h>
|
||||
#include <xen/mm.h>
|
||||
#include <public/arch-ia64.h>
|
||||
|
||||
/* Global flag to identify whether Intel vmx feature is on */
|
||||
u32 vmx_enabled = 0;
|
||||
@@ -136,39 +137,6 @@ vmx_init_env(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
void vmx_setup_platform(struct vcpu *v, struct vcpu_guest_context *c)
|
||||
{
|
||||
struct domain *d = v->domain;
|
||||
shared_iopage_t *sp;
|
||||
|
||||
ASSERT(d != dom0); /* only for non-privileged vti domain */
|
||||
d->arch.vmx_platform.shared_page_va = __va(c->share_io_pg);
|
||||
sp = get_sp(d);
|
||||
memset((char *)sp,0,PAGE_SIZE);
|
||||
/* FIXME: temp due to old CP */
|
||||
sp->sp_global.eport = 2;
|
||||
#ifdef V_IOSAPIC_READY
|
||||
sp->vcpu_number = 1;
|
||||
#endif
|
||||
/* TEMP */
|
||||
d->arch.vmx_platform.pib_base = 0xfee00000UL;
|
||||
|
||||
/* One more step to enable interrupt assist */
|
||||
set_bit(ARCH_VMX_INTR_ASSIST, &v->arch.arch_vmx.flags);
|
||||
/* Only open one port for I/O and interrupt emulation */
|
||||
if (v == d->vcpu[0]) {
|
||||
memset(&d->shared_info->evtchn_mask[0], 0xff,
|
||||
sizeof(d->shared_info->evtchn_mask));
|
||||
clear_bit(iopacket_port(d), &d->shared_info->evtchn_mask[0]);
|
||||
}
|
||||
|
||||
/* FIXME: only support PMT table continuously by far */
|
||||
// d->arch.pmt = __va(c->pt_base);
|
||||
|
||||
|
||||
vmx_final_setup_domain(d);
|
||||
}
|
||||
|
||||
typedef union {
|
||||
u64 value;
|
||||
struct {
|
||||
@@ -376,40 +344,6 @@ vmx_final_setup_domain(struct domain *d)
|
||||
/* Other vmx specific initialization work */
|
||||
}
|
||||
|
||||
/*
|
||||
* Following stuff should really move to domain builder. However currently
|
||||
* XEN/IA64 doesn't export physical -> machine page table to domain builder,
|
||||
* instead only the copy. Also there's no hypercall to notify hypervisor
|
||||
* IO ranges by far. Let's enhance it later.
|
||||
*/
|
||||
|
||||
#define MEM_G (1UL << 30)
|
||||
#define MEM_M (1UL << 20)
|
||||
|
||||
#define MMIO_START (3 * MEM_G)
|
||||
#define MMIO_SIZE (512 * MEM_M)
|
||||
|
||||
#define VGA_IO_START 0xA0000UL
|
||||
#define VGA_IO_SIZE 0x20000
|
||||
|
||||
#define LEGACY_IO_START (MMIO_START + MMIO_SIZE)
|
||||
#define LEGACY_IO_SIZE (64*MEM_M)
|
||||
|
||||
#define IO_PAGE_START (LEGACY_IO_START + LEGACY_IO_SIZE)
|
||||
#define IO_PAGE_SIZE PAGE_SIZE
|
||||
|
||||
#define STORE_PAGE_START (IO_PAGE_START + IO_PAGE_SIZE)
|
||||
#define STORE_PAGE_SIZE PAGE_SIZE
|
||||
|
||||
#define IO_SAPIC_START 0xfec00000UL
|
||||
#define IO_SAPIC_SIZE 0x100000
|
||||
|
||||
#define PIB_START 0xfee00000UL
|
||||
#define PIB_SIZE 0x100000
|
||||
|
||||
#define GFW_START (4*MEM_G -16*MEM_M)
|
||||
#define GFW_SIZE (16*MEM_M)
|
||||
|
||||
typedef struct io_range {
|
||||
unsigned long start;
|
||||
unsigned long size;
|
||||
@@ -424,18 +358,26 @@ io_range_t io_ranges[] = {
|
||||
{PIB_START, PIB_SIZE, GPFN_PIB},
|
||||
};
|
||||
|
||||
#define VMX_SYS_PAGES (2 + GFW_SIZE >> PAGE_SHIFT)
|
||||
#define VMX_SYS_PAGES (2 + (GFW_SIZE >> PAGE_SHIFT))
|
||||
#define VMX_CONFIG_PAGES(d) ((d)->max_pages - VMX_SYS_PAGES)
|
||||
|
||||
int vmx_alloc_contig_pages(struct domain *d)
|
||||
{
|
||||
unsigned int order, i, j;
|
||||
unsigned long start, end, pgnr, conf_nr;
|
||||
unsigned int order;
|
||||
unsigned long i, j, start, end, pgnr, conf_nr;
|
||||
struct pfn_info *page;
|
||||
struct vcpu *v = d->vcpu[0];
|
||||
|
||||
ASSERT(!test_bit(ARCH_VMX_CONTIG_MEM, &v->arch.arch_vmx.flags));
|
||||
|
||||
/* Mark I/O ranges */
|
||||
for (i = 0; i < (sizeof(io_ranges) / sizeof(io_range_t)); i++) {
|
||||
for (j = io_ranges[i].start;
|
||||
j < io_ranges[i].start + io_ranges[i].size;
|
||||
j += PAGE_SIZE)
|
||||
map_domain_page(d, j, io_ranges[i].type);
|
||||
}
|
||||
|
||||
conf_nr = VMX_CONFIG_PAGES(d);
|
||||
order = get_order_from_pages(conf_nr);
|
||||
if (unlikely((page = alloc_domheap_pages(d, order, 0)) == NULL)) {
|
||||
@@ -462,32 +404,64 @@ int vmx_alloc_contig_pages(struct domain *d)
|
||||
|
||||
d->arch.max_pfn = end >> PAGE_SHIFT;
|
||||
|
||||
order = get_order_from_pages(VMX_SYS_PAGES);
|
||||
order = get_order_from_pages(GFW_SIZE >> PAGE_SHIFT);
|
||||
if (unlikely((page = alloc_domheap_pages(d, order, 0)) == NULL)) {
|
||||
printk("Could not allocate order=%d pages for vmx contig alloc\n",
|
||||
order);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Map guest firmware */
|
||||
pgnr = page_to_pfn(page);
|
||||
for (i = GFW_START; i < GFW_START + GFW_SIZE; i += PAGE_SIZE, pgnr++)
|
||||
map_domain_page(d, i, pgnr << PAGE_SHIFT);
|
||||
|
||||
if (unlikely((page = alloc_domheap_pages(d, 1, 0)) == NULL)) {
|
||||
printk("Could not allocate order=1 pages for vmx contig alloc\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Map for shared I/O page and xenstore */
|
||||
pgnr = page_to_pfn(page);
|
||||
map_domain_page(d, IO_PAGE_START, pgnr << PAGE_SHIFT);
|
||||
pgnr++;
|
||||
map_domain_page(d, STORE_PAGE_START, pgnr << PAGE_SHIFT);
|
||||
pgnr++;
|
||||
|
||||
/* Map guest firmware */
|
||||
for (i = GFW_START; i < GFW_START + GFW_SIZE; i += PAGE_SIZE, pgnr++)
|
||||
map_domain_page(d, i, pgnr << PAGE_SHIFT);
|
||||
|
||||
/* Mark I/O ranges */
|
||||
for (i = 0; i < (sizeof(io_ranges) / sizeof(io_range_t)); i++) {
|
||||
for (j = io_ranges[i].start;
|
||||
j < io_ranges[i].start + io_ranges[i].size;
|
||||
j += PAGE_SIZE)
|
||||
map_domain_page(d, j, io_ranges[i].type);
|
||||
}
|
||||
|
||||
set_bit(ARCH_VMX_CONTIG_MEM, &v->arch.arch_vmx.flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vmx_setup_platform(struct vcpu *v, struct vcpu_guest_context *c)
|
||||
{
|
||||
struct domain *d = v->domain;
|
||||
shared_iopage_t *sp;
|
||||
|
||||
ASSERT(d != dom0); /* only for non-privileged vti domain */
|
||||
d->arch.vmx_platform.shared_page_va =
|
||||
__va(__gpa_to_mpa(d, IO_PAGE_START));
|
||||
sp = get_sp(d);
|
||||
//memset((char *)sp,0,PAGE_SIZE);
|
||||
//sp->sp_global.eport = 2;
|
||||
#ifdef V_IOSAPIC_READY
|
||||
sp->vcpu_number = 1;
|
||||
#endif
|
||||
/* TEMP */
|
||||
d->arch.vmx_platform.pib_base = 0xfee00000UL;
|
||||
|
||||
/* One more step to enable interrupt assist */
|
||||
set_bit(ARCH_VMX_INTR_ASSIST, &v->arch.arch_vmx.flags);
|
||||
/* Only open one port for I/O and interrupt emulation */
|
||||
if (v == d->vcpu[0]) {
|
||||
memset(&d->shared_info->evtchn_mask[0], 0xff,
|
||||
sizeof(d->shared_info->evtchn_mask));
|
||||
clear_bit(iopacket_port(d), &d->shared_info->evtchn_mask[0]);
|
||||
}
|
||||
|
||||
/* FIXME: only support PMT table continuously by far */
|
||||
// d->arch.pmt = __va(c->pt_base);
|
||||
|
||||
|
||||
vmx_final_setup_domain(d);
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,10 @@ vmx_ia64_handle_irq (ia64_vector vector, struct pt_regs *regs)
|
||||
|
||||
if (vector != IA64_TIMER_VECTOR) {
|
||||
/* FIXME: Leave IRQ re-route later */
|
||||
vmx_vcpu_pend_interrupt(dom0->vcpu[0],vector);
|
||||
if (!VMX_DOMAIN(dom0->vcpu[0]))
|
||||
vcpu_pend_interrupt(dom0->vcpu[0],vector);
|
||||
else
|
||||
vmx_vcpu_pend_interrupt(dom0->vcpu[0],vector);
|
||||
wake_dom0 = 1;
|
||||
}
|
||||
else { // FIXME: Handle Timer only now
|
||||
|
||||
@@ -156,13 +156,6 @@ physical_itlb_miss_domn(VCPU *vcpu, u64 vadr)
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
physical_itlb_miss(VCPU *vcpu, u64 vadr)
|
||||
{
|
||||
physical_itlb_miss_dom0(vcpu, vadr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
physical_itlb_miss_dom0(VCPU *vcpu, u64 vadr)
|
||||
{
|
||||
@@ -186,6 +179,13 @@ physical_itlb_miss_dom0(VCPU *vcpu, u64 vadr)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
physical_itlb_miss(VCPU *vcpu, u64 vadr)
|
||||
{
|
||||
physical_itlb_miss_dom0(vcpu, vadr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
physical_dtlb_miss(VCPU *vcpu, u64 vadr)
|
||||
{
|
||||
|
||||
@@ -56,6 +56,38 @@ extern struct ia64_sal_retval pal_emulator_static(UINT64);
|
||||
extern struct ia64_sal_retval sal_emulator(UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64,UINT64);
|
||||
extern void rnat_consumption (VCPU *vcpu);
|
||||
#define DOMN_PAL_REQUEST 0x110000
|
||||
|
||||
static UINT64 vec2off[68] = {0x0,0x400,0x800,0xc00,0x1000, 0x1400,0x1800,
|
||||
0x1c00,0x2000,0x2400,0x2800,0x2c00,0x3000,0x3400,0x3800,0x3c00,0x4000,
|
||||
0x4400,0x4800,0x4c00,0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x5600,
|
||||
0x5700,0x5800,0x5900,0x5a00,0x5b00,0x5c00,0x5d00,0x5e00,0x5f00,0x6000,
|
||||
0x6100,0x6200,0x6300,0x6400,0x6500,0x6600,0x6700,0x6800,0x6900,0x6a00,
|
||||
0x6b00,0x6c00,0x6d00,0x6e00,0x6f00,0x7000,0x7100,0x7200,0x7300,0x7400,
|
||||
0x7500,0x7600,0x7700,0x7800,0x7900,0x7a00,0x7b00,0x7c00,0x7d00,0x7e00,
|
||||
0x7f00,
|
||||
};
|
||||
|
||||
|
||||
|
||||
void vmx_reflect_interruption(UINT64 ifa,UINT64 isr,UINT64 iim,
|
||||
UINT64 vector,REGS *regs)
|
||||
{
|
||||
VCPU *vcpu = current;
|
||||
UINT64 viha,vpsr = vmx_vcpu_get_psr(vcpu);
|
||||
if(!(vpsr&IA64_PSR_IC)&&(vector!=5)){
|
||||
panic("Guest nested fault!");
|
||||
}
|
||||
VCPU(vcpu,isr)=isr;
|
||||
VCPU(vcpu,iipa) = regs->cr_iip;
|
||||
vector=vec2off[vector];
|
||||
if (vector == IA64_BREAK_VECTOR || vector == IA64_SPECULATION_VECTOR)
|
||||
VCPU(vcpu,iim) = iim;
|
||||
else {
|
||||
set_ifa_itir_iha(vcpu,ifa,1,1,1);
|
||||
}
|
||||
inject_guest_interruption(vcpu, vector);
|
||||
}
|
||||
|
||||
IA64FAULT
|
||||
vmx_ia64_handle_break (unsigned long ifa, struct pt_regs *regs, unsigned long isr, unsigned long iim)
|
||||
{
|
||||
@@ -157,37 +189,6 @@ vmx_ia64_handle_break (unsigned long ifa, struct pt_regs *regs, unsigned long is
|
||||
vmx_reflect_interruption(ifa,isr,iim,11,regs);
|
||||
}
|
||||
|
||||
static UINT64 vec2off[68] = {0x0,0x400,0x800,0xc00,0x1000, 0x1400,0x1800,
|
||||
0x1c00,0x2000,0x2400,0x2800,0x2c00,0x3000,0x3400,0x3800,0x3c00,0x4000,
|
||||
0x4400,0x4800,0x4c00,0x5000,0x5100,0x5200,0x5300,0x5400,0x5500,0x5600,
|
||||
0x5700,0x5800,0x5900,0x5a00,0x5b00,0x5c00,0x5d00,0x5e00,0x5f00,0x6000,
|
||||
0x6100,0x6200,0x6300,0x6400,0x6500,0x6600,0x6700,0x6800,0x6900,0x6a00,
|
||||
0x6b00,0x6c00,0x6d00,0x6e00,0x6f00,0x7000,0x7100,0x7200,0x7300,0x7400,
|
||||
0x7500,0x7600,0x7700,0x7800,0x7900,0x7a00,0x7b00,0x7c00,0x7d00,0x7e00,
|
||||
0x7f00,
|
||||
};
|
||||
|
||||
|
||||
|
||||
void vmx_reflect_interruption(UINT64 ifa,UINT64 isr,UINT64 iim,
|
||||
UINT64 vector,REGS *regs)
|
||||
{
|
||||
VCPU *vcpu = current;
|
||||
UINT64 viha,vpsr = vmx_vcpu_get_psr(vcpu);
|
||||
if(!(vpsr&IA64_PSR_IC)&&(vector!=5)){
|
||||
panic("Guest nested fault!");
|
||||
}
|
||||
VCPU(vcpu,isr)=isr;
|
||||
VCPU(vcpu,iipa) = regs->cr_iip;
|
||||
vector=vec2off[vector];
|
||||
if (vector == IA64_BREAK_VECTOR || vector == IA64_SPECULATION_VECTOR)
|
||||
VCPU(vcpu,iim) = iim;
|
||||
else {
|
||||
set_ifa_itir_iha(vcpu,ifa,1,1,1);
|
||||
}
|
||||
inject_guest_interruption(vcpu, vector);
|
||||
}
|
||||
|
||||
|
||||
void save_banked_regs_to_vpd(VCPU *v, REGS *regs)
|
||||
{
|
||||
@@ -271,10 +272,10 @@ void vmx_hpw_miss(u64 vadr , u64 vec, REGS* regs)
|
||||
{
|
||||
IA64_PSR vpsr;
|
||||
CACHE_LINE_TYPE type;
|
||||
u64 vhpt_adr;
|
||||
u64 vhpt_adr, gppa;
|
||||
ISR misr;
|
||||
ia64_rr vrr;
|
||||
REGS *regs;
|
||||
// REGS *regs;
|
||||
thash_cb_t *vtlb, *vhpt;
|
||||
thash_data_t *data, me;
|
||||
VCPU *v = current;
|
||||
@@ -314,9 +315,9 @@ void vmx_hpw_miss(u64 vadr , u64 vec, REGS* regs)
|
||||
// prepare_if_physical_mode(v);
|
||||
|
||||
if(data=vtlb_lookup_ex(vtlb, vrr.rid, vadr,type)){
|
||||
if(v->domain!=dom0&&type==DSIDE_TLB && __gpfn_is_io(v->domain,data->ppn>>(PAGE_SHIFT-12))){
|
||||
vadr=(vadr&((1UL<<data->ps)-1))+(data->ppn>>(data->ps-12)<<data->ps);
|
||||
emulate_io_inst(v, vadr, data->ma);
|
||||
gppa = (vadr&((1UL<<data->ps)-1))+(data->ppn>>(data->ps-12)<<data->ps);
|
||||
if(v->domain!=dom0&&type==DSIDE_TLB && __gpfn_is_io(v->domain,gppa>>PAGE_SHIFT)){
|
||||
emulate_io_inst(v, gppa, data->ma);
|
||||
return IA64_FAULT;
|
||||
}
|
||||
|
||||
|
||||
@@ -158,7 +158,7 @@ void vmx_intr_assist(struct vcpu *v)
|
||||
#ifdef V_IOSAPIC_READY
|
||||
vlapic_update_ext_irq(v);
|
||||
#else
|
||||
panic("IOSAPIC model is missed in qemu\n");
|
||||
//panic("IOSAPIC model is missed in qemu\n");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
@@ -387,6 +387,15 @@ void vtlb_insert(thash_cb_t *hcb, thash_data_t *entry, u64 va)
|
||||
thash_insert(hcb->ts->vhpt, entry, va);
|
||||
return;
|
||||
}
|
||||
|
||||
#if 1
|
||||
vrr=vmx_vcpu_rr(current, va);
|
||||
if (vrr.ps != entry->ps) {
|
||||
printk("not preferred ps with va: 0x%lx\n", va);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
flag = 1;
|
||||
gppn = (POFFSET(va,entry->ps)|PAGEALIGN((entry->ppn<<12),entry->ps))>>PAGE_SHIFT;
|
||||
ppns = PAGEALIGN((entry->ppn<<12),entry->ps);
|
||||
|
||||
@@ -121,6 +121,7 @@ acpi_get_sysname (void)
|
||||
#ifdef CONFIG_ACPI_BOOT
|
||||
|
||||
#define ACPI_MAX_PLATFORM_INTERRUPTS 256
|
||||
#define NR_IOSAPICS 4
|
||||
|
||||
#if 0
|
||||
/* Array to record platform interrupt vectors for generic interrupt routing. */
|
||||
@@ -162,7 +163,6 @@ static int available_cpus __initdata;
|
||||
struct acpi_table_madt * acpi_madt __initdata;
|
||||
static u8 has_8259;
|
||||
|
||||
#if 0
|
||||
static int __init
|
||||
acpi_parse_lapic_addr_ovr (
|
||||
acpi_table_entry_header *header, const unsigned long end)
|
||||
@@ -247,12 +247,13 @@ acpi_parse_iosapic (acpi_table_entry_header *header, const unsigned long end)
|
||||
|
||||
acpi_table_print_madt_entry(header);
|
||||
|
||||
#if 0
|
||||
iosapic_init(iosapic->address, iosapic->global_irq_base);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int __init
|
||||
acpi_parse_plat_int_src (
|
||||
acpi_table_entry_header *header, const unsigned long end)
|
||||
@@ -267,6 +268,7 @@ acpi_parse_plat_int_src (
|
||||
|
||||
acpi_table_print_madt_entry(header);
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Get vector assignment for this interrupt, set attributes,
|
||||
* and program the IOSAPIC routing table.
|
||||
@@ -280,6 +282,7 @@ acpi_parse_plat_int_src (
|
||||
(plintsrc->flags.trigger == 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
|
||||
|
||||
platform_intr_list[plintsrc->type] = vector;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -297,13 +300,14 @@ acpi_parse_int_src_ovr (
|
||||
|
||||
acpi_table_print_madt_entry(header);
|
||||
|
||||
#if 0
|
||||
iosapic_override_isa_irq(p->bus_irq, p->global_irq,
|
||||
(p->flags.polarity == 1) ? IOSAPIC_POL_HIGH : IOSAPIC_POL_LOW,
|
||||
(p->flags.trigger == 1) ? IOSAPIC_EDGE : IOSAPIC_LEVEL);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int __init
|
||||
acpi_parse_nmi_src (acpi_table_entry_header *header, const unsigned long end)
|
||||
{
|
||||
@@ -331,8 +335,10 @@ void __init acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
||||
*/
|
||||
sal_platform_features |= IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT;
|
||||
|
||||
#if 0
|
||||
/*Start cyclone clock*/
|
||||
cyclone_setup(0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -350,7 +356,9 @@ acpi_parse_madt (unsigned long phys_addr, unsigned long size)
|
||||
#else
|
||||
has_8259 = acpi_madt->flags.pcat_compat;
|
||||
#endif
|
||||
#if 0
|
||||
iosapic_system_init(has_8259);
|
||||
#endif
|
||||
|
||||
/* Get base address of IPI Message Block */
|
||||
|
||||
@@ -364,7 +372,6 @@ acpi_parse_madt (unsigned long phys_addr, unsigned long size)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ACPI_NUMA
|
||||
|
||||
@@ -529,6 +536,7 @@ acpi_register_gsi (u32 gsi, int polarity, int trigger)
|
||||
return acpi_register_irq(gsi, polarity, trigger);
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_register_gsi);
|
||||
#endif
|
||||
static int __init
|
||||
acpi_parse_fadt (unsigned long phys_addr, unsigned long size)
|
||||
{
|
||||
@@ -550,10 +558,11 @@ acpi_parse_fadt (unsigned long phys_addr, unsigned long size)
|
||||
if (fadt->iapc_boot_arch & BAF_LEGACY_DEVICES)
|
||||
acpi_legacy_devices = 1;
|
||||
|
||||
#if 0
|
||||
acpi_register_gsi(fadt->sci_int, ACPI_ACTIVE_LOW, ACPI_LEVEL_SENSITIVE);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned long __init
|
||||
acpi_find_rsdp (void)
|
||||
@@ -567,7 +576,6 @@ acpi_find_rsdp (void)
|
||||
return rsdp_phys;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int __init
|
||||
acpi_boot_init (void)
|
||||
{
|
||||
@@ -646,6 +654,7 @@ acpi_boot_init (void)
|
||||
printk(KERN_INFO "%d CPUs available, %d CPUs total\n", available_cpus, total_cpus);
|
||||
return 0;
|
||||
}
|
||||
#if 0
|
||||
int
|
||||
acpi_gsi_to_irq (u32 gsi, unsigned int *irq)
|
||||
{
|
||||
|
||||
@@ -177,13 +177,8 @@ long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op)
|
||||
|
||||
for ( i = start_page; i < (start_page + nr_pages); i++ )
|
||||
{
|
||||
page = map_new_domain_page(d, i << PAGE_SHIFT);
|
||||
if ( page == NULL )
|
||||
{
|
||||
ret = -ENOMEM;
|
||||
break;
|
||||
}
|
||||
pfn = page_to_pfn(page);
|
||||
pfn = __gpfn_to_mfn_foreign(d, i);
|
||||
|
||||
if ( put_user(pfn, buffer) )
|
||||
{
|
||||
ret = -EFAULT;
|
||||
|
||||
@@ -301,7 +301,7 @@ xen_pal_emulator(unsigned long index, unsigned long in1,
|
||||
// pal code must be mapped by a TR when pal is called, however
|
||||
// calls are rare enough that we will map it lazily rather than
|
||||
// at every context switch
|
||||
efi_map_pal_code();
|
||||
//efi_map_pal_code();
|
||||
switch (index) {
|
||||
case PAL_MEM_ATTRIB:
|
||||
status = ia64_pal_mem_attrib(&r9);
|
||||
|
||||
+52
-32
@@ -23,11 +23,13 @@
|
||||
#include <asm/io.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/desc.h>
|
||||
#include <asm/hw_irq.h>
|
||||
//#include <asm/mpspec.h>
|
||||
#include <xen/irq.h>
|
||||
#include <xen/event.h>
|
||||
//#include <xen/shadow.h>
|
||||
#include <xen/console.h>
|
||||
#include <xen/compile.h>
|
||||
|
||||
#include <xen/elf.h>
|
||||
//#include <asm/page.h>
|
||||
@@ -58,6 +60,7 @@ unsigned long *domU_staging_area;
|
||||
|
||||
// initialized by arch/ia64/setup.c:find_initrd()
|
||||
unsigned long initrd_start = 0, initrd_end = 0;
|
||||
extern unsigned long running_on_sim;
|
||||
|
||||
#define IS_XEN_ADDRESS(d,a) ((a >= d->xen_vastart) && (a <= d->xen_vaend))
|
||||
|
||||
@@ -75,35 +78,21 @@ void free_perdomain_pt(struct domain *d)
|
||||
//free_page((unsigned long)d->mm.perdomain_pt);
|
||||
}
|
||||
|
||||
int hlt_counter;
|
||||
|
||||
void disable_hlt(void)
|
||||
{
|
||||
hlt_counter++;
|
||||
}
|
||||
|
||||
void enable_hlt(void)
|
||||
{
|
||||
hlt_counter--;
|
||||
}
|
||||
|
||||
static void default_idle(void)
|
||||
{
|
||||
if ( hlt_counter == 0 )
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
local_irq_disable();
|
||||
if ( !softirq_pending(smp_processor_id()) )
|
||||
if ( !softirq_pending(cpu))
|
||||
safe_halt();
|
||||
//else
|
||||
local_irq_enable();
|
||||
}
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
void continue_cpu_idle_loop(void)
|
||||
static void continue_cpu_idle_loop(void)
|
||||
{
|
||||
int cpu = smp_processor_id();
|
||||
for ( ; ; )
|
||||
{
|
||||
printf ("idle%dD\n", cpu);
|
||||
#ifdef IA64
|
||||
// __IRQ_STAT(cpu, idle_timestamp) = jiffies
|
||||
#else
|
||||
@@ -111,23 +100,32 @@ void continue_cpu_idle_loop(void)
|
||||
#endif
|
||||
while ( !softirq_pending(cpu) )
|
||||
default_idle();
|
||||
add_preempt_count(SOFTIRQ_OFFSET);
|
||||
raise_softirq(SCHEDULE_SOFTIRQ);
|
||||
do_softirq();
|
||||
sub_preempt_count(SOFTIRQ_OFFSET);
|
||||
}
|
||||
}
|
||||
|
||||
void startup_cpu_idle_loop(void)
|
||||
{
|
||||
int cpu = smp_processor_id ();
|
||||
/* Just some sanity to ensure that the scheduler is set up okay. */
|
||||
ASSERT(current->domain == IDLE_DOMAIN_ID);
|
||||
printf ("idle%dA\n", cpu);
|
||||
raise_softirq(SCHEDULE_SOFTIRQ);
|
||||
#if 0 /* All this work is done within continue_cpu_idle_loop */
|
||||
printf ("idle%dB\n", cpu);
|
||||
asm volatile ("mov ar.k2=r0");
|
||||
do_softirq();
|
||||
printf ("idle%dC\n", cpu);
|
||||
|
||||
/*
|
||||
* Declares CPU setup done to the boot processor.
|
||||
* Therefore memory barrier to ensure state is visible.
|
||||
*/
|
||||
smp_mb();
|
||||
#endif
|
||||
#if 0
|
||||
//do we have to ensure the idle task has a shared page so that, for example,
|
||||
//region registers can be loaded from it. Apparently not...
|
||||
@@ -204,6 +202,15 @@ void arch_do_createdomain(struct vcpu *v)
|
||||
while (1);
|
||||
}
|
||||
memset(d->shared_info, 0, PAGE_SIZE);
|
||||
if (v == d->vcpu[0])
|
||||
memset(&d->shared_info->evtchn_mask[0], 0xff,
|
||||
sizeof(d->shared_info->evtchn_mask));
|
||||
#if 0
|
||||
d->vcpu[0].arch.privregs =
|
||||
alloc_xenheap_pages(get_order(sizeof(mapped_regs_t)));
|
||||
printf("arch_vcpu_info=%p\n", d->vcpu[0].arch.privregs);
|
||||
memset(d->vcpu.arch.privregs, 0, PAGE_SIZE);
|
||||
#endif
|
||||
v->vcpu_info = &(d->shared_info->vcpu_data[0]);
|
||||
|
||||
d->max_pages = (128UL*1024*1024)/PAGE_SIZE; // 128MB default // FIXME
|
||||
@@ -233,17 +240,21 @@ void arch_do_createdomain(struct vcpu *v)
|
||||
v->arch.breakimm = d->arch.breakimm;
|
||||
|
||||
d->arch.sys_pgnr = 0;
|
||||
d->arch.mm = xmalloc(struct mm_struct);
|
||||
if (unlikely(!d->arch.mm)) {
|
||||
printk("Can't allocate mm_struct for domain %d\n",d->domain_id);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(d->arch.mm, 0, sizeof(*d->arch.mm));
|
||||
d->arch.mm->pgd = pgd_alloc(d->arch.mm);
|
||||
if (unlikely(!d->arch.mm->pgd)) {
|
||||
printk("Can't allocate pgd for domain %d\n",d->domain_id);
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (d->domain_id != IDLE_DOMAIN_ID) {
|
||||
d->arch.mm = xmalloc(struct mm_struct);
|
||||
if (unlikely(!d->arch.mm)) {
|
||||
printk("Can't allocate mm_struct for domain %d\n",d->domain_id);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(d->arch.mm, 0, sizeof(*d->arch.mm));
|
||||
d->arch.mm->pgd = pgd_alloc(d->arch.mm);
|
||||
if (unlikely(!d->arch.mm->pgd)) {
|
||||
printk("Can't allocate pgd for domain %d\n",d->domain_id);
|
||||
return -ENOMEM;
|
||||
}
|
||||
} else
|
||||
d->arch.mm = NULL;
|
||||
printf ("arch_do_create_domain: domain=%p\n", d);
|
||||
}
|
||||
|
||||
void arch_getdomaininfo_ctxt(struct vcpu *v, struct vcpu_guest_context *c)
|
||||
@@ -268,6 +279,14 @@ int arch_set_info_guest(struct vcpu *v, struct vcpu_guest_context *c)
|
||||
if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) )
|
||||
return 0;
|
||||
|
||||
/* Sync d/i cache conservatively */
|
||||
if (!running_on_sim) {
|
||||
ret = ia64_pal_cache_flush(4, 0, &progress, NULL);
|
||||
if (ret != PAL_STATUS_SUCCESS)
|
||||
panic("PAL CACHE FLUSH failed for domain.\n");
|
||||
printk("Sync i/d cache for dom0 image SUCC\n");
|
||||
}
|
||||
|
||||
if (c->flags & VGCF_VMX_GUEST) {
|
||||
if (!vmx_enabled) {
|
||||
printk("No VMX hardware feature for vmx domain.\n");
|
||||
@@ -527,7 +546,8 @@ tryagain:
|
||||
if (pte_present(*pte)) {
|
||||
//printk("lookup_domain_page: found mapping for %lx, pte=%lx\n",mpaddr,pte_val(*pte));
|
||||
return *(unsigned long *)pte;
|
||||
}
|
||||
} else if (VMX_DOMAIN(d->vcpu[0]))
|
||||
return GPFN_INV_MASK;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -779,7 +799,6 @@ void physdev_init_dom0(struct domain *d)
|
||||
set_bit(_DOMF_physdev_access, &d->domain_flags);
|
||||
}
|
||||
|
||||
extern unsigned long running_on_sim;
|
||||
unsigned int vmx_dom0 = 0;
|
||||
int construct_dom0(struct domain *d,
|
||||
unsigned long image_start, unsigned long image_len,
|
||||
@@ -930,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;
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
#include <asm/system.h>
|
||||
#include <public/arch-ia64.h>
|
||||
|
||||
#define _PAGE_PPN_MASK 0x0003fffffffff000 //asm/pgtable.h doesn't do assembly
|
||||
#define PAGE_PHYS 0x0010000000000761 //__pgprot(__DIRTY_BITS|_PAGE_PL_2|_PAGE_AR_RWX)
|
||||
#define _PAGE_PL_2 (2<<7)
|
||||
|
||||
#if 1 // change to 0 to turn off all fast paths
|
||||
#define FAST_HYPERPRIVOPS
|
||||
#define FAST_HYPERPRIVOP_CNT
|
||||
@@ -24,6 +28,7 @@
|
||||
#define FAST_RFI
|
||||
#define FAST_SSM_I
|
||||
#define FAST_PTC_GA
|
||||
#undef FAST_ITC // working but default off for now
|
||||
#undef RFI_TO_INTERRUPT // not working yet
|
||||
#endif
|
||||
|
||||
@@ -802,8 +807,11 @@ just_do_rfi:
|
||||
// OK, now all set to go except for switch to virtual bank1
|
||||
mov r22=1;; st4 [r20]=r22;
|
||||
mov r30=r2; mov r29=r3;;
|
||||
adds r16=XSI_B1NATS_OFS-XSI_PSR_IC_OFS,r18
|
||||
adds r2=XSI_BANK1_OFS-XSI_PSR_IC_OFS,r18;
|
||||
adds r3=(XSI_BANK1_OFS+8)-XSI_PSR_IC_OFS,r18;;
|
||||
ld8 r16=[r16];;
|
||||
mov ar.unat=r16;;
|
||||
bsw.1;;
|
||||
// FIXME?: ar.unat is not really handled correctly,
|
||||
// but may not matter if the OS is NaT-clean
|
||||
@@ -1663,10 +1671,159 @@ ENTRY(hyper_ptc_ga)
|
||||
;;
|
||||
END(hyper_ptc_ga)
|
||||
|
||||
ENTRY(hyper_itc_d)
|
||||
br.spnt.many dispatch_break_fault ;;
|
||||
END(hyper_itc_d)
|
||||
|
||||
// Registers at entry
|
||||
// r17 = break immediate (XEN_HYPER_ITC_D or I)
|
||||
// r18 == XSI_PSR_IC_OFS
|
||||
// r31 == pr
|
||||
GLOBAL_ENTRY(hyper_itc)
|
||||
ENTRY(hyper_itc_i)
|
||||
// fall through, hyper_itc_d handles both i and d
|
||||
ENTRY(hyper_itc_d)
|
||||
#ifndef FAST_ITC
|
||||
br.spnt.many dispatch_break_fault ;;
|
||||
END(hyper_itc_i)
|
||||
#endif
|
||||
adds r23=XSI_ITIR_OFS-XSI_PSR_IC_OFS,r18 ;;
|
||||
ld8 r23=[r23];;
|
||||
extr.u r24=r23,2,6;; // r24==logps
|
||||
cmp.gt p7,p0=PAGE_SHIFT,r24
|
||||
(p7) br.spnt.many dispatch_break_fault ;;
|
||||
// translate_domain_pte(r8=pteval,PSCB(ifa)=address,r24=itir)
|
||||
mov r19=1;;
|
||||
shl r20=r19,r24;;
|
||||
adds r20=-1,r20;; // r20 == mask
|
||||
movl r19=_PAGE_PPN_MASK;;
|
||||
and r22=r8,r19;; // r22 == pteval & _PAGE_PPN_MASK
|
||||
andcm r19=r22,r20;;
|
||||
adds r21=XSI_IFA_OFS-XSI_PSR_IC_OFS,r18 ;;
|
||||
ld8 r21=[r21];;
|
||||
and r20=r21,r20;;
|
||||
or r19=r19,r20;; // r19 == mpaddr
|
||||
movl r27=THIS_CPU(cpu_kr)+IA64_KR_CURRENT_OFFSET;;
|
||||
ld8 r27=[r27];;
|
||||
adds r27=IA64_VCPU_DOMAIN_OFFSET,r27;;
|
||||
ld8 r27=[r27];;
|
||||
// FIXME: is the global var dom0 always pinned? assume so for now
|
||||
movl r28=dom0;;
|
||||
ld8 r28=[r28];;
|
||||
// FIXME: for now, only handle dom0 (see lookup_domain_mpa below)
|
||||
cmp.ne p7,p0=r27,r28
|
||||
(p7) br.spnt.many dispatch_break_fault ;;
|
||||
// if region 6, go slow way
|
||||
#ifdef FAST_HYPERPRIVOP_CNT
|
||||
cmp.eq p6,p7=XEN_HYPER_ITC_D,r17;;
|
||||
(p6) movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_ITC_D);;
|
||||
(p7) movl r20=fast_hyperpriv_cnt+(8*XEN_HYPER_ITC_I);;
|
||||
ld8 r21=[r20];;
|
||||
adds r21=1,r21;;
|
||||
st8 [r20]=r21;;
|
||||
#endif
|
||||
// FIXME: for now, just do domain0 and skip mpaddr range checks
|
||||
dep r20=r0,r19,0,PAGE_SHIFT
|
||||
movl r21=PAGE_PHYS ;;
|
||||
or r20=r20,r21 ;; // r20==return value from lookup_domain_mpa
|
||||
// r8=pteval,r20=pteval2
|
||||
movl r19=_PAGE_PPN_MASK
|
||||
movl r21=_PAGE_PL_2;;
|
||||
andcm r25=r8,r19;; // r25==pteval & ~_PAGE_PPN_MASK
|
||||
and r22=r20,r19;;
|
||||
or r22=r22,r21;;
|
||||
or r22=r22,r25;; // r22==return value from translate_domain_pte
|
||||
// done with translate_domain_pte
|
||||
// now do vcpu_itc_no_srlz(vcpu,IorD,ifa,r22=pte,r8=mppte,r24=logps)
|
||||
// FIXME: for now, just domain0 and skip range check
|
||||
// psr.ic already cleared
|
||||
// NOTE: r24 still contains ps (from above)
|
||||
shladd r24=r24,2,r0;;
|
||||
mov cr.itir=r24;;
|
||||
adds r23=XSI_IFA_OFS-XSI_PSR_IC_OFS,r18 ;;
|
||||
ld8 r23=[r23];;
|
||||
mov cr.ifa=r23;;
|
||||
cmp.eq p6,p7=XEN_HYPER_ITC_D,r17;;
|
||||
(p6) itc.d r22;;
|
||||
(p7) itc.i r22;;
|
||||
dv_serialize_data
|
||||
// FIXME: how do I make assembler warnings go away here?
|
||||
// vhpt_insert(r23=vaddr,r22=pte,r24=logps<<2)
|
||||
thash r28=r23
|
||||
or r26=1,r22;;
|
||||
ttag r21=r23
|
||||
adds r25=8,r28
|
||||
mov r19=r28;;
|
||||
st8 [r25]=r24
|
||||
adds r20=16,r28;;
|
||||
st8 [r19]=r26
|
||||
st8 [r20]=r21;;
|
||||
// vcpu_set_tr_entry(trp,r22=pte|1,r24=itir,r23=ifa)
|
||||
// TR_ENTRY = {page_flags,itir,addr,rid}
|
||||
cmp.eq p6,p7=XEN_HYPER_ITC_D,r17
|
||||
movl r27=THIS_CPU(cpu_kr)+IA64_KR_CURRENT_OFFSET;;
|
||||
ld8 r27=[r27];;
|
||||
adds r28=IA64_VCPU_STARTING_RID_OFFSET,r27
|
||||
(p6) adds r27=IA64_VCPU_DTLB_OFFSET,r27
|
||||
(p7) adds r27=IA64_VCPU_ITLB_OFFSET,r27;;
|
||||
st8 [r27]=r22,8;; // page_flags: already has pl >= 2 and p==1
|
||||
st8 [r27]=r24,8;; // itir
|
||||
mov r19=-4096;;
|
||||
and r23=r23,r19;;
|
||||
st8 [r27]=r23,8;; // ifa & ~0xfff
|
||||
// ?? is virtualize_rid(v,get_rr(ifa))==vcpu_get_rr(ifa)?? YES!!
|
||||
adds r29 = XSI_RR0_OFS-XSI_PSR_IC_OFS,r18
|
||||
extr.u r25=r23,61,3;;
|
||||
shladd r29=r25,3,r29;;
|
||||
ld8 r29=[r29];;
|
||||
movl r20=0xffffff00;;
|
||||
and r29=r29,r20;;
|
||||
st8 [r27]=r29,-8;; // rid
|
||||
//if ps > 12
|
||||
cmp.eq p7,p0=12<<2,r24
|
||||
(p7) br.cond.sptk.many 1f;;
|
||||
// if (ps > 12) {
|
||||
// trp->ppn &= ~((1UL<<(ps-12))-1); trp->vadr &= ~((1UL<<ps)-1); }
|
||||
extr.u r29=r24,2,6
|
||||
mov r28=1;;
|
||||
shl r26=r28,r29;;
|
||||
adds r29=-12,r29;;
|
||||
shl r25=r28,r29;;
|
||||
mov r29=-1
|
||||
adds r26=-1,r26
|
||||
adds r25=-1,r25;;
|
||||
andcm r26=r29,r26 // ~((1UL<<ps)-1)
|
||||
andcm r25=r29,r25;; // ~((1UL<<(ps-12))-1)
|
||||
ld8 r29=[r27];;
|
||||
and r29=r29,r26;;
|
||||
st8 [r27]=r29,-16;;
|
||||
ld8 r29=[r27];;
|
||||
extr.u r28=r29,12,38;;
|
||||
movl r26=0xfffc000000000fff;;
|
||||
and r29=r29,r26
|
||||
and r28=r28,r25;;
|
||||
shl r28=r28,12;;
|
||||
or r29=r29,r28;;
|
||||
st8 [r27]=r29;;
|
||||
1: // done with vcpu_set_tr_entry
|
||||
//PSCBX(vcpu,i/dtlb_pte) = mp_pte
|
||||
movl r27=THIS_CPU(cpu_kr)+IA64_KR_CURRENT_OFFSET;;
|
||||
ld8 r27=[r27];;
|
||||
cmp.eq p6,p7=XEN_HYPER_ITC_D,r17;;
|
||||
(p6) adds r27=IA64_VCPU_DTLB_PTE_OFFSET,r27
|
||||
(p7) adds r27=IA64_VCPU_ITLB_PTE_OFFSET,r27;;
|
||||
st8 [r27]=r8;;
|
||||
// done with vcpu_itc_no_srlz
|
||||
|
||||
// done, increment to point to next instruction
|
||||
mov r29=cr.ipsr
|
||||
mov r30=cr.iip;;
|
||||
extr.u r26=r29,41,2 ;;
|
||||
cmp.eq p6,p7=2,r26 ;;
|
||||
(p6) mov r26=0
|
||||
(p6) adds r30=16,r30
|
||||
(p7) adds r26=1,r26
|
||||
;;
|
||||
dep r29=r26,r29,41,2
|
||||
;;
|
||||
mov cr.ipsr=r29
|
||||
mov cr.iip=r30
|
||||
mov pr=r31,-1 ;;
|
||||
rfi
|
||||
;;
|
||||
END(hyper_itc_d)
|
||||
+49
-25
@@ -484,6 +484,7 @@ END(alt_dtlb_miss)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 0x1400 Entry 5 (size 64 bundles) Data nested TLB (6,45)
|
||||
ENTRY(nested_dtlb_miss)
|
||||
DBG_FAULT(5)
|
||||
/*
|
||||
* In the absence of kernel bugs, we get here when the virtually mapped linear
|
||||
* page table is accessed non-speculatively (e.g., in the Dirty-bit, Instruction
|
||||
@@ -552,10 +553,10 @@ END(nested_dtlb_miss)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 0x1800 Entry 6 (size 64 bundles) Instruction Key Miss (24)
|
||||
ENTRY(ikey_miss)
|
||||
DBG_FAULT(6)
|
||||
#ifdef XEN
|
||||
REFLECT(6)
|
||||
#endif
|
||||
DBG_FAULT(6)
|
||||
FAULT(6)
|
||||
END(ikey_miss)
|
||||
|
||||
@@ -597,10 +598,10 @@ END(page_fault)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51)
|
||||
ENTRY(dkey_miss)
|
||||
DBG_FAULT(7)
|
||||
#ifdef XEN
|
||||
REFLECT(7)
|
||||
#endif
|
||||
DBG_FAULT(7)
|
||||
FAULT(7)
|
||||
END(dkey_miss)
|
||||
|
||||
@@ -608,10 +609,10 @@ END(dkey_miss)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 0x2000 Entry 8 (size 64 bundles) Dirty-bit (54)
|
||||
ENTRY(dirty_bit)
|
||||
DBG_FAULT(8)
|
||||
#ifdef XEN
|
||||
REFLECT(8)
|
||||
#endif
|
||||
DBG_FAULT(8)
|
||||
/*
|
||||
* What we do here is to simply turn on the dirty bit in the PTE. We need to
|
||||
* update both the page-table and the TLB entry. To efficiently access the PTE,
|
||||
@@ -673,6 +674,7 @@ END(dirty_bit)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 0x2400 Entry 9 (size 64 bundles) Instruction Access-bit (27)
|
||||
ENTRY(iaccess_bit)
|
||||
DBG_FAULT(9)
|
||||
#ifdef XEN
|
||||
mov r31=pr;
|
||||
mov r16=cr.isr
|
||||
@@ -681,7 +683,6 @@ ENTRY(iaccess_bit)
|
||||
movl r20=0x2400
|
||||
br.sptk.many fast_access_reflect;;
|
||||
#endif
|
||||
DBG_FAULT(9)
|
||||
// Like Entry 8, except for instruction access
|
||||
mov r16=cr.ifa // get the address that caused the fault
|
||||
movl r30=1f // load continuation point in case of nested fault
|
||||
@@ -746,6 +747,7 @@ END(iaccess_bit)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 0x2800 Entry 10 (size 64 bundles) Data Access-bit (15,55)
|
||||
ENTRY(daccess_bit)
|
||||
DBG_FAULT(10)
|
||||
#ifdef XEN
|
||||
mov r31=pr;
|
||||
mov r16=cr.isr
|
||||
@@ -754,7 +756,6 @@ ENTRY(daccess_bit)
|
||||
movl r20=0x2800
|
||||
br.sptk.many fast_access_reflect;;
|
||||
#endif
|
||||
DBG_FAULT(10)
|
||||
// Like Entry 8, except for data access
|
||||
mov r16=cr.ifa // get the address that caused the fault
|
||||
movl r30=1f // load continuation point in case of nested fault
|
||||
@@ -971,8 +972,10 @@ slow_interrupt:
|
||||
mov out0=cr.ivr // pass cr.ivr as first arg
|
||||
#endif
|
||||
add out1=16,sp // pass pointer to pt_regs as second arg
|
||||
#ifndef XEN
|
||||
;;
|
||||
srlz.d // make sure we see the effect of cr.ivr
|
||||
#endif
|
||||
movl r14=ia64_leave_kernel
|
||||
;;
|
||||
mov rp=r14
|
||||
@@ -1363,10 +1366,10 @@ END(dispatch_to_fault_handler)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 0x5000 Entry 20 (size 16 bundles) Page Not Present (10,22,49)
|
||||
ENTRY(page_not_present)
|
||||
DBG_FAULT(20)
|
||||
#ifdef XEN
|
||||
REFLECT(20)
|
||||
#endif
|
||||
DBG_FAULT(20)
|
||||
mov r16=cr.ifa
|
||||
rsm psr.dt
|
||||
/*
|
||||
@@ -1386,10 +1389,10 @@ END(page_not_present)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 0x5100 Entry 21 (size 16 bundles) Key Permission (13,25,52)
|
||||
ENTRY(key_permission)
|
||||
DBG_FAULT(21)
|
||||
#ifdef XEN
|
||||
REFLECT(21)
|
||||
#endif
|
||||
DBG_FAULT(21)
|
||||
mov r16=cr.ifa
|
||||
rsm psr.dt
|
||||
mov r31=pr
|
||||
@@ -1402,10 +1405,10 @@ END(key_permission)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 0x5200 Entry 22 (size 16 bundles) Instruction Access Rights (26)
|
||||
ENTRY(iaccess_rights)
|
||||
DBG_FAULT(22)
|
||||
#ifdef XEN
|
||||
REFLECT(22)
|
||||
#endif
|
||||
DBG_FAULT(22)
|
||||
mov r16=cr.ifa
|
||||
rsm psr.dt
|
||||
mov r31=pr
|
||||
@@ -1418,6 +1421,7 @@ END(iaccess_rights)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 0x5300 Entry 23 (size 16 bundles) Data Access Rights (14,53)
|
||||
ENTRY(daccess_rights)
|
||||
DBG_FAULT(23)
|
||||
#ifdef XEN
|
||||
mov r31=pr;
|
||||
mov r16=cr.isr
|
||||
@@ -1426,7 +1430,6 @@ ENTRY(daccess_rights)
|
||||
movl r20=0x5300
|
||||
br.sptk.many fast_access_reflect;;
|
||||
#endif
|
||||
DBG_FAULT(23)
|
||||
mov r16=cr.ifa
|
||||
rsm psr.dt
|
||||
mov r31=pr
|
||||
@@ -1459,10 +1462,31 @@ END(general_exception)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 0x5500 Entry 25 (size 16 bundles) Disabled FP-Register (35)
|
||||
ENTRY(disabled_fp_reg)
|
||||
#ifdef XEN
|
||||
REFLECT(25)
|
||||
#endif
|
||||
DBG_FAULT(25)
|
||||
#ifdef XEN
|
||||
#if 0
|
||||
mov r20=pr
|
||||
movl r16=0x2000000000000000
|
||||
movl r17=0x2000000000176b60
|
||||
mov r18=cr.iip
|
||||
mov r19=rr[r16]
|
||||
movl r22=0xe95d0439
|
||||
;;
|
||||
mov pr=r0,-1
|
||||
;;
|
||||
cmp.eq p6,p7=r22,r19
|
||||
;;
|
||||
(p6) cmp.eq p8,p9=r17,r18
|
||||
(p8) br.sptk.few floating_panic
|
||||
;;
|
||||
mov pr=r20,-1
|
||||
;;
|
||||
#endif
|
||||
REFLECT(25)
|
||||
//floating_panic:
|
||||
// br.sptk.many floating_panic
|
||||
;;
|
||||
#endif
|
||||
rsm psr.dfh // ensure we can access fph
|
||||
;;
|
||||
srlz.d
|
||||
@@ -1475,10 +1499,10 @@ END(disabled_fp_reg)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 0x5600 Entry 26 (size 16 bundles) Nat Consumption (11,23,37,50)
|
||||
ENTRY(nat_consumption)
|
||||
DBG_FAULT(26)
|
||||
#ifdef XEN
|
||||
REFLECT(26)
|
||||
#endif
|
||||
DBG_FAULT(26)
|
||||
FAULT(26)
|
||||
END(nat_consumption)
|
||||
|
||||
@@ -1486,11 +1510,11 @@ END(nat_consumption)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 0x5700 Entry 27 (size 16 bundles) Speculation (40)
|
||||
ENTRY(speculation_vector)
|
||||
DBG_FAULT(27)
|
||||
#ifdef XEN
|
||||
// this probably need not reflect...
|
||||
REFLECT(27)
|
||||
#endif
|
||||
DBG_FAULT(27)
|
||||
/*
|
||||
* A [f]chk.[as] instruction needs to take the branch to the recovery code but
|
||||
* this part of the architecture is not implemented in hardware on some CPUs, such
|
||||
@@ -1533,10 +1557,10 @@ END(speculation_vector)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 0x5900 Entry 29 (size 16 bundles) Debug (16,28,56)
|
||||
ENTRY(debug_vector)
|
||||
DBG_FAULT(29)
|
||||
#ifdef XEN
|
||||
REFLECT(29)
|
||||
#endif
|
||||
DBG_FAULT(29)
|
||||
FAULT(29)
|
||||
END(debug_vector)
|
||||
|
||||
@@ -1544,10 +1568,10 @@ END(debug_vector)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 0x5a00 Entry 30 (size 16 bundles) Unaligned Reference (57)
|
||||
ENTRY(unaligned_access)
|
||||
DBG_FAULT(30)
|
||||
#ifdef XEN
|
||||
REFLECT(30)
|
||||
#endif
|
||||
DBG_FAULT(30)
|
||||
mov r16=cr.ipsr
|
||||
mov r31=pr // prepare to save predicates
|
||||
;;
|
||||
@@ -1558,10 +1582,10 @@ END(unaligned_access)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 0x5b00 Entry 31 (size 16 bundles) Unsupported Data Reference (57)
|
||||
ENTRY(unsupported_data_reference)
|
||||
DBG_FAULT(31)
|
||||
#ifdef XEN
|
||||
REFLECT(31)
|
||||
#endif
|
||||
DBG_FAULT(31)
|
||||
FAULT(31)
|
||||
END(unsupported_data_reference)
|
||||
|
||||
@@ -1569,10 +1593,10 @@ END(unsupported_data_reference)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 0x5c00 Entry 32 (size 16 bundles) Floating-Point Fault (64)
|
||||
ENTRY(floating_point_fault)
|
||||
DBG_FAULT(32)
|
||||
#ifdef XEN
|
||||
REFLECT(32)
|
||||
#endif
|
||||
DBG_FAULT(32)
|
||||
FAULT(32)
|
||||
END(floating_point_fault)
|
||||
|
||||
@@ -1580,10 +1604,10 @@ END(floating_point_fault)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 0x5d00 Entry 33 (size 16 bundles) Floating Point Trap (66)
|
||||
ENTRY(floating_point_trap)
|
||||
DBG_FAULT(33)
|
||||
#ifdef XEN
|
||||
REFLECT(33)
|
||||
#endif
|
||||
DBG_FAULT(33)
|
||||
FAULT(33)
|
||||
END(floating_point_trap)
|
||||
|
||||
@@ -1591,10 +1615,10 @@ END(floating_point_trap)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 0x5e00 Entry 34 (size 16 bundles) Lower Privilege Transfer Trap (66)
|
||||
ENTRY(lower_privilege_trap)
|
||||
DBG_FAULT(34)
|
||||
#ifdef XEN
|
||||
REFLECT(34)
|
||||
#endif
|
||||
DBG_FAULT(34)
|
||||
FAULT(34)
|
||||
END(lower_privilege_trap)
|
||||
|
||||
@@ -1602,10 +1626,10 @@ END(lower_privilege_trap)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 0x5f00 Entry 35 (size 16 bundles) Taken Branch Trap (68)
|
||||
ENTRY(taken_branch_trap)
|
||||
DBG_FAULT(35)
|
||||
#ifdef XEN
|
||||
REFLECT(35)
|
||||
#endif
|
||||
DBG_FAULT(35)
|
||||
FAULT(35)
|
||||
END(taken_branch_trap)
|
||||
|
||||
@@ -1613,10 +1637,10 @@ END(taken_branch_trap)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 0x6000 Entry 36 (size 16 bundles) Single Step Trap (69)
|
||||
ENTRY(single_step_trap)
|
||||
DBG_FAULT(36)
|
||||
#ifdef XEN
|
||||
REFLECT(36)
|
||||
#endif
|
||||
DBG_FAULT(36)
|
||||
FAULT(36)
|
||||
END(single_step_trap)
|
||||
|
||||
@@ -1672,10 +1696,10 @@ END(single_step_trap)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 0x6900 Entry 45 (size 16 bundles) IA-32 Exeception (17,18,29,41,42,43,44,58,60,61,62,72,73,75,76,77)
|
||||
ENTRY(ia32_exception)
|
||||
DBG_FAULT(45)
|
||||
#ifdef XEN
|
||||
REFLECT(45)
|
||||
#endif
|
||||
DBG_FAULT(45)
|
||||
FAULT(45)
|
||||
END(ia32_exception)
|
||||
|
||||
@@ -1683,10 +1707,10 @@ END(ia32_exception)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 0x6a00 Entry 46 (size 16 bundles) IA-32 Intercept (30,31,59,70,71)
|
||||
ENTRY(ia32_intercept)
|
||||
DBG_FAULT(46)
|
||||
#ifdef XEN
|
||||
REFLECT(46)
|
||||
#endif
|
||||
DBG_FAULT(46)
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
mov r31=pr
|
||||
mov r16=cr.isr
|
||||
@@ -1716,10 +1740,10 @@ END(ia32_intercept)
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// 0x6b00 Entry 47 (size 16 bundles) IA-32 Interrupt (74)
|
||||
ENTRY(ia32_interrupt)
|
||||
DBG_FAULT(47)
|
||||
#ifdef XEN
|
||||
REFLECT(47)
|
||||
#endif
|
||||
DBG_FAULT(47)
|
||||
#ifdef CONFIG_IA32_SUPPORT
|
||||
mov r31=pr
|
||||
br.sptk.many dispatch_to_ia32_handler
|
||||
|
||||
@@ -62,11 +62,23 @@ long do_iopl(domid_t domain, unsigned int new_io_pl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <xen/sched-if.h>
|
||||
|
||||
extern struct schedule_data schedule_data[NR_CPUS];
|
||||
|
||||
void schedule_tail(struct vcpu *next)
|
||||
{
|
||||
unsigned long rr7;
|
||||
//printk("current=%lx,shared_info=%lx\n",current,current->vcpu_info);
|
||||
//printk("next=%lx,shared_info=%lx\n",next,next->vcpu_info);
|
||||
|
||||
// TG: Real HACK FIXME.
|
||||
// This is currently necessary because when a new domain is started,
|
||||
// the context_switch function of xen/common/schedule.c(__enter_scheduler)
|
||||
// never returns. Therefore, the lock must be released.
|
||||
// schedule_tail is only called when a domain is started.
|
||||
spin_unlock_irq(&schedule_data[current->processor].schedule_lock);
|
||||
|
||||
/* rr7 will be postponed to last point when resuming back to guest */
|
||||
if(VMX_DOMAIN(current)){
|
||||
vmx_load_all_rr(current);
|
||||
@@ -733,6 +745,8 @@ ia64_handle_reflection (unsigned long ifa, struct pt_regs *regs, unsigned long i
|
||||
case 26:
|
||||
printf("*** NaT fault... attempting to handle as privop\n");
|
||||
printf("isr=%p, ifa=%p,iip=%p,ipsr=%p\n",isr,ifa,regs->cr_iip,psr);
|
||||
regs->eml_unat = 0;
|
||||
return;
|
||||
vector = priv_emulate(v,regs,isr);
|
||||
if (vector == IA64_NO_FAULT) {
|
||||
printf("*** Handled privop masquerading as NaT fault\n");
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
#include <asm/regionreg.h>
|
||||
#include <asm/vhpt.h>
|
||||
#include <asm/vcpu.h>
|
||||
extern void ia64_new_rr7(unsigned long rid,void *shared_info, void *shared_arch_info);
|
||||
extern void ia64_new_rr7(unsigned long rid,void *shared_info, void *shared_arch_info, unsigned long p_vhpt, unsigned long v_pal);
|
||||
extern void *pal_vaddr;
|
||||
|
||||
|
||||
#define IA64_MIN_IMPL_RID_BITS (IA64_MIN_IMPL_RID_MSB+1)
|
||||
@@ -66,9 +67,12 @@ unsigned long allocate_metaphysical_rr(void)
|
||||
{
|
||||
ia64_rr rrv;
|
||||
|
||||
rrv.rrval = 0; // Or else may see reserved bit fault
|
||||
rrv.rid = allocate_reserved_rid();
|
||||
rrv.ps = PAGE_SHIFT;
|
||||
rrv.ve = 0;
|
||||
/* Mangle metaphysical rid */
|
||||
rrv.rrval = vmMangleRID(rrv.rrval);
|
||||
return rrv.rrval;
|
||||
}
|
||||
|
||||
@@ -213,6 +217,7 @@ int set_one_rr(unsigned long rr, unsigned long val)
|
||||
unsigned long rreg = REGION_NUMBER(rr);
|
||||
ia64_rr rrv, newrrv, memrrv;
|
||||
unsigned long newrid;
|
||||
extern unsigned long vhpt_paddr;
|
||||
|
||||
if (val == -1) return 1;
|
||||
|
||||
@@ -250,9 +255,10 @@ int set_one_rr(unsigned long rr, unsigned long val)
|
||||
newrrv.rid = newrid;
|
||||
newrrv.ve = 1; // VHPT now enabled for region 7!!
|
||||
newrrv.ps = PAGE_SHIFT;
|
||||
if (rreg == 0) v->arch.metaphysical_saved_rr0 = newrrv.rrval;
|
||||
if (rreg == 0) v->arch.metaphysical_saved_rr0 =
|
||||
vmMangleRID(newrrv.rrval);
|
||||
if (rreg == 7) ia64_new_rr7(vmMangleRID(newrrv.rrval),v->vcpu_info,
|
||||
v->arch.privregs);
|
||||
v->arch.privregs, vhpt_paddr, pal_vaddr);
|
||||
else set_rr(rr,newrrv.rrval);
|
||||
#endif
|
||||
return 1;
|
||||
@@ -265,7 +271,8 @@ int set_metaphysical_rr0(void)
|
||||
ia64_rr rrv;
|
||||
|
||||
// rrv.ve = 1; FIXME: TURN ME BACK ON WHEN VHPT IS WORKING
|
||||
set_rr(0,v->arch.metaphysical_rr0);
|
||||
ia64_set_rr(0,v->arch.metaphysical_rr0);
|
||||
ia64_srlz_d();
|
||||
}
|
||||
|
||||
// validates/changes region registers 0-6 in the currently executing domain
|
||||
@@ -290,7 +297,7 @@ void init_all_rr(struct vcpu *v)
|
||||
ia64_rr rrv;
|
||||
|
||||
rrv.rrval = 0;
|
||||
rrv.rrval = v->domain->arch.metaphysical_rr0;
|
||||
//rrv.rrval = v->domain->arch.metaphysical_rr0;
|
||||
rrv.ps = PAGE_SHIFT;
|
||||
rrv.ve = 1;
|
||||
if (!v->vcpu_info) { printf("Stopping in init_all_rr\n"); dummy(); }
|
||||
@@ -343,12 +350,16 @@ unsigned long load_region_regs(struct vcpu *v)
|
||||
if (VCPU(v,metaphysical_mode)) {
|
||||
ia64_rr rrv;
|
||||
|
||||
#if 0
|
||||
rrv.rrval = 0;
|
||||
rrv.rid = v->domain->arch.metaphysical_rr0;
|
||||
rrv.ps = PAGE_SHIFT;
|
||||
rrv.ve = 1;
|
||||
rr0 = rrv.rrval;
|
||||
set_rr_no_srlz(0x0000000000000000L, rr0);
|
||||
#endif
|
||||
rr0 = v->domain->arch.metaphysical_rr0;
|
||||
ia64_set_rr(0x0000000000000000L, rr0);
|
||||
ia64_srlz_d();
|
||||
}
|
||||
else {
|
||||
|
||||
+71
-159
@@ -66,8 +66,16 @@ unsigned long phys_translate_count = 0;
|
||||
unsigned long vcpu_verbose = 0;
|
||||
#define verbose(a...) do {if (vcpu_verbose) printf(a);} while(0)
|
||||
|
||||
extern TR_ENTRY *match_tr(VCPU *vcpu, unsigned long ifa);
|
||||
extern TR_ENTRY *match_dtlb(VCPU *vcpu, unsigned long ifa);
|
||||
//#define vcpu_quick_region_check(_tr_regions,_ifa) 1
|
||||
#define vcpu_quick_region_check(_tr_regions,_ifa) \
|
||||
(_tr_regions & (1 << ((unsigned long)_ifa >> 61)))
|
||||
#define vcpu_quick_region_set(_tr_regions,_ifa) \
|
||||
do {_tr_regions |= (1 << ((unsigned long)_ifa >> 61)); } while (0)
|
||||
|
||||
// FIXME: also need to check && (!trp->key || vcpu_pkr_match(trp->key))
|
||||
#define vcpu_match_tr_entry(_trp,_ifa,_rid) \
|
||||
((_trp->p && (_trp->rid==_rid) && (_ifa >= _trp->vadr) && \
|
||||
(_ifa < (_trp->vadr + (1L<< _trp->ps)) - 1)))
|
||||
|
||||
/**************************************************************************
|
||||
VCPU general register access routines
|
||||
@@ -620,7 +628,7 @@ void vcpu_pend_interrupt(VCPU *vcpu, UINT64 vector)
|
||||
return;
|
||||
}
|
||||
if ( VMX_DOMAIN(vcpu) ) {
|
||||
set_bit(vector,VCPU(vcpu,irr));
|
||||
set_bit(vector,VCPU(vcpu,irr));
|
||||
} else
|
||||
{
|
||||
/* if (!test_bit(vector,PSCB(vcpu,delivery_mask))) return; */
|
||||
@@ -630,16 +638,6 @@ void vcpu_pend_interrupt(VCPU *vcpu, UINT64 vector)
|
||||
set_bit(vector,PSCBX(vcpu,irr));
|
||||
PSCB(vcpu,pending_interruption) = 1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Keir: I think you should unblock when an interrupt is pending. */
|
||||
{
|
||||
int running = test_bit(_VCPUF_running, &vcpu->vcpu_flags);
|
||||
vcpu_unblock(vcpu);
|
||||
if ( running )
|
||||
smp_send_event_check_cpu(vcpu->processor);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void early_tick(VCPU *vcpu)
|
||||
@@ -710,14 +708,6 @@ UINT64 vcpu_check_pending_interrupts(VCPU *vcpu)
|
||||
}
|
||||
|
||||
//printf("returned to caller\n");
|
||||
#if 0
|
||||
if (vector == (PSCB(vcpu,itv) & 0xff)) {
|
||||
UINT64 now = ia64_get_itc();
|
||||
UINT64 itm = PSCBX(vcpu,domain_itm);
|
||||
if (now < itm) early_tick(vcpu);
|
||||
|
||||
}
|
||||
#endif
|
||||
return vector;
|
||||
}
|
||||
|
||||
@@ -775,6 +765,7 @@ IA64FAULT vcpu_get_ivr(VCPU *vcpu, UINT64 *pval)
|
||||
}
|
||||
#ifdef HEARTBEAT_FREQ
|
||||
if (domid >= N_DOMS) domid = N_DOMS-1;
|
||||
#if 0
|
||||
if (vector == (PSCB(vcpu,itv) & 0xff)) {
|
||||
if (!(++count[domid] & ((HEARTBEAT_FREQ*1024)-1))) {
|
||||
printf("Dom%d heartbeat... ticks=%lx,nonticks=%lx\n",
|
||||
@@ -783,6 +774,7 @@ IA64FAULT vcpu_get_ivr(VCPU *vcpu, UINT64 *pval)
|
||||
//dump_runq();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else nonclockcount[domid]++;
|
||||
#endif
|
||||
// now have an unmasked, pending, deliverable vector!
|
||||
@@ -1068,23 +1060,6 @@ void vcpu_set_next_timer(VCPU *vcpu)
|
||||
/* gloss over the wraparound problem for now... we know it exists
|
||||
* but it doesn't matter right now */
|
||||
|
||||
#if 0
|
||||
/* ensure at least next SP tick is in the future */
|
||||
if (!interval) PSCBX(vcpu,xen_itm) = now +
|
||||
#if 0
|
||||
(running_on_sim() ? SIM_DEFAULT_CLOCK_RATE :
|
||||
DEFAULT_CLOCK_RATE);
|
||||
#else
|
||||
3000000;
|
||||
//printf("vcpu_set_next_timer: HACK!\n");
|
||||
#endif
|
||||
#if 0
|
||||
if (PSCBX(vcpu,xen_itm) < now)
|
||||
while (PSCBX(vcpu,xen_itm) < now + (interval>>1))
|
||||
PSCBX(vcpu,xen_itm) += interval;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (is_idle_task(vcpu->domain)) {
|
||||
// printf("****** vcpu_set_next_timer called during idle!!\n");
|
||||
vcpu_safe_set_itm(s);
|
||||
@@ -1175,14 +1150,6 @@ void vcpu_pend_timer(VCPU *vcpu)
|
||||
// don't deliver another
|
||||
return;
|
||||
}
|
||||
#if 0
|
||||
// attempt to flag "timer tick before its due" source
|
||||
{
|
||||
UINT64 itm = PSCBX(vcpu,domain_itm);
|
||||
UINT64 now = ia64_get_itc();
|
||||
if (now < itm) printf("******* vcpu_pend_timer: pending before due!\n");
|
||||
}
|
||||
#endif
|
||||
vcpu_pend_interrupt(vcpu, itv);
|
||||
}
|
||||
|
||||
@@ -1197,33 +1164,6 @@ UINT64 vcpu_timer_pending_early(VCPU *vcpu)
|
||||
return (vcpu_deliverable_timer(vcpu) && (now < itm));
|
||||
}
|
||||
|
||||
//FIXME: This is a hack because everything dies if a timer tick is lost
|
||||
void vcpu_poke_timer(VCPU *vcpu)
|
||||
{
|
||||
UINT64 itv = PSCB(vcpu,itv) & 0xff;
|
||||
UINT64 now = ia64_get_itc();
|
||||
UINT64 itm = PSCBX(vcpu,domain_itm);
|
||||
UINT64 irr;
|
||||
|
||||
if (vcpu_timer_disabled(vcpu)) return;
|
||||
if (!itm) return;
|
||||
if (itv != 0xefL) {
|
||||
printf("vcpu_poke_timer: unimplemented itv=%lx!\n",itv);
|
||||
while(1);
|
||||
}
|
||||
// using 0xef instead of itv so can get real irr
|
||||
if (now > itm && !test_bit(0xefL, PSCBX(vcpu,insvc))) {
|
||||
if (!test_bit(0xefL,PSCBX(vcpu,irr))) {
|
||||
irr = ia64_getreg(_IA64_REG_CR_IRR3);
|
||||
if (irr & (1L<<(0xef-0xc0))) return;
|
||||
if (now-itm>0x800000)
|
||||
printf("*** poking timer: now=%lx,vitm=%lx,xitm=%lx,itm=%lx\n",now,itm,local_cpu_data->itm_next,ia64_get_itm());
|
||||
vcpu_pend_timer(vcpu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
Privileged operation emulation routines
|
||||
**************************************************************************/
|
||||
@@ -1316,13 +1256,6 @@ IA64FAULT vcpu_thash(VCPU *vcpu, UINT64 vadr, UINT64 *pval)
|
||||
UINT64 VHPT_addr = VHPT_addr1 | ((VHPT_addr2a | VHPT_addr2b) << 15) |
|
||||
VHPT_addr3;
|
||||
|
||||
#if 0
|
||||
if (VHPT_addr1 == 0xe000000000000000L) {
|
||||
printf("vcpu_thash: thash unsupported with rr7 @%lx\n",
|
||||
PSCB(vcpu,iip));
|
||||
return (IA64_ILLOP_FAULT);
|
||||
}
|
||||
#endif
|
||||
//verbose("vcpu_thash: vadr=%p, VHPT_addr=%p\n",vadr,VHPT_addr);
|
||||
*pval = VHPT_addr;
|
||||
return (IA64_NO_FAULT);
|
||||
@@ -1341,9 +1274,9 @@ unsigned long vhpt_translate_count = 0;
|
||||
|
||||
IA64FAULT vcpu_translate(VCPU *vcpu, UINT64 address, BOOLEAN is_data, UINT64 *pteval, UINT64 *itir, UINT64 *iha)
|
||||
{
|
||||
unsigned long pta, pta_mask, pte, ps;
|
||||
unsigned long pta, pte, rid, rr;
|
||||
int i;
|
||||
TR_ENTRY *trp;
|
||||
ia64_rr rr;
|
||||
|
||||
if (!(address >> 61)) {
|
||||
if (!PSCB(vcpu,metaphysical_mode)) {
|
||||
@@ -1361,67 +1294,80 @@ IA64FAULT vcpu_translate(VCPU *vcpu, UINT64 address, BOOLEAN is_data, UINT64 *pt
|
||||
return IA64_NO_FAULT;
|
||||
}
|
||||
|
||||
/* check translation registers */
|
||||
if ((trp = match_tr(vcpu,address))) {
|
||||
tr_translate_count++;
|
||||
*pteval = trp->page_flags;
|
||||
*itir = trp->itir;
|
||||
return IA64_NO_FAULT;
|
||||
rr = PSCB(vcpu,rrs)[address>>61];
|
||||
rid = rr & RR_RID_MASK;
|
||||
if (is_data) {
|
||||
if (vcpu_quick_region_check(vcpu->arch.dtr_regions,address)) {
|
||||
for (trp = vcpu->arch.dtrs, i = NDTRS; i; i--, trp++) {
|
||||
if (vcpu_match_tr_entry(trp,address,rid)) {
|
||||
*pteval = trp->page_flags;
|
||||
*itir = trp->itir;
|
||||
tr_translate_count++;
|
||||
return IA64_NO_FAULT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// FIXME?: check itr's for data accesses too, else bad things happen?
|
||||
/* else */ {
|
||||
if (vcpu_quick_region_check(vcpu->arch.itr_regions,address)) {
|
||||
for (trp = vcpu->arch.itrs, i = NITRS; i; i--, trp++) {
|
||||
if (vcpu_match_tr_entry(trp,address,rid)) {
|
||||
*pteval = trp->page_flags;
|
||||
*itir = trp->itir;
|
||||
tr_translate_count++;
|
||||
return IA64_NO_FAULT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check 1-entry TLB */
|
||||
if ((trp = match_dtlb(vcpu,address))) {
|
||||
dtlb_translate_count++;
|
||||
// FIXME?: check dtlb for inst accesses too, else bad things happen?
|
||||
trp = &vcpu->arch.dtlb;
|
||||
if (/* is_data && */ vcpu_match_tr_entry(trp,address,rid)) {
|
||||
if (vcpu->domain==dom0 && !in_tpa) *pteval = trp->page_flags;
|
||||
else *pteval = vcpu->arch.dtlb_pte;
|
||||
// printf("DTLB MATCH... NEW, DOM%s, %s\n", vcpu->domain==dom0?
|
||||
// "0":"U", in_tpa?"vcpu_tpa":"ia64_do_page_fault");
|
||||
*itir = trp->itir;
|
||||
dtlb_translate_count++;
|
||||
return IA64_NO_FAULT;
|
||||
}
|
||||
|
||||
/* check guest VHPT */
|
||||
pta = PSCB(vcpu,pta);
|
||||
rr.rrval = PSCB(vcpu,rrs)[address>>61];
|
||||
if (!rr.ve || !(pta & IA64_PTA_VE)) {
|
||||
// FIXME? does iha get set for alt faults? does xenlinux depend on it?
|
||||
vcpu_thash(vcpu, address, iha);
|
||||
// FIXME?: does itir get set for alt faults?
|
||||
*itir = vcpu_get_itir_on_fault(vcpu,address);
|
||||
return (is_data ? IA64_ALT_DATA_TLB_VECTOR :
|
||||
IA64_ALT_INST_TLB_VECTOR);
|
||||
}
|
||||
if (pta & IA64_PTA_VF) { /* long format VHPT - not implemented */
|
||||
// thash won't work right?
|
||||
panic_domain(vcpu_regs(vcpu),"can't do long format VHPT\n");
|
||||
//return (is_data ? IA64_DATA_TLB_VECTOR:IA64_INST_TLB_VECTOR);
|
||||
}
|
||||
|
||||
*itir = rr & (RR_RID_MASK | RR_PS_MASK);
|
||||
// note: architecturally, iha is optionally set for alt faults but
|
||||
// xenlinux depends on it so should document it as part of PV interface
|
||||
vcpu_thash(vcpu, address, iha);
|
||||
if (!(rr & RR_VE_MASK) || !(pta & IA64_PTA_VE))
|
||||
return (is_data ? IA64_ALT_DATA_TLB_VECTOR : IA64_ALT_INST_TLB_VECTOR);
|
||||
|
||||
/* avoid recursively walking (short format) VHPT */
|
||||
pta_mask = (itir_mask(pta) << 3) >> 3;
|
||||
if (((address ^ pta) & pta_mask) == 0)
|
||||
if (((address ^ pta) & ((itir_mask(pta) << 3) >> 3)) == 0)
|
||||
return (is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR);
|
||||
|
||||
vcpu_thash(vcpu, address, iha);
|
||||
if (__copy_from_user(&pte, (void *)(*iha), sizeof(pte)) != 0) {
|
||||
// FIXME?: does itir get set for vhpt faults?
|
||||
*itir = vcpu_get_itir_on_fault(vcpu,*iha);
|
||||
if (__copy_from_user(&pte, (void *)(*iha), sizeof(pte)) != 0)
|
||||
// virtual VHPT walker "missed" in TLB
|
||||
return IA64_VHPT_FAULT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Optimisation: this VHPT walker aborts on not-present pages
|
||||
* instead of inserting a not-present translation, this allows
|
||||
* vectoring directly to the miss handler.
|
||||
*/
|
||||
if (pte & _PAGE_P) {
|
||||
*pteval = pte;
|
||||
*itir = vcpu_get_itir_on_fault(vcpu,address);
|
||||
vhpt_translate_count++;
|
||||
return IA64_NO_FAULT;
|
||||
}
|
||||
*itir = vcpu_get_itir_on_fault(vcpu,address);
|
||||
return (is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR);
|
||||
* Optimisation: this VHPT walker aborts on not-present pages
|
||||
* instead of inserting a not-present translation, this allows
|
||||
* vectoring directly to the miss handler.
|
||||
*/
|
||||
if (!(pte & _PAGE_P))
|
||||
return (is_data ? IA64_DATA_TLB_VECTOR : IA64_INST_TLB_VECTOR);
|
||||
|
||||
/* found mapping in guest VHPT! */
|
||||
*itir = rr & RR_PS_MASK;
|
||||
*pteval = pte;
|
||||
vhpt_translate_count++;
|
||||
return IA64_NO_FAULT;
|
||||
}
|
||||
|
||||
IA64FAULT vcpu_tpa(VCPU *vcpu, UINT64 vadr, UINT64 *padr)
|
||||
@@ -1736,33 +1682,6 @@ static void vcpu_set_tr_entry(TR_ENTRY *trp, UINT64 pte, UINT64 itir, UINT64 ifa
|
||||
}
|
||||
}
|
||||
|
||||
TR_ENTRY *vcpu_match_tr_entry(VCPU *vcpu, TR_ENTRY *trp, UINT64 ifa, int count)
|
||||
{
|
||||
unsigned long rid = (get_rr(ifa) & RR_RID_MASK);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++, trp++) {
|
||||
if (!trp->p) continue;
|
||||
if (physicalize_rid(vcpu,trp->rid) != rid) continue;
|
||||
if (ifa < trp->vadr) continue;
|
||||
if (ifa >= (trp->vadr + (1L << trp->ps)) - 1) continue;
|
||||
//if (trp->key && !match_pkr(vcpu,trp->key)) continue;
|
||||
return trp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
TR_ENTRY *match_tr(VCPU *vcpu, unsigned long ifa)
|
||||
{
|
||||
TR_ENTRY *trp;
|
||||
|
||||
trp = vcpu_match_tr_entry(vcpu,vcpu->arch.dtrs,ifa,NDTRS);
|
||||
if (trp) return trp;
|
||||
trp = vcpu_match_tr_entry(vcpu,vcpu->arch.itrs,ifa,NITRS);
|
||||
if (trp) return trp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
IA64FAULT vcpu_itr_d(VCPU *vcpu, UINT64 slot, UINT64 pte,
|
||||
UINT64 itir, UINT64 ifa)
|
||||
{
|
||||
@@ -1772,6 +1691,7 @@ IA64FAULT vcpu_itr_d(VCPU *vcpu, UINT64 slot, UINT64 pte,
|
||||
trp = &PSCBX(vcpu,dtrs[slot]);
|
||||
//printf("***** itr.d: setting slot %d: ifa=%p\n",slot,ifa);
|
||||
vcpu_set_tr_entry(trp,pte,itir,ifa);
|
||||
vcpu_quick_region_set(PSCBX(vcpu,dtr_regions),ifa);
|
||||
return IA64_NO_FAULT;
|
||||
}
|
||||
|
||||
@@ -1784,6 +1704,7 @@ IA64FAULT vcpu_itr_i(VCPU *vcpu, UINT64 slot, UINT64 pte,
|
||||
trp = &PSCBX(vcpu,itrs[slot]);
|
||||
//printf("***** itr.i: setting slot %d: ifa=%p\n",slot,ifa);
|
||||
vcpu_set_tr_entry(trp,pte,itir,ifa);
|
||||
vcpu_quick_region_set(PSCBX(vcpu,itr_regions),ifa);
|
||||
return IA64_NO_FAULT;
|
||||
}
|
||||
|
||||
@@ -1835,17 +1756,6 @@ void vcpu_itc_no_srlz(VCPU *vcpu, UINT64 IorD, UINT64 vaddr, UINT64 pte, UINT64
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: returns a physical pte, NOT a "metaphysical" pte, so do not check
|
||||
// the physical address contained for correctness
|
||||
TR_ENTRY *match_dtlb(VCPU *vcpu, unsigned long ifa)
|
||||
{
|
||||
TR_ENTRY *trp;
|
||||
|
||||
if (trp = vcpu_match_tr_entry(vcpu,&vcpu->arch.dtlb,ifa,1))
|
||||
return (&vcpu->arch.dtlb);
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
IA64FAULT vcpu_itc_d(VCPU *vcpu, UINT64 pte, UINT64 itir, UINT64 ifa)
|
||||
{
|
||||
unsigned long pteval, logps = (itir >> 2) & 0x3f;
|
||||
@@ -1952,12 +1862,14 @@ IA64FAULT vcpu_ptc_ga(VCPU *vcpu,UINT64 vadr,UINT64 addr_range)
|
||||
IA64FAULT vcpu_ptr_d(VCPU *vcpu,UINT64 vadr,UINT64 addr_range)
|
||||
{
|
||||
printf("vcpu_ptr_d: Purging TLB is unsupported\n");
|
||||
// don't forget to recompute dtr_regions
|
||||
return (IA64_ILLOP_FAULT);
|
||||
}
|
||||
|
||||
IA64FAULT vcpu_ptr_i(VCPU *vcpu,UINT64 vadr,UINT64 addr_range)
|
||||
{
|
||||
printf("vcpu_ptr_i: Purging TLB is unsupported\n");
|
||||
// don't forget to recompute itr_regions
|
||||
return (IA64_ILLOP_FAULT);
|
||||
}
|
||||
|
||||
@@ -48,11 +48,11 @@ END(platform_is_hp_ski)
|
||||
// FIXME? Note that this turns off the DB bit (debug)
|
||||
#define PSR_BITS_TO_SET IA64_PSR_BN
|
||||
|
||||
//extern void ia64_new_rr7(unsigned long rid,void *shared_info, void *shared_arch_info);
|
||||
//extern void ia64_new_rr7(unsigned long rid,void *shared_info, void *shared_arch_info, unsigned long p_vhpt, unsigned long v_pal);
|
||||
GLOBAL_ENTRY(ia64_new_rr7)
|
||||
// not sure this unwind statement is correct...
|
||||
.prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(1)
|
||||
alloc loc1 = ar.pfs, 3, 8, 0, 0
|
||||
alloc loc1 = ar.pfs, 5, 9, 0, 0
|
||||
1: {
|
||||
mov r28 = in0 // copy procedure index
|
||||
mov r8 = ip // save ip to compute branch
|
||||
@@ -63,10 +63,12 @@ GLOBAL_ENTRY(ia64_new_rr7)
|
||||
;;
|
||||
tpa loc2=loc2 // grab this BEFORE changing rr7
|
||||
;;
|
||||
#if VHPT_ENABLED
|
||||
movl loc6=VHPT_ADDR
|
||||
dep loc8=0,in4,60,4
|
||||
;;
|
||||
tpa loc6=loc6 // grab this BEFORE changing rr7
|
||||
#if VHPT_ENABLED
|
||||
mov loc6=in3
|
||||
;;
|
||||
//tpa loc6=loc6 // grab this BEFORE changing rr7
|
||||
;;
|
||||
#endif
|
||||
mov loc5=in1
|
||||
@@ -231,6 +233,21 @@ GLOBAL_ENTRY(ia64_new_rr7)
|
||||
itr.d dtr[r25]=r23 // wire in new mapping...
|
||||
;;
|
||||
|
||||
//Purge/insert PAL TR
|
||||
mov r24=IA64_TR_PALCODE
|
||||
movl r25=PAGE_KERNEL
|
||||
;;
|
||||
or loc8=r25,loc8
|
||||
mov r23=IA64_GRANULE_SHIFT<<2
|
||||
;;
|
||||
ptr.i in4,r23
|
||||
;;
|
||||
mov cr.itir=r23
|
||||
mov cr.ifa=in4
|
||||
;;
|
||||
itr.i itr[r24]=loc8
|
||||
;;
|
||||
|
||||
// done, switch back to virtual and return
|
||||
mov r16=loc3 // r16= original psr
|
||||
br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode
|
||||
|
||||
@@ -35,7 +35,7 @@ xen_debug_irq(ia64_vector vector, struct pt_regs *regs)
|
||||
int
|
||||
xen_do_IRQ(ia64_vector vector)
|
||||
{
|
||||
if (vector != 0xef) {
|
||||
if (vector != IA64_TIMER_VECTOR && vector != IA64_IPI_VECTOR) {
|
||||
extern void vcpu_pend_interrupt(void *, int);
|
||||
#if 0
|
||||
if (firsttime[vector]) {
|
||||
@@ -57,22 +57,18 @@ xen_do_IRQ(ia64_vector vector)
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* From linux/kernel/softirq.c */
|
||||
#ifdef __ARCH_IRQ_EXIT_IRQS_DISABLED
|
||||
# define invoke_softirq() __do_softirq()
|
||||
#else
|
||||
# define invoke_softirq() do_softirq()
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Exit an interrupt context. Process softirqs if needed and possible:
|
||||
*/
|
||||
void irq_exit(void)
|
||||
{
|
||||
//account_system_vtime(current);
|
||||
//sub_preempt_count(IRQ_EXIT_OFFSET);
|
||||
if (!in_interrupt() && local_softirq_pending())
|
||||
invoke_softirq();
|
||||
sub_preempt_count(IRQ_EXIT_OFFSET);
|
||||
if (!in_interrupt() && local_softirq_pending()) {
|
||||
add_preempt_count(SOFTIRQ_OFFSET);
|
||||
do_softirq();
|
||||
sub_preempt_count(SOFTIRQ_OFFSET);
|
||||
}
|
||||
//preempt_enable_no_resched();
|
||||
}
|
||||
/* end from linux/kernel/softirq.c */
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <asm/io.h>
|
||||
#include <xen/softirq.h>
|
||||
#include <public/sched.h>
|
||||
#include <asm/vhpt.h>
|
||||
|
||||
efi_memory_desc_t ia64_efi_io_md;
|
||||
EXPORT_SYMBOL(ia64_efi_io_md);
|
||||
@@ -280,6 +281,8 @@ void cs01foo(void) {}
|
||||
|
||||
unsigned long context_switch_count = 0;
|
||||
|
||||
#include <asm/vcpu.h>
|
||||
|
||||
void context_switch(struct vcpu *prev, struct vcpu *next)
|
||||
{
|
||||
//printk("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
|
||||
@@ -287,7 +290,8 @@ void context_switch(struct vcpu *prev, struct vcpu *next)
|
||||
//prev->domain->domain_id,(long)prev&0xffffff,next->domain->domain_id,(long)next&0xffffff);
|
||||
//if (prev->domain->domain_id == 1 && next->domain->domain_id == 0) cs10foo();
|
||||
//if (prev->domain->domain_id == 0 && next->domain->domain_id == 1) cs01foo();
|
||||
//printk("@@sw %d->%d\n",prev->domain->domain_id,next->domain->domain_id);
|
||||
printk("@@sw%d/%x %d->%d\n",smp_processor_id(), hard_smp_processor_id (),
|
||||
prev->domain->domain_id,next->domain->domain_id);
|
||||
if(VMX_DOMAIN(prev)){
|
||||
vtm_domain_out(prev);
|
||||
}
|
||||
@@ -307,9 +311,13 @@ if (!cnt[id]--) { printk("%x",id); cnt[id] = 500000; }
|
||||
if (!i--) { printk("+",id); i = 1000000; }
|
||||
}
|
||||
|
||||
if (VMX_DOMAIN(current)){
|
||||
if (VMX_DOMAIN(current)){
|
||||
vmx_load_all_rr(current);
|
||||
}else{
|
||||
extern char ia64_ivt;
|
||||
ia64_set_iva(&ia64_ivt);
|
||||
ia64_set_pta(VHPT_ADDR | (1 << 8) | (VHPT_SIZE_LOG2 << 2) |
|
||||
VHPT_ENABLED);
|
||||
if (!is_idle_task(current->domain)) {
|
||||
load_region_regs(current);
|
||||
if (vcpu_timer_expired(current)) vcpu_pend_timer(current);
|
||||
|
||||
@@ -253,11 +253,11 @@ void start_kernel(void)
|
||||
printk("About to call scheduler_init()\n");
|
||||
scheduler_init();
|
||||
local_irq_disable();
|
||||
init_IRQ ();
|
||||
printk("About to call init_xen_time()\n");
|
||||
init_xen_time(); /* initialise the time */
|
||||
printk("About to call ac_timer_init()\n");
|
||||
ac_timer_init();
|
||||
// init_xen_time(); ???
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
if ( opt_nosmp )
|
||||
@@ -276,6 +276,9 @@ printk("About to call ac_timer_init()\n");
|
||||
|
||||
//BUG_ON(!local_irq_is_enabled());
|
||||
|
||||
/* Enable IRQ to receive IPI (needed for ITC sync). */
|
||||
local_irq_enable();
|
||||
|
||||
printk("num_online_cpus=%d, max_cpus=%d\n",num_online_cpus(),max_cpus);
|
||||
for_each_present_cpu ( i )
|
||||
{
|
||||
@@ -287,24 +290,16 @@ printk("About to call __cpu_up(%d)\n",i);
|
||||
}
|
||||
}
|
||||
|
||||
local_irq_disable();
|
||||
|
||||
printk("Brought up %ld CPUs\n", (long)num_online_cpus());
|
||||
smp_cpus_done(max_cpus);
|
||||
#endif
|
||||
|
||||
|
||||
// FIXME: Should the following be swapped and moved later?
|
||||
schedulers_start();
|
||||
do_initcalls();
|
||||
printk("About to call sort_main_extable()\n");
|
||||
sort_main_extable();
|
||||
|
||||
/* surrender usage of kernel registers to domain, use percpu area instead */
|
||||
__get_cpu_var(cpu_kr)._kr[IA64_KR_IO_BASE] = ia64_get_kr(IA64_KR_IO_BASE);
|
||||
__get_cpu_var(cpu_kr)._kr[IA64_KR_PER_CPU_DATA] = ia64_get_kr(IA64_KR_PER_CPU_DATA);
|
||||
__get_cpu_var(cpu_kr)._kr[IA64_KR_CURRENT_STACK] = ia64_get_kr(IA64_KR_CURRENT_STACK);
|
||||
__get_cpu_var(cpu_kr)._kr[IA64_KR_FPU_OWNER] = ia64_get_kr(IA64_KR_FPU_OWNER);
|
||||
__get_cpu_var(cpu_kr)._kr[IA64_KR_CURRENT] = ia64_get_kr(IA64_KR_CURRENT);
|
||||
__get_cpu_var(cpu_kr)._kr[IA64_KR_PT_BASE] = ia64_get_kr(IA64_KR_PT_BASE);
|
||||
|
||||
/* Create initial domain 0. */
|
||||
printk("About to call do_createdomain()\n");
|
||||
@@ -342,6 +337,11 @@ printk("About to call construct_dom0()\n");
|
||||
0,
|
||||
0) != 0)
|
||||
panic("Could not set up DOM0 guest OS\n");
|
||||
|
||||
/* PIN domain0 on CPU 0. */
|
||||
dom0->vcpu[0]->cpumap=1;
|
||||
set_bit(_VCPUF_cpu_pinned, &dom0->vcpu[0]->vcpu_flags);
|
||||
|
||||
#ifdef CLONE_DOMAIN0
|
||||
{
|
||||
int i;
|
||||
@@ -379,9 +379,16 @@ printk("About to call init_trace_bufs()\n");
|
||||
domain_unpause_by_systemcontroller(clones[i]);
|
||||
}
|
||||
#endif
|
||||
domain_unpause_by_systemcontroller(dom0);
|
||||
domain0_ready = 1;
|
||||
|
||||
local_irq_enable();
|
||||
|
||||
printf("About to call schedulers_start dom0=%p, idle0_dom=%p\n",
|
||||
dom0, &idle0_domain);
|
||||
schedulers_start();
|
||||
|
||||
domain_unpause_by_systemcontroller(dom0);
|
||||
|
||||
printk("About to call startup_cpu_idle_loop()\n");
|
||||
startup_cpu_idle_loop();
|
||||
}
|
||||
|
||||
+31
-23
@@ -38,6 +38,20 @@ static s_time_t stime_irq = 0x0; /* System time at last 'time updat
|
||||
unsigned long itc_scale, ns_scale;
|
||||
unsigned long itc_at_irq;
|
||||
|
||||
/* We don't expect an absolute cycle value here, since then no way
|
||||
* to prevent overflow for large norminator. Normally this conversion
|
||||
* is used for relative offset.
|
||||
*/
|
||||
u64 cycle_to_ns(u64 cycle)
|
||||
{
|
||||
return (cycle * itc_scale) >> 32;
|
||||
}
|
||||
|
||||
u64 ns_to_cycle(u64 ns)
|
||||
{
|
||||
return (ns * ns_scale) >> 32;
|
||||
}
|
||||
|
||||
static inline u64 get_time_delta(void)
|
||||
{
|
||||
s64 delta_itc;
|
||||
@@ -52,19 +66,6 @@ static inline u64 get_time_delta(void)
|
||||
return cycle_to_ns(delta_itc);
|
||||
}
|
||||
|
||||
/* We don't expect an absolute cycle value here, since then no way
|
||||
* to prevent overflow for large norminator. Normally this conversion
|
||||
* is used for relative offset.
|
||||
*/
|
||||
u64 cycle_to_ns(u64 cycle)
|
||||
{
|
||||
return (cycle * itc_scale) >> 32;
|
||||
}
|
||||
|
||||
u64 ns_to_cycle(u64 ns)
|
||||
{
|
||||
return (ns * ns_scale) >> 32;
|
||||
}
|
||||
|
||||
s_time_t get_s_time(void)
|
||||
{
|
||||
@@ -99,16 +100,18 @@ xen_timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
unsigned long new_itm, old_itc;
|
||||
|
||||
#if 0
|
||||
#define HEARTBEAT_FREQ 16 // period in seconds
|
||||
#ifdef HEARTBEAT_FREQ
|
||||
static long count = 0;
|
||||
if (!(++count & ((HEARTBEAT_FREQ*1024)-1))) {
|
||||
printf("Heartbeat... iip=%p,psr.i=%d,pend=%d\n",
|
||||
regs->cr_iip,
|
||||
printf("Heartbeat... iip=%p\n", /*",psr.i=%d,pend=%d\n", */
|
||||
regs->cr_iip /*,
|
||||
VCPU(current,interrupt_delivery_enabled),
|
||||
VCPU(current,pending_interruption));
|
||||
VCPU(current,pending_interruption) */);
|
||||
count = 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
if (current->domain == dom0) {
|
||||
// FIXME: there's gotta be a better way of doing this...
|
||||
@@ -117,12 +120,14 @@ xen_timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
|
||||
//domain0_ready = 1; // moved to xensetup.c
|
||||
VCPU(current,pending_interruption) = 1;
|
||||
}
|
||||
if (domain0_ready && vcpu_timer_expired(dom0->vcpu[0])) {
|
||||
vcpu_pend_timer(dom0->vcpu[0]);
|
||||
//vcpu_set_next_timer(dom0->vcpu[0]);
|
||||
vcpu_wake(dom0->vcpu[0]);
|
||||
if (domain0_ready && current->domain != dom0) {
|
||||
if(vcpu_timer_expired(dom0->vcpu[0])) {
|
||||
vcpu_pend_timer(dom0->vcpu[0]);
|
||||
//vcpu_set_next_timer(dom0->vcpu[0]);
|
||||
vcpu_wake(dom0->vcpu[0]);
|
||||
}
|
||||
}
|
||||
if (!is_idle_task(current->domain) && current->domain != dom0) {
|
||||
if (!is_idle_task(current->domain)) {
|
||||
if (vcpu_timer_expired(current)) {
|
||||
vcpu_pend_timer(current);
|
||||
// ensure another timer interrupt happens even if domain doesn't
|
||||
@@ -132,9 +137,12 @@ xen_timer_interrupt (int irq, void *dev_id, struct pt_regs *regs)
|
||||
}
|
||||
new_itm = local_cpu_data->itm_next;
|
||||
|
||||
if (!time_after(ia64_get_itc(), new_itm))
|
||||
if (!VMX_DOMAIN(current) && !time_after(ia64_get_itc(), new_itm))
|
||||
return;
|
||||
|
||||
if (VMX_DOMAIN(current))
|
||||
vcpu_wake(current);
|
||||
|
||||
while (1) {
|
||||
new_itm += local_cpu_data->itm_delta;
|
||||
|
||||
@@ -233,7 +241,7 @@ int reprogram_ac_timer(s_time_t timeout)
|
||||
s_time_t expire;
|
||||
unsigned long seq, cur_itc, itm_next;
|
||||
|
||||
if (!domain0_ready) return 1;
|
||||
if (!domain0_ready || timeout == 0) return 1;
|
||||
|
||||
do {
|
||||
seq = read_seqbegin(&xtime_lock);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
+17
-5
@@ -1147,6 +1147,9 @@ asmlinkage void do_nmi(struct cpu_user_regs *regs, unsigned long reason)
|
||||
|
||||
asmlinkage int math_state_restore(struct cpu_user_regs *regs)
|
||||
{
|
||||
struct trap_bounce *tb;
|
||||
trap_info_t *ti;
|
||||
|
||||
/* Prevent recursion. */
|
||||
clts();
|
||||
|
||||
@@ -1154,10 +1157,15 @@ asmlinkage int math_state_restore(struct cpu_user_regs *regs)
|
||||
|
||||
if ( current->arch.guest_context.ctrlreg[0] & X86_CR0_TS )
|
||||
{
|
||||
struct trap_bounce *tb = ¤t->arch.trap_bounce;
|
||||
tb = ¤t->arch.trap_bounce;
|
||||
ti = ¤t->arch.guest_context.trap_ctxt[TRAP_no_device];
|
||||
|
||||
tb->flags = TBF_EXCEPTION;
|
||||
tb->cs = current->arch.guest_context.trap_ctxt[7].cs;
|
||||
tb->eip = current->arch.guest_context.trap_ctxt[7].address;
|
||||
tb->cs = ti->cs;
|
||||
tb->eip = ti->address;
|
||||
if ( TI_GET_IF(ti) )
|
||||
tb->flags |= TBF_INTERRUPT;
|
||||
|
||||
current->arch.guest_context.ctrlreg[0] &= ~X86_CR0_TS;
|
||||
}
|
||||
|
||||
@@ -1169,6 +1177,7 @@ asmlinkage int do_debug(struct cpu_user_regs *regs)
|
||||
unsigned long condition;
|
||||
struct vcpu *v = current;
|
||||
struct trap_bounce *tb = &v->arch.trap_bounce;
|
||||
trap_info_t *ti;
|
||||
|
||||
__asm__ __volatile__("mov %%db6,%0" : "=r" (condition));
|
||||
|
||||
@@ -1198,9 +1207,12 @@ asmlinkage int do_debug(struct cpu_user_regs *regs)
|
||||
/* Save debug status register where guest OS can peek at it */
|
||||
v->arch.guest_context.debugreg[6] = condition;
|
||||
|
||||
ti = &v->arch.guest_context.trap_ctxt[TRAP_debug];
|
||||
tb->flags = TBF_EXCEPTION;
|
||||
tb->cs = v->arch.guest_context.trap_ctxt[TRAP_debug].cs;
|
||||
tb->eip = v->arch.guest_context.trap_ctxt[TRAP_debug].address;
|
||||
tb->cs = ti->cs;
|
||||
tb->eip = ti->address;
|
||||
if ( TI_GET_IF(ti) )
|
||||
tb->flags |= TBF_INTERRUPT;
|
||||
|
||||
out:
|
||||
return EXCRET_not_a_fault;
|
||||
|
||||
+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 */
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
|
||||
#ifdef CONFIG_XEN_SMP
|
||||
#define CONFIG_SMP 1
|
||||
#define NR_CPUS 2
|
||||
#define CONFIG_NR_CPUS 2
|
||||
#define NR_CPUS 8
|
||||
#define CONFIG_NR_CPUS 8
|
||||
#else
|
||||
#undef CONFIG_SMP
|
||||
#define NR_CPUS 1
|
||||
@@ -102,7 +102,7 @@ extern char _end[]; /* standard ELF symbol */
|
||||
#endif
|
||||
|
||||
// xen/include/asm/config.h
|
||||
#define HZ 100
|
||||
//#define HZ 1000
|
||||
// FIXME SMP: leave SMP for a later time
|
||||
#define barrier() __asm__ __volatile__("": : :"memory")
|
||||
|
||||
@@ -123,8 +123,7 @@ extern char _end[]; /* standard ELF symbol */
|
||||
#ifdef CONFIG_SMP
|
||||
#warning "Lots of things to fix to enable CONFIG_SMP!"
|
||||
#endif
|
||||
// FIXME SMP
|
||||
#define get_cpu() 0
|
||||
#define get_cpu() smp_processor_id()
|
||||
#define put_cpu() do {} while(0)
|
||||
|
||||
// needed for common/dom0_ops.c until hyperthreading is supported
|
||||
@@ -140,6 +139,7 @@ struct page;
|
||||
// function calls; see decl in xen/include/xen/sched.h
|
||||
#undef free_task_struct
|
||||
#undef alloc_task_struct
|
||||
#define get_thread_info(v) alloc_thread_info(v)
|
||||
|
||||
// initial task has a different name in Xen
|
||||
//#define idle0_task init_task
|
||||
@@ -299,7 +299,11 @@ extern int ht_per_core;
|
||||
#endif /* __XEN_IA64_CONFIG_H__ */
|
||||
|
||||
// needed for include/xen/smp.h
|
||||
#ifdef CONFIG_SMP
|
||||
#define __smp_processor_id() current_thread_info()->cpu
|
||||
#else
|
||||
#define __smp_processor_id() 0
|
||||
#endif
|
||||
|
||||
|
||||
// FOLLOWING ADDED FOR XEN POST-NGIO and/or LINUX 2.6.7
|
||||
|
||||
@@ -49,6 +49,8 @@ struct arch_vcpu {
|
||||
TR_ENTRY dtrs[NDTRS];
|
||||
TR_ENTRY itlb;
|
||||
TR_ENTRY dtlb;
|
||||
unsigned int itr_regions;
|
||||
unsigned int dtr_regions;
|
||||
unsigned long itlb_pte;
|
||||
unsigned long dtlb_pte;
|
||||
unsigned long irr[4];
|
||||
|
||||
@@ -14,6 +14,21 @@
|
||||
|
||||
static inline void evtchn_notify(struct vcpu *v)
|
||||
{
|
||||
/*
|
||||
* NB1. 'vcpu_flags' and 'processor' must be checked /after/ update of
|
||||
* pending flag. These values may fluctuate (after all, we hold no
|
||||
* locks) but the key insight is that each change will cause
|
||||
* evtchn_upcall_pending to be polled.
|
||||
*
|
||||
* NB2. We save VCPUF_running across the unblock to avoid a needless
|
||||
* IPI for domains that we IPI'd to unblock.
|
||||
*/
|
||||
int running = test_bit(_VCPUF_running, &v->vcpu_flags);
|
||||
vcpu_unblock(v);
|
||||
if ( running )
|
||||
smp_send_event_check_cpu(v->processor);
|
||||
|
||||
if(!VMX_DOMAIN(v))
|
||||
vcpu_pend_interrupt(v, v->vcpu_info->arch.evtchn_vector);
|
||||
}
|
||||
|
||||
|
||||
Loaded 100 of 116 files, more files were not shown because too many files have changed in this diff.
Show more