mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 02:30:03 +01:00
merge with xen-unstable.hg
This commit is contained in:
commit
a63ce0c65d
57 files changed
+694
-427
No files matched your search
@@ -9,7 +9,7 @@
|
||||
#include <asm/page.h>
|
||||
#include <asm/thread_info.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <xen/interface/arch-x86_32.h>
|
||||
#include <xen/interface/xen.h>
|
||||
#include <xen/interface/elfnote.h>
|
||||
|
||||
/*
|
||||
@@ -192,6 +192,7 @@ ENTRY(cpu_gdt_table)
|
||||
#endif /* !CONFIG_XEN_COMPAT_030002 */
|
||||
ELFNOTE(Xen, XEN_ELFNOTE_ENTRY, .long, startup_32)
|
||||
ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .long, hypercall_page)
|
||||
ELFNOTE(Xen, XEN_ELFNOTE_HV_START_LOW, .long, HYPERVISOR_VIRT_START)
|
||||
ELFNOTE(Xen, XEN_ELFNOTE_FEATURES, .asciz, "writable_page_tables|writable_descriptor_tables|auto_translated_physmap|pae_pgdir_above_4gb|supervisor_mode_kernel")
|
||||
#ifdef CONFIG_X86_PAE
|
||||
ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE, .asciz, "yes")
|
||||
|
||||
@@ -282,12 +282,6 @@ static int spurious_fault(struct pt_regs *regs,
|
||||
pmd_t *pmd;
|
||||
pte_t *pte;
|
||||
|
||||
#ifdef CONFIG_XEN
|
||||
/* Faults in hypervisor area are never spurious. */
|
||||
if (address >= HYPERVISOR_VIRT_START)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
/* Reserved-bit violation or user access to kernel space? */
|
||||
if (error_code & 0x0c)
|
||||
return 0;
|
||||
@@ -372,7 +366,7 @@ fastcall void __kprobes do_page_fault(struct pt_regs *regs,
|
||||
if (unlikely(address >= TASK_SIZE)) {
|
||||
#ifdef CONFIG_XEN
|
||||
/* Faults in hypervisor area can never be patched up. */
|
||||
if (address >= HYPERVISOR_VIRT_START)
|
||||
if (address >= hypervisor_virt_start)
|
||||
goto bad_area_nosemaphore;
|
||||
#endif
|
||||
if (!(error_code & 5))
|
||||
|
||||
@@ -130,7 +130,7 @@ static void __init page_table_range_init (unsigned long start, unsigned long end
|
||||
pud = pud_offset(pgd, vaddr);
|
||||
pmd = pmd_offset(pud, vaddr);
|
||||
for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_idx++) {
|
||||
if (vaddr < HYPERVISOR_VIRT_START && pmd_none(*pmd))
|
||||
if (vaddr < hypervisor_virt_start && pmd_none(*pmd))
|
||||
one_page_table_init(pmd);
|
||||
|
||||
vaddr += PMD_SIZE;
|
||||
@@ -187,7 +187,7 @@ static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
|
||||
pmd += pmd_idx;
|
||||
for (; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_idx++) {
|
||||
unsigned int address = pfn * PAGE_SIZE + PAGE_OFFSET;
|
||||
if (address >= HYPERVISOR_VIRT_START)
|
||||
if (address >= hypervisor_virt_start)
|
||||
continue;
|
||||
|
||||
/* Map with big pages if possible, otherwise create normal page tables. */
|
||||
@@ -410,7 +410,7 @@ static void __init pagetable_init (void)
|
||||
* created - mappings will be set by set_fixmap():
|
||||
*/
|
||||
vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
|
||||
page_table_range_init(vaddr, 0, pgd_base);
|
||||
page_table_range_init(vaddr, hypervisor_virt_start, pgd_base);
|
||||
|
||||
permanent_kmaps_init(pgd_base);
|
||||
}
|
||||
|
||||
@@ -102,8 +102,11 @@ static void set_pte_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
|
||||
return;
|
||||
}
|
||||
pte = pte_offset_kernel(pmd, vaddr);
|
||||
/* <pfn,flags> stored as-is, to permit clearing entries */
|
||||
set_pte(pte, pfn_pte(pfn, flags));
|
||||
if (pgprot_val(flags))
|
||||
/* <pfn,flags> stored as-is, to permit clearing entries */
|
||||
set_pte(pte, pfn_pte(pfn, flags));
|
||||
else
|
||||
pte_clear(&init_mm, vaddr, pte);
|
||||
|
||||
/*
|
||||
* It's enough to flush this one mapping.
|
||||
@@ -140,8 +143,11 @@ static void set_pte_pfn_ma(unsigned long vaddr, unsigned long pfn,
|
||||
return;
|
||||
}
|
||||
pte = pte_offset_kernel(pmd, vaddr);
|
||||
/* <pfn,flags> stored as-is, to permit clearing entries */
|
||||
set_pte(pte, pfn_pte_ma(pfn, flags));
|
||||
if (pgprot_val(flags))
|
||||
/* <pfn,flags> stored as-is, to permit clearing entries */
|
||||
set_pte(pte, pfn_pte_ma(pfn, flags));
|
||||
else
|
||||
pte_clear(&init_mm, vaddr, pte);
|
||||
|
||||
/*
|
||||
* It's enough to flush this one mapping.
|
||||
@@ -186,9 +192,16 @@ void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
|
||||
}
|
||||
|
||||
static int nr_fixmaps = 0;
|
||||
unsigned long hypervisor_virt_start = HYPERVISOR_VIRT_START;
|
||||
unsigned long __FIXADDR_TOP = (HYPERVISOR_VIRT_START - 2 * PAGE_SIZE);
|
||||
EXPORT_SYMBOL(__FIXADDR_TOP);
|
||||
|
||||
void __init set_fixaddr_top()
|
||||
{
|
||||
BUG_ON(nr_fixmaps > 0);
|
||||
__FIXADDR_TOP = hypervisor_virt_start - 2 * PAGE_SIZE;
|
||||
}
|
||||
|
||||
void __set_fixmap (enum fixed_addresses idx, maddr_t phys, pgprot_t flags)
|
||||
{
|
||||
unsigned long address = __fix_to_virt(idx);
|
||||
@@ -211,12 +224,6 @@ void __set_fixmap (enum fixed_addresses idx, maddr_t phys, pgprot_t flags)
|
||||
nr_fixmaps++;
|
||||
}
|
||||
|
||||
void set_fixaddr_top(unsigned long top)
|
||||
{
|
||||
BUG_ON(nr_fixmaps > 0);
|
||||
__FIXADDR_TOP = top - PAGE_SIZE;
|
||||
}
|
||||
|
||||
pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
|
||||
{
|
||||
pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
|
||||
|
||||
@@ -260,7 +260,10 @@ static void set_pte_phys(unsigned long vaddr,
|
||||
return;
|
||||
}
|
||||
}
|
||||
new_pte = pfn_pte(phys >> PAGE_SHIFT, prot);
|
||||
if (pgprot_val(prot))
|
||||
new_pte = pfn_pte(phys >> PAGE_SHIFT, prot);
|
||||
else
|
||||
new_pte = __pte(0);
|
||||
|
||||
pte = pte_offset_kernel(pmd, vaddr);
|
||||
if (!pte_none(*pte) &&
|
||||
|
||||
@@ -165,7 +165,7 @@ static int privcmd_ioctl(struct inode *inode, struct file *file,
|
||||
struct mm_struct *mm = current->mm;
|
||||
struct vm_area_struct *vma;
|
||||
xen_pfn_t __user *p;
|
||||
unsigned long addr, mfn;
|
||||
unsigned long addr, mfn, nr_pages;
|
||||
int i;
|
||||
|
||||
if (!is_initial_xendomain())
|
||||
@@ -174,7 +174,8 @@ static int privcmd_ioctl(struct inode *inode, struct file *file,
|
||||
if (copy_from_user(&m, udata, sizeof(m)))
|
||||
return -EFAULT;
|
||||
|
||||
if ((m.num <= 0) || (m.num > (LONG_MAX >> PAGE_SHIFT)))
|
||||
nr_pages = m.num;
|
||||
if ((m.num <= 0) || (nr_pages > (LONG_MAX >> PAGE_SHIFT)))
|
||||
return -EINVAL;
|
||||
|
||||
down_read(&mm->mmap_sem);
|
||||
@@ -182,8 +183,7 @@ static int privcmd_ioctl(struct inode *inode, struct file *file,
|
||||
vma = find_vma(mm, m.addr);
|
||||
if (!vma ||
|
||||
(m.addr != vma->vm_start) ||
|
||||
((m.addr + ((unsigned long)m.num<<PAGE_SHIFT)) !=
|
||||
vma->vm_end) ||
|
||||
((m.addr + (nr_pages << PAGE_SHIFT)) != vma->vm_end) ||
|
||||
!privcmd_enforce_singleshot_mapping(vma)) {
|
||||
up_read(&mm->mmap_sem);
|
||||
return -EINVAL;
|
||||
@@ -191,7 +191,7 @@ static int privcmd_ioctl(struct inode *inode, struct file *file,
|
||||
|
||||
p = m.arr;
|
||||
addr = m.addr;
|
||||
for (i = 0; i < m.num; i++, addr += PAGE_SIZE, p++) {
|
||||
for (i = 0; i < nr_pages; i++, addr += PAGE_SIZE, p++) {
|
||||
if (get_user(mfn, p)) {
|
||||
up_read(&mm->mmap_sem);
|
||||
return -EFAULT;
|
||||
|
||||
@@ -98,7 +98,7 @@ enum fixed_addresses {
|
||||
extern void __set_fixmap(enum fixed_addresses idx,
|
||||
maddr_t phys, pgprot_t flags);
|
||||
|
||||
extern void set_fixaddr_top(unsigned long top);
|
||||
extern void set_fixaddr_top(void);
|
||||
|
||||
#define set_fixmap(idx, phys) \
|
||||
__set_fixmap(idx, phys, PAGE_KERNEL)
|
||||
|
||||
@@ -56,6 +56,10 @@
|
||||
|
||||
extern shared_info_t *HYPERVISOR_shared_info;
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
extern unsigned long hypervisor_virt_start;
|
||||
#endif
|
||||
|
||||
/* arch/xen/i386/kernel/setup.c */
|
||||
extern start_info_t *xen_start_info;
|
||||
#ifdef CONFIG_XEN_PRIVILEGED_GUEST
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
#define PGDIR_SHIFT 22
|
||||
#define PTRS_PER_PGD 1024
|
||||
#define PTRS_PER_PGD_NO_HV (HYPERVISOR_VIRT_START >> PGDIR_SHIFT)
|
||||
|
||||
/*
|
||||
* the i386 is two-level, so we don't really have any
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
*/
|
||||
#define PGDIR_SHIFT 30
|
||||
#define PTRS_PER_PGD 4
|
||||
#define PTRS_PER_PGD_NO_HV 4
|
||||
|
||||
/*
|
||||
* PMD_SHIFT determines the size of the area a middle-level
|
||||
|
||||
@@ -92,8 +92,10 @@ static void __init machine_specific_arch_setup(void)
|
||||
#endif
|
||||
|
||||
if (HYPERVISOR_xen_version(XENVER_platform_parameters,
|
||||
&pp) == 0)
|
||||
set_fixaddr_top(pp.virt_start - PAGE_SIZE);
|
||||
&pp) == 0) {
|
||||
hypervisor_virt_start = pp.virt_start;
|
||||
set_fixaddr_top();
|
||||
}
|
||||
|
||||
machine_to_phys_mapping = (unsigned long *)MACH2PHYS_VIRT_START;
|
||||
machine_to_phys_nr_ents = MACH2PHYS_NR_ENTRIES;
|
||||
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
# CHECK-BUILD CHECK-INSTALL
|
||||
|
||||
function error {
|
||||
echo
|
||||
echo " *** Check for crypto library FAILED"
|
||||
exit 1
|
||||
}
|
||||
|
||||
set -e
|
||||
ldconfig -p | grep -q libcrypto.so || error
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
# CHECK-BUILD
|
||||
|
||||
function error {
|
||||
echo
|
||||
echo " *** Check for openssl headers FAILED"
|
||||
exit 1
|
||||
}
|
||||
|
||||
set -e
|
||||
[ -e /usr/include/openssl/md5.h ] || error
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
# CHECK-BUILD
|
||||
|
||||
function error {
|
||||
echo
|
||||
echo " *** Check for x11 headers FAILED"
|
||||
exit 1
|
||||
}
|
||||
|
||||
set -e
|
||||
[ -e /usr/include/X11/keysymdef.h ] || error
|
||||
@@ -813,6 +813,58 @@ pop(struct regs *regs, unsigned prefix, unsigned opc)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
mov_to_seg(struct regs *regs, unsigned prefix, unsigned opc)
|
||||
{
|
||||
unsigned eip = regs->eip - 1;
|
||||
unsigned modrm = fetch8(regs);
|
||||
unsigned addr = operand(prefix, regs, modrm);
|
||||
|
||||
/* Only need to emulate segment loads in real->protected mode. */
|
||||
if (mode != VM86_REAL_TO_PROTECTED)
|
||||
return 0;
|
||||
|
||||
/* Register source only. */
|
||||
if ((modrm & 0xC0) != 0xC0)
|
||||
goto fail;
|
||||
|
||||
switch ((modrm & 0x38) >> 3) {
|
||||
case 0: /* es */
|
||||
regs->ves = getreg16(regs, modrm);
|
||||
saved_rm_regs.ves = 0;
|
||||
oldctx.es_sel = regs->ves;
|
||||
return 1;
|
||||
|
||||
/* case 1: cs */
|
||||
|
||||
case 2: /* ss */
|
||||
regs->uss = getreg16(regs, modrm);
|
||||
saved_rm_regs.uss = 0;
|
||||
oldctx.ss_sel = regs->uss;
|
||||
return 1;
|
||||
case 3: /* ds */
|
||||
regs->vds = getreg16(regs, modrm);
|
||||
saved_rm_regs.vds = 0;
|
||||
oldctx.ds_sel = regs->vds;
|
||||
return 1;
|
||||
case 4: /* fs */
|
||||
regs->vfs = getreg16(regs, modrm);
|
||||
saved_rm_regs.vfs = 0;
|
||||
oldctx.fs_sel = regs->vfs;
|
||||
return 1;
|
||||
case 5: /* gs */
|
||||
regs->vgs = getreg16(regs, modrm);
|
||||
saved_rm_regs.vgs = 0;
|
||||
oldctx.gs_sel = regs->vgs;
|
||||
return 1;
|
||||
}
|
||||
|
||||
fail:
|
||||
printf("%s:%d: missed opcode %02x %02x\n",
|
||||
__FUNCTION__, __LINE__, opc, modrm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Emulate a segment load in protected mode
|
||||
*/
|
||||
@@ -1257,11 +1309,9 @@ opcode(struct regs *regs)
|
||||
|
||||
for (;;) {
|
||||
switch ((opc = fetch8(regs))) {
|
||||
case 0x07:
|
||||
if (prefix & DATA32)
|
||||
regs->ves = pop32(regs);
|
||||
else
|
||||
regs->ves = pop16(regs);
|
||||
case 0x07: /* pop %es */
|
||||
regs->ves = (prefix & DATA32) ?
|
||||
pop32(regs) : pop16(regs);
|
||||
TRACE((regs, regs->eip - eip, "pop %%es"));
|
||||
if (mode == VM86_REAL_TO_PROTECTED) {
|
||||
saved_rm_regs.ves = 0;
|
||||
@@ -1316,6 +1366,16 @@ opcode(struct regs *regs)
|
||||
}
|
||||
goto invalid;
|
||||
|
||||
case 0x1F: /* pop %ds */
|
||||
regs->vds = (prefix & DATA32) ?
|
||||
pop32(regs) : pop16(regs);
|
||||
TRACE((regs, regs->eip - eip, "pop %%ds"));
|
||||
if (mode == VM86_REAL_TO_PROTECTED) {
|
||||
saved_rm_regs.vds = 0;
|
||||
oldctx.ds_sel = regs->vds;
|
||||
}
|
||||
return OPC_EMULATED;
|
||||
|
||||
case 0x26:
|
||||
TRACE((regs, regs->eip - eip, "%%es:"));
|
||||
prefix |= SEG_ES;
|
||||
@@ -1402,6 +1462,11 @@ opcode(struct regs *regs)
|
||||
goto invalid;
|
||||
return OPC_EMULATED;
|
||||
|
||||
case 0x8E: /* mov r16, sreg */
|
||||
if (!mov_to_seg(regs, prefix, opc))
|
||||
goto invalid;
|
||||
return OPC_EMULATED;
|
||||
|
||||
case 0x8F: /* addr32 pop r/m16 */
|
||||
if ((prefix & ADDR32) == 0)
|
||||
goto invalid;
|
||||
|
||||
@@ -398,8 +398,16 @@ void pci_piix4_acpi_init(PCIBus *bus, int devfn)
|
||||
pci_conf[0x0e] = 0x00;
|
||||
pci_conf[0x3d] = 0x01; /* Hardwired to PIRQA is used */
|
||||
|
||||
pci_register_io_region((PCIDevice *)d, 4, 0x10,
|
||||
PCI_ADDRESS_SPACE_IO, acpi_map);
|
||||
|
||||
/* PMBA POWER MANAGEMENT BASE ADDRESS, hardcoded to 0x1f40
|
||||
* to make shutdown work for IPF, due to IPF Guest Firmware
|
||||
* will enumerate pci devices.
|
||||
*
|
||||
* TODO: if Guest Firmware or Guest OS will change this PMBA,
|
||||
* More logic will be added.
|
||||
*/
|
||||
pci_conf[0x40] = 0x41; /* Special device-specific BAR at 0x40 */
|
||||
pci_conf[0x41] = 0x1f;
|
||||
acpi_map(d, 0, 0x1f40, 0x10, PCI_ADDRESS_SPACE_IO);
|
||||
acpi_reset(d);
|
||||
}
|
||||
@@ -338,10 +338,14 @@ static void pci_bios_init_device(PCIDevice *d)
|
||||
break;
|
||||
case 0x0680:
|
||||
if (vendor_id == 0x8086 && device_id == 0x7113) {
|
||||
/* PIIX4 ACPI PM */
|
||||
pci_config_writew(d, 0x20, 0x0000); /* NO smb bus IO enable in PIIX4 */
|
||||
/*
|
||||
* PIIX4 ACPI PM.
|
||||
* Special device with special PCI config space. No ordinary BARs.
|
||||
*/
|
||||
pci_config_writew(d, 0x20, 0x0000); // No smb bus IO enable
|
||||
pci_config_writew(d, 0x22, 0x0000);
|
||||
goto default_map;
|
||||
pci_config_writew(d, 0x3c, 0x0009); // Hardcoded IRQ9
|
||||
pci_config_writew(d, 0x3d, 0x0001);
|
||||
}
|
||||
break;
|
||||
case 0x0300:
|
||||
@@ -394,14 +398,6 @@ static void pci_bios_init_device(PCIDevice *d)
|
||||
pic_irq = pci_irqs[pin];
|
||||
pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq);
|
||||
}
|
||||
|
||||
if (class== 0x0680&& vendor_id == 0x8086 && device_id == 0x7113) {
|
||||
// PIIX4 ACPI PM
|
||||
pci_config_writew(d, 0x20, 0x0000); // NO smb bus IO enable in PIIX4
|
||||
pci_config_writew(d, 0x22, 0x0000);
|
||||
pci_config_writew(d, 0x3c, 0x0009); // Hardcodeed IRQ9
|
||||
pci_config_writew(d, 0x3d, 0x0001);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+20
-6
@@ -73,6 +73,11 @@
|
||||
#define UART_LSR_OE 0x02 /* Overrun error indicator */
|
||||
#define UART_LSR_DR 0x01 /* Receiver data ready */
|
||||
|
||||
/* Maximum retries for a single byte transmit. */
|
||||
#define WRITE_MAX_SINGLE_RETRIES 3
|
||||
/* Maximum retries for a sequence of back-to-back unsuccessful transmits. */
|
||||
#define WRITE_MAX_TOTAL_RETRIES 10
|
||||
|
||||
struct SerialState {
|
||||
uint8_t divider;
|
||||
uint8_t rbr; /* receive register */
|
||||
@@ -98,8 +103,12 @@ struct SerialState {
|
||||
* If a character transmitted via UART cannot be written to its
|
||||
* destination immediately we remember it here and retry a few times via
|
||||
* a polling timer.
|
||||
* - write_single_retries: Number of write retries for current byte.
|
||||
* - write_total_retries: Number of write retries for back-to-back
|
||||
* unsuccessful transmits.
|
||||
*/
|
||||
int write_retries;
|
||||
int write_single_retries;
|
||||
int write_total_retries;
|
||||
char write_chr;
|
||||
QEMUTimer *write_retry_timer;
|
||||
};
|
||||
@@ -217,16 +226,21 @@ static void serial_chr_write(void *opaque)
|
||||
{
|
||||
SerialState *s = opaque;
|
||||
|
||||
/* Cancel any outstanding retry if this is a new byte. */
|
||||
qemu_del_timer(s->write_retry_timer);
|
||||
|
||||
/* Retry every 100ms for 300ms total. */
|
||||
if (qemu_chr_write(s->chr, &s->write_chr, 1) == -1) {
|
||||
if (s->write_retries++ >= 3)
|
||||
printf("serial: write error\n");
|
||||
else
|
||||
s->write_total_retries++;
|
||||
if (s->write_single_retries++ >= WRITE_MAX_SINGLE_RETRIES)
|
||||
fprintf(stderr, "serial: write error\n");
|
||||
else if (s->write_total_retries <= WRITE_MAX_TOTAL_RETRIES) {
|
||||
qemu_mod_timer(s->write_retry_timer,
|
||||
qemu_get_clock(vm_clock) + ticks_per_sec / 10);
|
||||
return;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
s->write_total_retries = 0; /* if successful then reset counter */
|
||||
}
|
||||
|
||||
/* Success: Notify guest that THR is empty. */
|
||||
@@ -255,7 +269,7 @@ static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val)
|
||||
s->lsr &= ~UART_LSR_THRE;
|
||||
serial_update_irq(s);
|
||||
s->write_chr = val;
|
||||
s->write_retries = 0;
|
||||
s->write_single_retries = 0;
|
||||
serial_chr_write(s);
|
||||
}
|
||||
break;
|
||||
|
||||
+2
-1
@@ -6424,7 +6424,8 @@ int main(int argc, char **argv)
|
||||
page_array[i] = i;
|
||||
if (xc_domain_translate_gpfn_list(xc_handle, domid, tmp_nr_pages,
|
||||
page_array, page_array)) {
|
||||
fprintf(logfile, "xc_get_pfn_list returned error %d\n", errno);
|
||||
fprintf(logfile, "xc_domain_translate_gpfn_list returned error %d\n",
|
||||
errno);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ int
|
||||
fsig_devread(fsi_file_t *ffi, unsigned int sector, unsigned int offset,
|
||||
unsigned int bufsize, char *buf)
|
||||
{
|
||||
uint64_t off = ffi->ff_fsi->f_off + ((uint64_t)(sector * 512)) + offset;
|
||||
uint64_t off = ffi->ff_fsi->f_off + ((uint64_t)sector * 512) + offset;
|
||||
ssize_t bytes_read = 0;
|
||||
|
||||
while (bufsize) {
|
||||
|
||||
@@ -232,6 +232,7 @@ struct ext2_dir_entry
|
||||
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
||||
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
/* include/asm-i386/bitops.h */
|
||||
/*
|
||||
* ffz = Find First Zero in word. Undefined if no zero exists,
|
||||
@@ -251,6 +252,66 @@ ffz (unsigned long word)
|
||||
return word;
|
||||
}
|
||||
|
||||
#elif defined(__ia64__)
|
||||
|
||||
typedef unsigned long __u64;
|
||||
|
||||
#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
|
||||
# define ia64_popcnt(x) __builtin_popcountl(x)
|
||||
#else
|
||||
# define ia64_popcnt(x) \
|
||||
({ \
|
||||
__u64 ia64_intri_res; \
|
||||
asm ("popcnt %0=%1" : "=r" (ia64_intri_res) : "r" (x)); \
|
||||
ia64_intri_res; \
|
||||
})
|
||||
#endif
|
||||
|
||||
static __inline__ unsigned long
|
||||
ffz (unsigned long word)
|
||||
{
|
||||
unsigned long result;
|
||||
|
||||
result = ia64_popcnt(word & (~word - 1));
|
||||
return result;
|
||||
}
|
||||
|
||||
#elif defined(__powerpc__)
|
||||
|
||||
static __inline__ int
|
||||
__ilog2(unsigned long x)
|
||||
{
|
||||
int lz;
|
||||
|
||||
asm (PPC_CNTLZL "%0,%1" : "=r" (lz) : "r" (x));
|
||||
return BITS_PER_LONG - 1 - lz;
|
||||
}
|
||||
|
||||
static __inline__ unsigned long
|
||||
ffz (unsigned long word)
|
||||
{
|
||||
if ((word = ~word) == 0)
|
||||
return BITS_PER_LONG;
|
||||
return __ilog2(word & -word);
|
||||
}
|
||||
|
||||
#else /* Unoptimized */
|
||||
|
||||
static __inline__ unsigned long
|
||||
ffz (unsigned long word)
|
||||
{
|
||||
unsigned long result;
|
||||
|
||||
result = 0;
|
||||
while(word & 1)
|
||||
{
|
||||
result++;
|
||||
word >>= 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* check filesystem types and read superblock into memory buffer */
|
||||
int
|
||||
ext2fs_mount (fsi_file_t *ffi)
|
||||
|
||||
@@ -363,6 +363,8 @@ struct fsys_reiser_info
|
||||
#define JOURNAL_START ((__u32 *) (INFO + 1))
|
||||
#define JOURNAL_END ((__u32 *) (FSYS_BUF + FSYS_BUFLEN))
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
|
||||
#ifdef __amd64
|
||||
#define BSF "bsfq"
|
||||
#else
|
||||
@@ -376,6 +378,61 @@ grub_log2 (unsigned long word)
|
||||
: "r" (word));
|
||||
return word;
|
||||
}
|
||||
|
||||
#elif defined(__ia64__)
|
||||
|
||||
#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
|
||||
# define ia64_popcnt(x) __builtin_popcountl(x)
|
||||
#else
|
||||
# define ia64_popcnt(x) \
|
||||
({ \
|
||||
__u64 ia64_intri_res; \
|
||||
asm ("popcnt %0=%1" : "=r" (ia64_intri_res) : "r" (x)); \
|
||||
ia64_intri_res; \
|
||||
})
|
||||
#endif
|
||||
|
||||
static __inline__ unsigned long
|
||||
grub_log2 (unsigned long word)
|
||||
{
|
||||
unsigned long result;
|
||||
|
||||
result = ia64_popcnt((word - 1) & ~word);
|
||||
return result;
|
||||
}
|
||||
|
||||
#elif defined(__powerpc__)
|
||||
|
||||
static __inline__ int
|
||||
__ilog2(unsigned long x)
|
||||
{
|
||||
int lz;
|
||||
|
||||
asm (PPC_CNTLZL "%0,%1" : "=r" (lz) : "r" (x));
|
||||
return BITS_PER_LONG - 1 - lz;
|
||||
}
|
||||
|
||||
static __inline__ unsigned long
|
||||
grub_log2 (unsigned long word)
|
||||
{
|
||||
return __ilog2(word & -word);
|
||||
}
|
||||
|
||||
#else /* Unoptimized */
|
||||
|
||||
static __inline__ unsigned long
|
||||
grub_log2 (unsigned long word)
|
||||
{
|
||||
unsigned long result = 0;
|
||||
|
||||
while (!(word & 1UL))
|
||||
{
|
||||
result++;
|
||||
word >>= 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
#define log2 grub_log2
|
||||
|
||||
static __inline__ int
|
||||
|
||||
@@ -575,8 +575,10 @@ struct node *get_node(struct connection *conn,
|
||||
/* If we don't have permission, we don't have node. */
|
||||
if (node) {
|
||||
if ((perm_for_conn(conn, node->perms, node->num_perms) & perm)
|
||||
!= perm)
|
||||
!= perm) {
|
||||
errno = EACCES;
|
||||
node = NULL;
|
||||
}
|
||||
}
|
||||
/* Clean up errno if they weren't supposed to know. */
|
||||
if (!node)
|
||||
@@ -789,7 +791,7 @@ static void delete_node_single(struct connection *conn, struct node *node)
|
||||
corrupt(conn, "Could not delete '%s'", node->name);
|
||||
return;
|
||||
}
|
||||
domain_entry_dec(conn);
|
||||
domain_entry_dec(conn, node);
|
||||
}
|
||||
|
||||
/* Must not be / */
|
||||
@@ -840,7 +842,7 @@ static struct node *construct_node(struct connection *conn, const char *name)
|
||||
node->children = node->data = NULL;
|
||||
node->childlen = node->datalen = 0;
|
||||
node->parent = parent;
|
||||
domain_entry_inc(conn);
|
||||
domain_entry_inc(conn, node);
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -876,7 +878,7 @@ static struct node *create_node(struct connection *conn,
|
||||
* something goes wrong. */
|
||||
for (i = node; i; i = i->parent) {
|
||||
if (!write_node(conn, i)) {
|
||||
domain_entry_dec(conn);
|
||||
domain_entry_dec(conn, i);
|
||||
return NULL;
|
||||
}
|
||||
talloc_set_destructor(i, destroy_node);
|
||||
@@ -1106,6 +1108,7 @@ static void do_get_perms(struct connection *conn, const char *name)
|
||||
static void do_set_perms(struct connection *conn, struct buffered_data *in)
|
||||
{
|
||||
unsigned int num;
|
||||
struct xs_permissions *perms;
|
||||
char *name, *permstr;
|
||||
struct node *node;
|
||||
|
||||
@@ -1127,12 +1130,24 @@ static void do_set_perms(struct connection *conn, struct buffered_data *in)
|
||||
return;
|
||||
}
|
||||
|
||||
node->perms = talloc_array(node, struct xs_permissions, num);
|
||||
node->num_perms = num;
|
||||
if (!xs_strings_to_perms(node->perms, num, permstr)) {
|
||||
perms = talloc_array(node, struct xs_permissions, num);
|
||||
if (!xs_strings_to_perms(perms, num, permstr)) {
|
||||
send_error(conn, errno);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Unprivileged domains may not change the owner. */
|
||||
if (domain_is_unprivileged(conn) &&
|
||||
perms[0].id != node->perms[0].id) {
|
||||
send_error(conn, EPERM);
|
||||
return;
|
||||
}
|
||||
|
||||
domain_entry_dec(conn, node);
|
||||
node->perms = perms;
|
||||
node->num_perms = num;
|
||||
domain_entry_inc(conn, node);
|
||||
|
||||
if (!write_node(conn, node)) {
|
||||
send_error(conn, errno);
|
||||
return;
|
||||
|
||||
@@ -501,18 +501,35 @@ int domain_init(void)
|
||||
return xce_handle;
|
||||
}
|
||||
|
||||
void domain_entry_inc(struct connection *conn)
|
||||
void domain_entry_inc(struct connection *conn, struct node *node)
|
||||
{
|
||||
if (!conn || !conn->domain)
|
||||
struct domain *d;
|
||||
|
||||
if (!conn)
|
||||
return;
|
||||
conn->domain->nbentry++;
|
||||
|
||||
if (node->perms && node->perms[0].id != conn->id) {
|
||||
d = find_domain_by_domid(node->perms[0].id);
|
||||
if (d)
|
||||
d->nbentry++;
|
||||
}
|
||||
else if (conn->domain) {
|
||||
conn->domain->nbentry++;
|
||||
}
|
||||
}
|
||||
|
||||
void domain_entry_dec(struct connection *conn)
|
||||
void domain_entry_dec(struct connection *conn, struct node *node)
|
||||
{
|
||||
if (!conn || !conn->domain)
|
||||
struct domain *d;
|
||||
|
||||
if (!conn)
|
||||
return;
|
||||
if (conn->domain->nbentry)
|
||||
|
||||
if (node->perms && node->perms[0].id != conn->id) {
|
||||
d = find_domain_by_domid(node->perms[0].id);
|
||||
if (d && d->nbentry)
|
||||
d->nbentry--;
|
||||
} else if (conn->domain && conn->domain->nbentry)
|
||||
conn->domain->nbentry--;
|
||||
}
|
||||
|
||||
|
||||
@@ -50,8 +50,8 @@ bool domain_can_write(struct connection *conn);
|
||||
bool domain_is_unprivileged(struct connection *conn);
|
||||
|
||||
/* Quota manipulation */
|
||||
void domain_entry_inc(struct connection *conn);
|
||||
void domain_entry_dec(struct connection *conn);
|
||||
void domain_entry_inc(struct connection *conn, struct node *);
|
||||
void domain_entry_dec(struct connection *conn, struct node *);
|
||||
int domain_entry(struct connection *conn);
|
||||
void domain_watch_inc(struct connection *conn);
|
||||
void domain_watch_dec(struct connection *conn);
|
||||
|
||||
@@ -196,21 +196,16 @@ ENTRY(stack_start)
|
||||
|
||||
/*** DESCRIPTOR TABLES ***/
|
||||
|
||||
.globl idt
|
||||
.globl gdt
|
||||
|
||||
ALIGN
|
||||
|
||||
.word 0
|
||||
idt_descr:
|
||||
.word 256*8-1
|
||||
idt:
|
||||
.long idt_table
|
||||
|
||||
.word 0
|
||||
gdt_descr:
|
||||
.word LAST_RESERVED_GDT_BYTE
|
||||
gdt:
|
||||
.long gdt_table - FIRST_RESERVED_GDT_BYTE
|
||||
|
||||
.word 0
|
||||
|
||||
@@ -192,9 +192,6 @@ ignore_int:
|
||||
|
||||
/*** DESCRIPTOR TABLES ***/
|
||||
|
||||
.globl idt
|
||||
.globl gdt
|
||||
|
||||
.align 8, 0xCC
|
||||
multiboot_ptr:
|
||||
.long 0
|
||||
@@ -210,13 +207,11 @@ cpuid_ext_features:
|
||||
.word 0
|
||||
gdt_descr:
|
||||
.word LAST_RESERVED_GDT_BYTE
|
||||
gdt:
|
||||
.quad gdt_table - FIRST_RESERVED_GDT_BYTE
|
||||
|
||||
.word 0,0,0
|
||||
idt_descr:
|
||||
.word 256*16-1
|
||||
idt:
|
||||
.quad idt_table
|
||||
|
||||
ENTRY(stack_start)
|
||||
|
||||
@@ -2,6 +2,6 @@ obj-y += k7.o
|
||||
obj-y += mce.o
|
||||
obj-y += non-fatal.o
|
||||
obj-y += p4.o
|
||||
obj-y += p5.o
|
||||
obj-y += p6.o
|
||||
obj-y += winchip.o
|
||||
obj-$(x86_32) += p5.o
|
||||
obj-$(x86_32) += p6.o
|
||||
obj-$(x86_32) += winchip.o
|
||||
@@ -39,18 +39,22 @@ void mcheck_init(struct cpuinfo_x86 *c)
|
||||
break;
|
||||
|
||||
case X86_VENDOR_INTEL:
|
||||
#ifndef CONFIG_X86_64
|
||||
if (c->x86==5)
|
||||
intel_p5_mcheck_init(c);
|
||||
if (c->x86==6)
|
||||
intel_p6_mcheck_init(c);
|
||||
#endif
|
||||
if (c->x86==15)
|
||||
intel_p4_mcheck_init(c);
|
||||
break;
|
||||
|
||||
#ifndef CONFIG_X86_64
|
||||
case X86_VENDOR_CENTAUR:
|
||||
if (c->x86==5)
|
||||
winchip_mcheck_init(c);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
obj-y += amd.o
|
||||
obj-y += centaur.o
|
||||
obj-y += cyrix.o
|
||||
obj-$(x86_32) += amd.o
|
||||
obj-$(x86_32) += centaur.o
|
||||
obj-$(x86_32) += cyrix.o
|
||||
obj-y += generic.o
|
||||
obj-y += main.o
|
||||
obj-y += state.o
|
||||
@@ -64,7 +64,11 @@ struct mtrr_ops * mtrr_if = NULL;
|
||||
static void set_mtrr(unsigned int reg, unsigned long base,
|
||||
unsigned long size, mtrr_type type);
|
||||
|
||||
#ifndef CONFIG_X86_64
|
||||
extern int arr3_protected;
|
||||
#else
|
||||
#define arr3_protected 0
|
||||
#endif
|
||||
|
||||
static char *mtrr_strings[MTRR_NUM_TYPES] =
|
||||
{
|
||||
@@ -539,9 +543,11 @@ extern void centaur_init_mtrr(void);
|
||||
|
||||
static void __init init_ifs(void)
|
||||
{
|
||||
#ifndef CONFIG_X86_64
|
||||
amd_init_mtrr();
|
||||
cyrix_init_mtrr();
|
||||
centaur_init_mtrr();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* The suspend/resume methods are only for CPU without MTRR. CPU using generic
|
||||
@@ -593,6 +599,7 @@ void __init mtrr_bp_init(void)
|
||||
size_and_mask = 0;
|
||||
}
|
||||
} else {
|
||||
#ifndef CONFIG_X86_64
|
||||
switch (boot_cpu_data.x86_vendor) {
|
||||
case X86_VENDOR_AMD:
|
||||
if (cpu_has_k6_mtrr) {
|
||||
@@ -619,6 +626,7 @@ void __init mtrr_bp_init(void)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (mtrr_if) {
|
||||
|
||||
+14
-13
@@ -166,6 +166,9 @@ void vcpu_destroy(struct vcpu *v)
|
||||
|
||||
int arch_domain_create(struct domain *d)
|
||||
{
|
||||
#ifdef __x86_64__
|
||||
struct page_info *pg;
|
||||
#endif
|
||||
l1_pgentry_t gdt_l1e;
|
||||
int vcpuid, pdpt_order;
|
||||
int i, rc = -ENOMEM;
|
||||
@@ -194,19 +197,17 @@ int arch_domain_create(struct domain *d)
|
||||
|
||||
#else /* __x86_64__ */
|
||||
|
||||
d->arch.mm_perdomain_l2 = alloc_xenheap_page();
|
||||
d->arch.mm_perdomain_l3 = alloc_xenheap_page();
|
||||
if ( (d->arch.mm_perdomain_l2 == NULL) ||
|
||||
(d->arch.mm_perdomain_l3 == NULL) )
|
||||
if ( (pg = alloc_domheap_page(NULL)) == NULL )
|
||||
goto fail;
|
||||
|
||||
memset(d->arch.mm_perdomain_l2, 0, PAGE_SIZE);
|
||||
d->arch.mm_perdomain_l2 = clear_page(page_to_virt(pg));
|
||||
for ( i = 0; i < (1 << pdpt_order); i++ )
|
||||
d->arch.mm_perdomain_l2[l2_table_offset(PERDOMAIN_VIRT_START)+i] =
|
||||
l2e_from_page(virt_to_page(d->arch.mm_perdomain_pt)+i,
|
||||
__PAGE_HYPERVISOR);
|
||||
|
||||
memset(d->arch.mm_perdomain_l3, 0, PAGE_SIZE);
|
||||
if ( (pg = alloc_domheap_page(NULL)) == NULL )
|
||||
goto fail;
|
||||
d->arch.mm_perdomain_l3 = clear_page(page_to_virt(pg));
|
||||
d->arch.mm_perdomain_l3[l3_table_offset(PERDOMAIN_VIRT_START)] =
|
||||
l3e_from_page(virt_to_page(d->arch.mm_perdomain_l2),
|
||||
__PAGE_HYPERVISOR);
|
||||
@@ -240,8 +241,8 @@ int arch_domain_create(struct domain *d)
|
||||
fail:
|
||||
free_xenheap_page(d->shared_info);
|
||||
#ifdef __x86_64__
|
||||
free_xenheap_page(d->arch.mm_perdomain_l2);
|
||||
free_xenheap_page(d->arch.mm_perdomain_l3);
|
||||
free_domheap_page(virt_to_page(d->arch.mm_perdomain_l2));
|
||||
free_domheap_page(virt_to_page(d->arch.mm_perdomain_l3));
|
||||
#endif
|
||||
free_xenheap_pages(d->arch.mm_perdomain_pt, pdpt_order);
|
||||
return rc;
|
||||
@@ -265,8 +266,8 @@ void arch_domain_destroy(struct domain *d)
|
||||
get_order_from_bytes(PDPT_L1_ENTRIES * sizeof(l1_pgentry_t)));
|
||||
|
||||
#ifdef __x86_64__
|
||||
free_xenheap_page(d->arch.mm_perdomain_l2);
|
||||
free_xenheap_page(d->arch.mm_perdomain_l3);
|
||||
free_domheap_page(virt_to_page(d->arch.mm_perdomain_l2));
|
||||
free_domheap_page(virt_to_page(d->arch.mm_perdomain_l3));
|
||||
#endif
|
||||
|
||||
free_xenheap_page(d->shared_info);
|
||||
@@ -587,9 +588,9 @@ static void load_segments(struct vcpu *n)
|
||||
regs->entry_vector = TRAP_syscall;
|
||||
regs->rflags &= ~(X86_EFLAGS_AC|X86_EFLAGS_VM|X86_EFLAGS_RF|
|
||||
X86_EFLAGS_NT|X86_EFLAGS_TF);
|
||||
regs->ss = __GUEST_SS;
|
||||
regs->ss = FLAT_KERNEL_SS;
|
||||
regs->rsp = (unsigned long)(rsp-11);
|
||||
regs->cs = __GUEST_CS;
|
||||
regs->cs = FLAT_KERNEL_CS;
|
||||
regs->rip = nctxt->failsafe_callback_eip;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -517,7 +517,8 @@ int hvm_bringup_ap(int vcpuid, int trampoline_vector)
|
||||
if ( bsp->vcpu_id != 0 )
|
||||
{
|
||||
gdprintk(XENLOG_ERR, "Not calling hvm_bringup_ap from BSP context.\n");
|
||||
domain_crash_synchronous();
|
||||
domain_crash(bsp->domain);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ( (v = d->vcpu[vcpuid]) == NULL )
|
||||
|
||||
@@ -253,11 +253,7 @@ int register_io_handler(
|
||||
struct hvm_io_handler *handler = &d->arch.hvm_domain.io_handler;
|
||||
int num = handler->num_slot;
|
||||
|
||||
if ( num >= MAX_IO_HANDLER )
|
||||
{
|
||||
printk("no extra space, register io interceptor failed!\n");
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
BUG_ON(num >= MAX_IO_HANDLER);
|
||||
|
||||
handler->hdl_list[num].addr = addr;
|
||||
handler->hdl_list[num].size = size;
|
||||
|
||||
+9
-14
@@ -81,9 +81,7 @@ static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *r
|
||||
regs->ebx |= ((value & 0xFF) << 8);
|
||||
break;
|
||||
default:
|
||||
printk("Error: size:%x, index:%x are invalid!\n", size, index);
|
||||
domain_crash_synchronous();
|
||||
break;
|
||||
goto crash;
|
||||
}
|
||||
break;
|
||||
case WORD:
|
||||
@@ -121,9 +119,7 @@ static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *r
|
||||
regs->edi |= (value & 0xFFFF);
|
||||
break;
|
||||
default:
|
||||
printk("Error: size:%x, index:%x are invalid!\n", size, index);
|
||||
domain_crash_synchronous();
|
||||
break;
|
||||
goto crash;
|
||||
}
|
||||
break;
|
||||
case LONG:
|
||||
@@ -153,15 +149,13 @@ static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *r
|
||||
regs->edi = value;
|
||||
break;
|
||||
default:
|
||||
printk("Error: size:%x, index:%x are invalid!\n", size, index);
|
||||
domain_crash_synchronous();
|
||||
break;
|
||||
goto crash;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printk("Error: size:%x, index:%x are invalid!\n", size, index);
|
||||
crash:
|
||||
gdprintk(XENLOG_ERR, "size:%x, index:%x are invalid!\n", size, index);
|
||||
domain_crash_synchronous();
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
@@ -184,7 +178,7 @@ static inline void __set_reg_value(unsigned long *reg, int size, long value)
|
||||
*reg = value;
|
||||
break;
|
||||
default:
|
||||
printk("Error: <__set_reg_value>: size:%x is invalid\n", size);
|
||||
gdprintk(XENLOG_ERR, "size:%x is invalid\n", size);
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
}
|
||||
@@ -226,7 +220,8 @@ static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *r
|
||||
regs->rbx |= ((value & 0xFF) << 8);
|
||||
break;
|
||||
default:
|
||||
printk("Error: size:%x, index:%x are invalid!\n", size, index);
|
||||
gdprintk(XENLOG_ERR, "size:%x, index:%x are invalid!\n",
|
||||
size, index);
|
||||
domain_crash_synchronous();
|
||||
break;
|
||||
}
|
||||
@@ -283,7 +278,7 @@ static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *r
|
||||
__set_reg_value(®s->r15, size, value);
|
||||
break;
|
||||
default:
|
||||
printk("Error: <set_reg_value> Invalid index\n");
|
||||
gdprintk(XENLOG_ERR, "Invalid index\n");
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -731,8 +731,7 @@ static void hvm_send_assist_req(struct vcpu *v)
|
||||
{
|
||||
/* This indicates a bug in the device model. Crash the domain. */
|
||||
gdprintk(XENLOG_ERR, "Device model set bad IO state %d.\n", p->state);
|
||||
domain_crash(v->domain);
|
||||
return;
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
|
||||
prepare_wait_on_xen_event_channel(v->arch.hvm_vcpu.xen_port);
|
||||
|
||||
+56
-62
@@ -326,14 +326,14 @@ static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
|
||||
static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
|
||||
{
|
||||
u64 msr_content = (u32)regs->eax | ((u64)regs->edx << 32);
|
||||
struct vcpu *vc = current;
|
||||
struct vmcb_struct *vmcb = vc->arch.hvm_svm.vmcb;
|
||||
struct vcpu *v = current;
|
||||
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
|
||||
|
||||
HVM_DBG_LOG(DBG_LEVEL_1, "mode_do_msr_write msr %lx "
|
||||
"msr_content %"PRIx64"\n",
|
||||
(unsigned long)regs->ecx, msr_content);
|
||||
|
||||
switch (regs->ecx)
|
||||
switch ( regs->ecx )
|
||||
{
|
||||
case MSR_EFER:
|
||||
#ifdef __x86_64__
|
||||
@@ -342,24 +342,24 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
|
||||
{
|
||||
printk("Trying to set reserved bit in EFER: %"PRIx64"\n",
|
||||
msr_content);
|
||||
svm_inject_exception(vc, TRAP_gp_fault, 1, 0);
|
||||
svm_inject_exception(v, TRAP_gp_fault, 1, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* LME: 0 -> 1 */
|
||||
if ( msr_content & EFER_LME &&
|
||||
!test_bit(SVM_CPU_STATE_LME_ENABLED, &vc->arch.hvm_svm.cpu_state))
|
||||
!test_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state))
|
||||
{
|
||||
if ( svm_paging_enabled(vc) ||
|
||||
if ( svm_paging_enabled(v) ||
|
||||
!test_bit(SVM_CPU_STATE_PAE_ENABLED,
|
||||
&vc->arch.hvm_svm.cpu_state) )
|
||||
&v->arch.hvm_svm.cpu_state) )
|
||||
{
|
||||
printk("Trying to set LME bit when "
|
||||
"in paging mode or PAE bit is not set\n");
|
||||
svm_inject_exception(vc, TRAP_gp_fault, 1, 0);
|
||||
svm_inject_exception(v, TRAP_gp_fault, 1, 0);
|
||||
return 0;
|
||||
}
|
||||
set_bit(SVM_CPU_STATE_LME_ENABLED, &vc->arch.hvm_svm.cpu_state);
|
||||
set_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state);
|
||||
}
|
||||
|
||||
/* We have already recorded that we want LME, so it will be set
|
||||
@@ -374,13 +374,13 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
|
||||
|
||||
case MSR_FS_BASE:
|
||||
case MSR_GS_BASE:
|
||||
if ( !svm_long_mode_enabled(vc) )
|
||||
domain_crash_synchronous();
|
||||
if ( !svm_long_mode_enabled(v) )
|
||||
goto exit_and_crash;
|
||||
|
||||
if (!IS_CANO_ADDRESS(msr_content))
|
||||
{
|
||||
HVM_DBG_LOG(DBG_LEVEL_1, "Not cano address of msr write\n");
|
||||
svm_inject_exception(vc, TRAP_gp_fault, 1, 0);
|
||||
svm_inject_exception(v, TRAP_gp_fault, 1, 0);
|
||||
}
|
||||
|
||||
if (regs->ecx == MSR_FS_BASE)
|
||||
@@ -412,7 +412,13 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
exit_and_crash:
|
||||
gdprintk(XENLOG_ERR, "Fatal error writing MSR %lx\n", (long)regs->ecx);
|
||||
domain_crash(v->domain);
|
||||
return 1; /* handled */
|
||||
}
|
||||
|
||||
|
||||
@@ -421,7 +427,6 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
|
||||
#define savedebug(_v,_reg) \
|
||||
__asm__ __volatile__ ("mov %%db" #_reg ",%0" : : "r" ((_v)->debugreg[_reg]))
|
||||
|
||||
|
||||
static inline void svm_save_dr(struct vcpu *v)
|
||||
{
|
||||
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
|
||||
@@ -938,7 +943,8 @@ static void svm_do_general_protection_fault(struct vcpu *v,
|
||||
svm_dump_vmcb(__func__, vmcb);
|
||||
svm_dump_regs(__func__, regs);
|
||||
svm_dump_inst(vmcb->rip);
|
||||
__hvm_bug(regs);
|
||||
domain_crash(v->domain);
|
||||
return;
|
||||
}
|
||||
|
||||
HVM_DBG_LOG(DBG_LEVEL_1,
|
||||
@@ -1169,8 +1175,9 @@ static void svm_get_prefix_info(
|
||||
if (inst_copy_from_guest(inst, svm_rip2pointer(vmcb), sizeof(inst))
|
||||
!= MAX_INST_LEN)
|
||||
{
|
||||
printk("%s: get guest instruction failed\n", __func__);
|
||||
domain_crash_synchronous();
|
||||
gdprintk(XENLOG_ERR, "get guest instruction failed\n");
|
||||
domain_crash(current->domain);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_INST_LEN; i++)
|
||||
@@ -1266,9 +1273,7 @@ static inline int svm_get_io_address(
|
||||
isize --;
|
||||
|
||||
if (isize > 1)
|
||||
{
|
||||
svm_get_prefix_info(vmcb, dir, &seg, &asize);
|
||||
}
|
||||
|
||||
ASSERT(dir == IOREQ_READ || dir == IOREQ_WRITE);
|
||||
|
||||
@@ -1470,8 +1475,10 @@ static int svm_set_cr0(unsigned long value)
|
||||
mfn = get_mfn_from_gpfn(v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT);
|
||||
if ( !VALID_MFN(mfn) || !get_page(mfn_to_page(mfn), v->domain))
|
||||
{
|
||||
printk("Invalid CR3 value = %lx\n", v->arch.hvm_svm.cpu_cr3);
|
||||
domain_crash_synchronous(); /* need to take a clean path */
|
||||
gdprintk(XENLOG_ERR, "Invalid CR3 value = %lx (mfn=%lx)\n",
|
||||
v->arch.hvm_svm.cpu_cr3, mfn);
|
||||
domain_crash(v->domain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(__x86_64__)
|
||||
@@ -1556,7 +1563,7 @@ static void mov_from_cr(int cr, int gp, struct cpu_user_regs *regs)
|
||||
vmcb = v->arch.hvm_svm.vmcb;
|
||||
ASSERT(vmcb);
|
||||
|
||||
switch (cr)
|
||||
switch ( cr )
|
||||
{
|
||||
case 0:
|
||||
value = v->arch.hvm_svm.cpu_shadow_cr0;
|
||||
@@ -1582,7 +1589,8 @@ static void mov_from_cr(int cr, int gp, struct cpu_user_regs *regs)
|
||||
break;
|
||||
|
||||
default:
|
||||
__hvm_bug(regs);
|
||||
domain_crash(v->domain);
|
||||
return;
|
||||
}
|
||||
|
||||
set_reg(gp, value, regs, vmcb);
|
||||
@@ -1602,14 +1610,11 @@ static inline int svm_pgbit_test(struct vcpu *v)
|
||||
*/
|
||||
static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
|
||||
{
|
||||
unsigned long value;
|
||||
unsigned long old_cr;
|
||||
unsigned long value, old_cr, old_base_mfn, mfn;
|
||||
struct vcpu *v = current;
|
||||
struct vlapic *vlapic = vcpu_vlapic(v);
|
||||
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
|
||||
|
||||
ASSERT(vmcb);
|
||||
|
||||
value = get_reg(gpreg, regs, vmcb);
|
||||
|
||||
HVM_DBG_LOG(DBG_LEVEL_1, "mov_to_cr: CR%d, value = %lx,", cr, value);
|
||||
@@ -1623,8 +1628,6 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
|
||||
return svm_set_cr0(value);
|
||||
|
||||
case 3:
|
||||
{
|
||||
unsigned long old_base_mfn, mfn;
|
||||
if (svm_dbg_on)
|
||||
printk("CR3 write =%lx \n", value );
|
||||
/* If paging is not enabled yet, simply copy the value to CR3. */
|
||||
@@ -1644,7 +1647,7 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
|
||||
*/
|
||||
mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT);
|
||||
if (mfn != pagetable_get_pfn(v->arch.guest_table))
|
||||
__hvm_bug(regs);
|
||||
goto bad_cr3;
|
||||
shadow_update_cr3(v);
|
||||
}
|
||||
else
|
||||
@@ -1656,10 +1659,7 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
|
||||
HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 value = %lx", value);
|
||||
mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT);
|
||||
if ( !VALID_MFN(mfn) || !get_page(mfn_to_page(mfn), v->domain))
|
||||
{
|
||||
printk("Invalid CR3 value=%lx\n", value);
|
||||
domain_crash_synchronous(); /* need to take a clean path */
|
||||
}
|
||||
goto bad_cr3;
|
||||
|
||||
old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
|
||||
v->arch.guest_table = pagetable_from_pfn(mfn);
|
||||
@@ -1673,10 +1673,8 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
|
||||
HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx", value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 4: /* CR4 */
|
||||
{
|
||||
if (svm_dbg_on)
|
||||
printk( "write cr4=%lx, cr0=%lx\n",
|
||||
value, v->arch.hvm_svm.cpu_shadow_cr0 );
|
||||
@@ -1692,10 +1690,7 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
|
||||
mfn = get_mfn_from_gpfn(v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT);
|
||||
if ( !VALID_MFN(mfn) ||
|
||||
!get_page(mfn_to_page(mfn), v->domain) )
|
||||
{
|
||||
printk("Invalid CR3 value = %lx", v->arch.hvm_svm.cpu_cr3);
|
||||
domain_crash_synchronous(); /* need to take a clean path */
|
||||
}
|
||||
goto bad_cr3;
|
||||
|
||||
/*
|
||||
* Now arch.guest_table points to machine physical.
|
||||
@@ -1741,20 +1736,23 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
|
||||
shadow_update_paging_modes(v);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 8:
|
||||
{
|
||||
vlapic_set_reg(vlapic, APIC_TASKPRI, ((value & 0x0F) << 4));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
printk("invalid cr: %d\n", cr);
|
||||
__hvm_bug(regs);
|
||||
gdprintk(XENLOG_ERR, "invalid cr: %d\n", cr);
|
||||
domain_crash(v->domain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
bad_cr3:
|
||||
gdprintk(XENLOG_ERR, "Invalid CR3\n");
|
||||
domain_crash(v->domain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1857,8 +1855,7 @@ static int svm_cr_access(struct vcpu *v, unsigned int cr, unsigned int type,
|
||||
break;
|
||||
|
||||
default:
|
||||
__hvm_bug(regs);
|
||||
break;
|
||||
BUG();
|
||||
}
|
||||
|
||||
ASSERT(inst_len);
|
||||
@@ -2037,16 +2034,15 @@ void svm_handle_invlpg(const short invlpga, struct cpu_user_regs *regs)
|
||||
int inst_len;
|
||||
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
|
||||
|
||||
ASSERT(vmcb);
|
||||
/*
|
||||
* Unknown how many bytes the invlpg instruction will take. Use the
|
||||
* maximum instruction length here
|
||||
*/
|
||||
if (inst_copy_from_guest(opcode, svm_rip2pointer(vmcb), length) < length)
|
||||
{
|
||||
printk("svm_handle_invlpg (): Error reading memory %d bytes\n",
|
||||
length);
|
||||
__hvm_bug(regs);
|
||||
gdprintk(XENLOG_ERR, "Error reading memory %d bytes\n", length);
|
||||
domain_crash(v->domain);
|
||||
return;
|
||||
}
|
||||
|
||||
if (invlpga)
|
||||
@@ -2510,7 +2506,7 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)
|
||||
if (exit_reason == VMEXIT_INVALID)
|
||||
{
|
||||
svm_dump_vmcb(__func__, vmcb);
|
||||
domain_crash_synchronous();
|
||||
goto exit_and_crash;
|
||||
}
|
||||
|
||||
#ifdef SVM_EXTRA_DEBUG
|
||||
@@ -2734,8 +2730,7 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)
|
||||
break;
|
||||
|
||||
case VMEXIT_TASK_SWITCH:
|
||||
__hvm_bug(regs);
|
||||
break;
|
||||
goto exit_and_crash;
|
||||
|
||||
case VMEXIT_CPUID:
|
||||
svm_vmexit_do_cpuid(vmcb, regs->eax, regs);
|
||||
@@ -2811,15 +2806,16 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)
|
||||
break;
|
||||
|
||||
case VMEXIT_SHUTDOWN:
|
||||
printk("Guest shutdown exit\n");
|
||||
domain_crash_synchronous();
|
||||
break;
|
||||
gdprintk(XENLOG_ERR, "Guest shutdown exit\n");
|
||||
goto exit_and_crash;
|
||||
|
||||
default:
|
||||
printk("unexpected VMEXIT: exit reason = 0x%x, exitinfo1 = %"PRIx64", "
|
||||
"exitinfo2 = %"PRIx64"\n", exit_reason,
|
||||
(u64)vmcb->exitinfo1, (u64)vmcb->exitinfo2);
|
||||
__hvm_bug(regs); /* should not happen */
|
||||
exit_and_crash:
|
||||
gdprintk(XENLOG_ERR, "unexpected VMEXIT: exit reason = 0x%x, "
|
||||
"exitinfo1 = %"PRIx64", exitinfo2 = %"PRIx64"\n",
|
||||
exit_reason,
|
||||
(u64)vmcb->exitinfo1, (u64)vmcb->exitinfo2);
|
||||
domain_crash(v->domain);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2840,8 +2836,6 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs)
|
||||
printk("svm_vmexit_handler: Returning\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
asmlinkage void svm_load_cr2(void)
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <public/hvm/ioreq.h>
|
||||
#include <asm/hvm/io.h>
|
||||
#include <asm/hvm/vpic.h>
|
||||
#include <asm/hvm/vlapic.h>
|
||||
#include <asm/hvm/support.h>
|
||||
#include <asm/current.h>
|
||||
#include <asm/event.h>
|
||||
@@ -285,42 +286,6 @@ static int ioapic_inj_irq(struct vioapic *vioapic,
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifndef __ia64__
|
||||
static int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t dest)
|
||||
{
|
||||
int result = 0;
|
||||
uint32_t logical_dest;
|
||||
|
||||
HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "vlapic_match_logical_addr "
|
||||
"vcpu=%d vlapic_id=%x dest=%x\n",
|
||||
vlapic_vcpu(vlapic)->vcpu_id, VLAPIC_ID(vlapic), dest);
|
||||
|
||||
logical_dest = vlapic_get_reg(vlapic, APIC_LDR);
|
||||
|
||||
switch ( vlapic_get_reg(vlapic, APIC_DFR) )
|
||||
{
|
||||
case APIC_DFR_FLAT:
|
||||
result = ((dest & GET_APIC_LOGICAL_ID(logical_dest)) != 0);
|
||||
break;
|
||||
case APIC_DFR_CLUSTER:
|
||||
/* Should we support flat cluster mode ?*/
|
||||
if ( (GET_APIC_LOGICAL_ID(logical_dest) >> 4
|
||||
== ((dest >> 0x4) & 0xf)) &&
|
||||
(logical_dest & (dest & 0xf)) )
|
||||
result = 1;
|
||||
break;
|
||||
default:
|
||||
gdprintk(XENLOG_WARNING, "error DFR value for lapic of vcpu %d\n",
|
||||
vlapic_vcpu(vlapic)->vcpu_id);
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#else
|
||||
extern int vlapic_match_logical_addr(struct vlapic *vlapic, uint16_t dest);
|
||||
#endif
|
||||
|
||||
static uint32_t ioapic_get_delivery_bitmask(struct vioapic *vioapic,
|
||||
uint16_t dest,
|
||||
uint8_t dest_mode,
|
||||
|
||||
+58
-61
@@ -196,63 +196,56 @@ uint32_t vlapic_get_ppr(struct vlapic *vlapic)
|
||||
return ppr;
|
||||
}
|
||||
|
||||
/* This only for fixed delivery mode */
|
||||
int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda)
|
||||
{
|
||||
int result = 0;
|
||||
uint8_t logical_id;
|
||||
|
||||
logical_id = GET_APIC_LOGICAL_ID(vlapic_get_reg(vlapic, APIC_LDR));
|
||||
|
||||
switch ( vlapic_get_reg(vlapic, APIC_DFR) )
|
||||
{
|
||||
case APIC_DFR_FLAT:
|
||||
if ( logical_id & mda )
|
||||
result = 1;
|
||||
break;
|
||||
case APIC_DFR_CLUSTER:
|
||||
if ( ((logical_id >> 4) == (mda >> 0x4)) && (logical_id & mda & 0xf) )
|
||||
result = 1;
|
||||
break;
|
||||
default:
|
||||
gdprintk(XENLOG_WARNING, "Bad DFR value for lapic of vcpu %d\n",
|
||||
vlapic_vcpu(vlapic)->vcpu_id);
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int vlapic_match_dest(struct vcpu *v, struct vlapic *source,
|
||||
int short_hand, int dest, int dest_mode,
|
||||
int delivery_mode)
|
||||
int short_hand, int dest, int dest_mode)
|
||||
{
|
||||
int result = 0;
|
||||
struct vlapic *target = vcpu_vlapic(v);
|
||||
|
||||
HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "target %p, source %p, dest 0x%x, "
|
||||
"dest_mode 0x%x, short_hand 0x%x, delivery_mode 0x%x.",
|
||||
target, source, dest, dest_mode, short_hand, delivery_mode);
|
||||
|
||||
if ( unlikely(target == NULL) &&
|
||||
((delivery_mode != APIC_DM_INIT) &&
|
||||
(delivery_mode != APIC_DM_STARTUP) &&
|
||||
(delivery_mode != APIC_DM_NMI)) )
|
||||
{
|
||||
HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "uninitialized target vcpu %p, "
|
||||
"delivery_mode 0x%x, dest 0x%x.\n",
|
||||
v, delivery_mode, dest);
|
||||
return result;
|
||||
}
|
||||
"dest_mode 0x%x, short_hand 0x%x\n",
|
||||
target, source, dest, dest_mode, short_hand);
|
||||
|
||||
switch ( short_hand )
|
||||
{
|
||||
case APIC_DEST_NOSHORT: /* no shorthand */
|
||||
if ( !dest_mode ) /* Physical */
|
||||
case APIC_DEST_NOSHORT:
|
||||
if ( dest_mode == 0 )
|
||||
{
|
||||
result = ( ((target != NULL) ?
|
||||
GET_APIC_ID(vlapic_get_reg(target, APIC_ID)):
|
||||
v->vcpu_id)) == dest;
|
||||
/* Physical mode. */
|
||||
if ( (dest == 0xFF) || /* broadcast? */
|
||||
(GET_APIC_ID(vlapic_get_reg(target, APIC_ID)) == dest) )
|
||||
result = 1;
|
||||
}
|
||||
else /* Logical */
|
||||
else
|
||||
{
|
||||
uint32_t ldr;
|
||||
if ( target == NULL )
|
||||
break;
|
||||
ldr = vlapic_get_reg(target, APIC_LDR);
|
||||
|
||||
/* Flat mode */
|
||||
if ( vlapic_get_reg(target, APIC_DFR) == APIC_DFR_FLAT )
|
||||
{
|
||||
result = GET_APIC_LOGICAL_ID(ldr) & dest;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( (delivery_mode == APIC_DM_LOWEST) &&
|
||||
(dest == 0xff) )
|
||||
{
|
||||
/* What shall we do now? */
|
||||
gdprintk(XENLOG_ERR, "Broadcast IPI with lowest priority "
|
||||
"delivery mode\n");
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
result = ((GET_APIC_LOGICAL_ID(ldr) == (dest & 0xf)) ?
|
||||
(GET_APIC_LOGICAL_ID(ldr) >> 4) & (dest >> 4) : 0);
|
||||
}
|
||||
/* Logical mode. */
|
||||
result = vlapic_match_logical_addr(target, dest);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -271,16 +264,14 @@ static int vlapic_match_dest(struct vcpu *v, struct vlapic *source,
|
||||
break;
|
||||
|
||||
default:
|
||||
gdprintk(XENLOG_WARNING, "Bad dest shorthand value %x\n", short_hand);
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a pending IRQ into lapic.
|
||||
* Return 1 if successfully added and 0 if discarded.
|
||||
*/
|
||||
/* Add a pending IRQ into lapic. */
|
||||
static int vlapic_accept_irq(struct vcpu *v, int delivery_mode,
|
||||
int vector, int level, int trig_mode)
|
||||
{
|
||||
@@ -331,7 +322,7 @@ static int vlapic_accept_irq(struct vcpu *v, int delivery_mode,
|
||||
if ( test_and_clear_bit(_VCPUF_initialised, &v->vcpu_flags) )
|
||||
{
|
||||
gdprintk(XENLOG_ERR, "Reset hvm vcpu not supported yet\n");
|
||||
domain_crash_synchronous();
|
||||
goto exit_and_crash;
|
||||
}
|
||||
v->arch.hvm_vcpu.init_sipi_sipi_state =
|
||||
HVM_VCPU_INIT_SIPI_SIPI_STATE_WAIT_SIPI;
|
||||
@@ -349,7 +340,7 @@ static int vlapic_accept_irq(struct vcpu *v, int delivery_mode,
|
||||
if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) )
|
||||
{
|
||||
gdprintk(XENLOG_ERR, "SIPI for initialized vcpu %x\n", v->vcpu_id);
|
||||
domain_crash_synchronous();
|
||||
goto exit_and_crash;
|
||||
}
|
||||
|
||||
if ( hvm_bringup_ap(v->vcpu_id, vector) != 0 )
|
||||
@@ -359,11 +350,14 @@ static int vlapic_accept_irq(struct vcpu *v, int delivery_mode,
|
||||
default:
|
||||
gdprintk(XENLOG_ERR, "TODO: unsupported delivery mode %x\n",
|
||||
delivery_mode);
|
||||
domain_crash_synchronous();
|
||||
break;
|
||||
goto exit_and_crash;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
exit_and_crash:
|
||||
domain_crash(v->domain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function is used by both ioapic and lapic.The bitmap is for vcpu_id. */
|
||||
@@ -440,10 +434,9 @@ static void vlapic_ipi(struct vlapic *vlapic)
|
||||
|
||||
for_each_vcpu ( vlapic_domain(vlapic), v )
|
||||
{
|
||||
if ( vlapic_match_dest(v, vlapic, short_hand,
|
||||
dest, dest_mode, delivery_mode) )
|
||||
if ( vlapic_match_dest(v, vlapic, short_hand, dest, dest_mode) )
|
||||
{
|
||||
if ( delivery_mode == APIC_DM_LOWEST)
|
||||
if ( delivery_mode == APIC_DM_LOWEST )
|
||||
set_bit(v->vcpu_id, &lpr_map);
|
||||
else
|
||||
vlapic_accept_irq(v, delivery_mode,
|
||||
@@ -578,14 +571,17 @@ static unsigned long vlapic_read(struct vcpu *v, unsigned long address,
|
||||
default:
|
||||
gdprintk(XENLOG_ERR, "Local APIC read with len=0x%lx, "
|
||||
"should be 4 instead.\n", len);
|
||||
domain_crash_synchronous();
|
||||
break;
|
||||
goto exit_and_crash;
|
||||
}
|
||||
|
||||
HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "offset 0x%x with length 0x%lx, "
|
||||
"and the result is 0x%lx.", offset, len, result);
|
||||
|
||||
return result;
|
||||
|
||||
exit_and_crash:
|
||||
domain_crash(v->domain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vlapic_write(struct vcpu *v, unsigned long address,
|
||||
@@ -625,7 +621,7 @@ static void vlapic_write(struct vcpu *v, unsigned long address,
|
||||
{
|
||||
gdprintk(XENLOG_ERR, "Uneven alignment error for "
|
||||
"2-byte vlapic access\n");
|
||||
domain_crash_synchronous();
|
||||
goto exit_and_crash;
|
||||
}
|
||||
|
||||
val = (tmp & ~(0xffff << (8*alignment))) |
|
||||
@@ -635,8 +631,9 @@ static void vlapic_write(struct vcpu *v, unsigned long address,
|
||||
default:
|
||||
gdprintk(XENLOG_ERR, "Local APIC write with len = %lx, "
|
||||
"should be 4 instead\n", len);
|
||||
domain_crash_synchronous();
|
||||
break;
|
||||
exit_and_crash:
|
||||
domain_crash(v->domain);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -466,14 +466,14 @@ void vm_launch_fail(unsigned long eflags)
|
||||
{
|
||||
unsigned long error = __vmread(VM_INSTRUCTION_ERROR);
|
||||
printk("<vm_launch_fail> error code %lx\n", error);
|
||||
__hvm_bug(guest_cpu_user_regs());
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
|
||||
void vm_resume_fail(unsigned long eflags)
|
||||
{
|
||||
unsigned long error = __vmread(VM_INSTRUCTION_ERROR);
|
||||
printk("<vm_resume_fail> error code %lx\n", error);
|
||||
__hvm_bug(guest_cpu_user_regs());
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
|
||||
void arch_vmx_do_resume(struct vcpu *v)
|
||||
|
||||
+80
-74
@@ -151,15 +151,14 @@ static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
|
||||
|
||||
case MSR_FS_BASE:
|
||||
if ( !(vmx_long_mode_enabled(v)) )
|
||||
/* XXX should it be GP fault */
|
||||
domain_crash_synchronous();
|
||||
goto exit_and_crash;
|
||||
|
||||
msr_content = __vmread(GUEST_FS_BASE);
|
||||
break;
|
||||
|
||||
case MSR_GS_BASE:
|
||||
if ( !(vmx_long_mode_enabled(v)) )
|
||||
domain_crash_synchronous();
|
||||
goto exit_and_crash;
|
||||
|
||||
msr_content = __vmread(GUEST_GS_BASE);
|
||||
break;
|
||||
@@ -183,6 +182,11 @@ static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
|
||||
regs->edx = (u32)(msr_content >> 32);
|
||||
|
||||
return 1;
|
||||
|
||||
exit_and_crash:
|
||||
gdprintk(XENLOG_ERR, "Fatal error reading MSR %lx\n", (long)regs->ecx);
|
||||
domain_crash(v->domain);
|
||||
return 1; /* handled */
|
||||
}
|
||||
|
||||
static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
|
||||
@@ -233,7 +237,7 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
|
||||
case MSR_FS_BASE:
|
||||
case MSR_GS_BASE:
|
||||
if ( !(vmx_long_mode_enabled(v)) )
|
||||
domain_crash_synchronous();
|
||||
goto exit_and_crash;
|
||||
|
||||
if ( !IS_CANO_ADDRESS(msr_content) )
|
||||
{
|
||||
@@ -251,7 +255,7 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
|
||||
|
||||
case MSR_SHADOW_GS_BASE:
|
||||
if ( !(vmx_long_mode_enabled(v)) )
|
||||
domain_crash_synchronous();
|
||||
goto exit_and_crash;
|
||||
|
||||
v->arch.hvm_vmx.msr_content.shadow_gs = msr_content;
|
||||
wrmsrl(MSR_SHADOW_GS_BASE, msr_content);
|
||||
@@ -267,6 +271,11 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
exit_and_crash:
|
||||
gdprintk(XENLOG_ERR, "Fatal error writing MSR %lx\n", (long)regs->ecx);
|
||||
domain_crash(v->domain);
|
||||
return 1; /* handled */
|
||||
}
|
||||
|
||||
static void vmx_restore_msrs(struct vcpu *v)
|
||||
@@ -726,8 +735,7 @@ static int __get_instruction_length(void)
|
||||
{
|
||||
int len;
|
||||
len = __vmread(VM_EXIT_INSTRUCTION_LEN); /* Safe: callers audited */
|
||||
if ( (len < 1) || (len > 15) )
|
||||
__hvm_bug(guest_cpu_user_regs());
|
||||
BUG_ON((len < 1) || (len > 15));
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -823,7 +831,10 @@ static void vmx_do_cpuid(struct cpu_user_regs *regs)
|
||||
/* 8-byte aligned valid pseudophys address from vmxassist, please. */
|
||||
if ( (value & 7) || (mfn == INVALID_MFN) ||
|
||||
!v->arch.hvm_vmx.vmxassist_enabled )
|
||||
domain_crash_synchronous();
|
||||
{
|
||||
domain_crash(v->domain);
|
||||
return;
|
||||
}
|
||||
|
||||
p = map_domain_page(mfn);
|
||||
value = *((uint64_t *)(p + (value & (PAGE_SIZE - 1))));
|
||||
@@ -966,8 +977,9 @@ static int check_for_null_selector(unsigned long eip, int inst_len, int dir)
|
||||
memset(inst, 0, MAX_INST_LEN);
|
||||
if ( inst_copy_from_guest(inst, eip, inst_len) != inst_len )
|
||||
{
|
||||
printk("check_for_null_selector: get guest instruction failed\n");
|
||||
domain_crash_synchronous();
|
||||
gdprintk(XENLOG_ERR, "Get guest instruction failed\n");
|
||||
domain_crash(current->domain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for ( i = 0; i < inst_len; i++ )
|
||||
@@ -1169,7 +1181,7 @@ static void vmx_world_save(struct vcpu *v, struct vmx_assist_context *c)
|
||||
c->ldtr_arbytes.bytes = __vmread(GUEST_LDTR_AR_BYTES);
|
||||
}
|
||||
|
||||
static void vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c)
|
||||
static int vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c)
|
||||
{
|
||||
unsigned long mfn, old_base_mfn;
|
||||
|
||||
@@ -1192,10 +1204,7 @@ static void vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c)
|
||||
*/
|
||||
mfn = get_mfn_from_gpfn(c->cr3 >> PAGE_SHIFT);
|
||||
if ( mfn != pagetable_get_pfn(v->arch.guest_table) )
|
||||
{
|
||||
printk("Invalid CR3 value=%x", c->cr3);
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
goto bad_cr3;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1205,13 +1214,8 @@ static void vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c)
|
||||
*/
|
||||
HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 c->cr3 = %x", c->cr3);
|
||||
mfn = get_mfn_from_gpfn(c->cr3 >> PAGE_SHIFT);
|
||||
if ( !VALID_MFN(mfn) )
|
||||
{
|
||||
printk("Invalid CR3 value=%x", c->cr3);
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
if ( !get_page(mfn_to_page(mfn), v->domain) )
|
||||
domain_crash_synchronous();
|
||||
if ( !VALID_MFN(mfn) || !get_page(mfn_to_page(mfn), v->domain) )
|
||||
goto bad_cr3;
|
||||
old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
|
||||
v->arch.guest_table = pagetable_from_pfn(mfn);
|
||||
if (old_base_mfn)
|
||||
@@ -1280,6 +1284,11 @@ static void vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c)
|
||||
|
||||
shadow_update_paging_modes(v);
|
||||
__vmwrite(GUEST_CR3, v->arch.hvm_vcpu.hw_cr3);
|
||||
return 0;
|
||||
|
||||
bad_cr3:
|
||||
gdprintk(XENLOG_ERR, "Invalid CR3 value=%x", c->cr3);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
enum { VMX_ASSIST_INVOKE = 0, VMX_ASSIST_RESTORE };
|
||||
@@ -1320,7 +1329,8 @@ static int vmx_assist(struct vcpu *v, int mode)
|
||||
if (cp != 0) {
|
||||
if (hvm_copy_from_guest_phys(&c, cp, sizeof(c)))
|
||||
goto error;
|
||||
vmx_world_restore(v, &c);
|
||||
if ( vmx_world_restore(v, &c) != 0 )
|
||||
goto error;
|
||||
v->arch.hvm_vmx.vmxassist_enabled = 1;
|
||||
return 1;
|
||||
}
|
||||
@@ -1337,7 +1347,8 @@ static int vmx_assist(struct vcpu *v, int mode)
|
||||
if (cp != 0) {
|
||||
if (hvm_copy_from_guest_phys(&c, cp, sizeof(c)))
|
||||
goto error;
|
||||
vmx_world_restore(v, &c);
|
||||
if ( vmx_world_restore(v, &c) != 0 )
|
||||
goto error;
|
||||
v->arch.hvm_vmx.vmxassist_enabled = 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -1345,8 +1356,8 @@ static int vmx_assist(struct vcpu *v, int mode)
|
||||
}
|
||||
|
||||
error:
|
||||
printk("Failed to transfer to vmxassist\n");
|
||||
domain_crash_synchronous();
|
||||
gdprintk(XENLOG_ERR, "Failed to transfer to vmxassist\n");
|
||||
domain_crash(v->domain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1390,9 +1401,10 @@ static int vmx_set_cr0(unsigned long value)
|
||||
mfn = get_mfn_from_gpfn(v->arch.hvm_vmx.cpu_cr3 >> PAGE_SHIFT);
|
||||
if ( !VALID_MFN(mfn) || !get_page(mfn_to_page(mfn), v->domain) )
|
||||
{
|
||||
printk("Invalid CR3 value = %lx (mfn=%lx)\n",
|
||||
v->arch.hvm_vmx.cpu_cr3, mfn);
|
||||
domain_crash_synchronous(); /* need to take a clean path */
|
||||
gdprintk(XENLOG_ERR, "Invalid CR3 value = %lx (mfn=%lx)\n",
|
||||
v->arch.hvm_vmx.cpu_cr3, mfn);
|
||||
domain_crash(v->domain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(__x86_64__)
|
||||
@@ -1536,12 +1548,12 @@ static int vmx_set_cr0(unsigned long value)
|
||||
*/
|
||||
static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs)
|
||||
{
|
||||
unsigned long value;
|
||||
unsigned long old_cr;
|
||||
unsigned long value, old_cr, old_base_mfn, mfn;
|
||||
struct vcpu *v = current;
|
||||
struct vlapic *vlapic = vcpu_vlapic(v);
|
||||
|
||||
switch ( gp ) {
|
||||
switch ( gp )
|
||||
{
|
||||
CASE_GET_REG(EAX, eax);
|
||||
CASE_GET_REG(ECX, ecx);
|
||||
CASE_GET_REG(EDX, edx);
|
||||
@@ -1554,8 +1566,8 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs)
|
||||
value = __vmread(GUEST_RSP);
|
||||
break;
|
||||
default:
|
||||
printk("invalid gp: %d\n", gp);
|
||||
__hvm_bug(regs);
|
||||
gdprintk(XENLOG_ERR, "invalid gp: %d\n", gp);
|
||||
goto exit_and_crash;
|
||||
}
|
||||
|
||||
TRACE_VMEXIT(1, TYPE_MOV_TO_CR);
|
||||
@@ -1564,13 +1576,12 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs)
|
||||
|
||||
HVM_DBG_LOG(DBG_LEVEL_1, "CR%d, value = %lx", cr, value);
|
||||
|
||||
switch ( cr ) {
|
||||
switch ( cr )
|
||||
{
|
||||
case 0:
|
||||
return vmx_set_cr0(value);
|
||||
case 3:
|
||||
{
|
||||
unsigned long old_base_mfn, mfn;
|
||||
|
||||
case 3:
|
||||
/*
|
||||
* If paging is not enabled yet, simply copy the value to CR3.
|
||||
*/
|
||||
@@ -1590,7 +1601,7 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs)
|
||||
*/
|
||||
mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT);
|
||||
if (mfn != pagetable_get_pfn(v->arch.guest_table))
|
||||
__hvm_bug(regs);
|
||||
goto bad_cr3;
|
||||
shadow_update_cr3(v);
|
||||
} else {
|
||||
/*
|
||||
@@ -1600,10 +1611,7 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs)
|
||||
HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 value = %lx", value);
|
||||
mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT);
|
||||
if ( !VALID_MFN(mfn) || !get_page(mfn_to_page(mfn), v->domain) )
|
||||
{
|
||||
printk("Invalid CR3 value=%lx\n", value);
|
||||
domain_crash_synchronous(); /* need to take a clean path */
|
||||
}
|
||||
goto bad_cr3;
|
||||
old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
|
||||
v->arch.guest_table = pagetable_from_pfn(mfn);
|
||||
if (old_base_mfn)
|
||||
@@ -1618,9 +1626,8 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs)
|
||||
__vmwrite(GUEST_CR3, v->arch.hvm_vcpu.hw_cr3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 4: /* CR4 */
|
||||
{
|
||||
old_cr = v->arch.hvm_vmx.cpu_shadow_cr4;
|
||||
|
||||
if ( (value & X86_CR4_PAE) && !(old_cr & X86_CR4_PAE) )
|
||||
@@ -1633,10 +1640,7 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs)
|
||||
mfn = get_mfn_from_gpfn(v->arch.hvm_vmx.cpu_cr3 >> PAGE_SHIFT);
|
||||
if ( !VALID_MFN(mfn) ||
|
||||
!get_page(mfn_to_page(mfn), v->domain) )
|
||||
{
|
||||
printk("Invalid CR3 value = %lx", v->arch.hvm_vmx.cpu_cr3);
|
||||
domain_crash_synchronous(); /* need to take a clean path */
|
||||
}
|
||||
goto bad_cr3;
|
||||
|
||||
/*
|
||||
* Now arch.guest_table points to machine physical.
|
||||
@@ -1682,18 +1686,24 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs)
|
||||
if ( (old_cr ^ value) & (X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE) )
|
||||
shadow_update_paging_modes(v);
|
||||
break;
|
||||
}
|
||||
|
||||
case 8:
|
||||
{
|
||||
vlapic_set_reg(vlapic, APIC_TASKPRI, ((value & 0x0F) << 4));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
printk("invalid cr: %d\n", gp);
|
||||
__hvm_bug(regs);
|
||||
gdprintk(XENLOG_ERR, "invalid cr: %d\n", cr);
|
||||
domain_crash(v->domain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
bad_cr3:
|
||||
gdprintk(XENLOG_ERR, "Invalid CR3\n");
|
||||
exit_and_crash:
|
||||
domain_crash(v->domain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1715,7 +1725,9 @@ static void mov_from_cr(int cr, int gp, struct cpu_user_regs *regs)
|
||||
value = (value & 0xF0) >> 4;
|
||||
break;
|
||||
default:
|
||||
__hvm_bug(regs);
|
||||
gdprintk(XENLOG_ERR, "invalid cr: %d\n", cr);
|
||||
domain_crash(v->domain);
|
||||
break;
|
||||
}
|
||||
|
||||
switch ( gp ) {
|
||||
@@ -1733,7 +1745,8 @@ static void mov_from_cr(int cr, int gp, struct cpu_user_regs *regs)
|
||||
break;
|
||||
default:
|
||||
printk("invalid gp: %d\n", gp);
|
||||
__hvm_bug(regs);
|
||||
domain_crash(v->domain);
|
||||
break;
|
||||
}
|
||||
|
||||
TRACE_VMEXIT(1, TYPE_MOV_FROM_CR);
|
||||
@@ -1782,9 +1795,9 @@ static int vmx_cr_access(unsigned long exit_qualification,
|
||||
return vmx_set_cr0(value);
|
||||
break;
|
||||
default:
|
||||
__hvm_bug(regs);
|
||||
break;
|
||||
BUG();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1814,7 +1827,7 @@ static inline void vmx_do_msr_read(struct cpu_user_regs *regs)
|
||||
msr_content = vcpu_vlapic(v)->apic_base_msr;
|
||||
break;
|
||||
default:
|
||||
if (long_mode_do_msr_read(regs))
|
||||
if ( long_mode_do_msr_read(regs) )
|
||||
return;
|
||||
|
||||
if ( rdmsr_hypervisor_regs(regs->ecx, &eax, &edx) )
|
||||
@@ -2045,11 +2058,6 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
|
||||
|
||||
perfc_incra(vmexits, exit_reason);
|
||||
|
||||
if ( (exit_reason != EXIT_REASON_EXTERNAL_INTERRUPT) &&
|
||||
(exit_reason != EXIT_REASON_VMCALL) &&
|
||||
(exit_reason != EXIT_REASON_IO_INSTRUCTION) )
|
||||
HVM_DBG_LOG(DBG_LEVEL_0, "exit reason = %x", exit_reason);
|
||||
|
||||
if ( exit_reason != EXIT_REASON_EXTERNAL_INTERRUPT )
|
||||
local_irq_enable();
|
||||
|
||||
@@ -2077,7 +2085,7 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
|
||||
printk("************* VMCS Area **************\n");
|
||||
vmcs_dump_vcpu();
|
||||
printk("**************************************\n");
|
||||
domain_crash_synchronous();
|
||||
goto exit_and_crash;
|
||||
}
|
||||
|
||||
TRACE_VMEXIT(0, exit_reason);
|
||||
@@ -2121,8 +2129,6 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
|
||||
#else
|
||||
case TRAP_debug:
|
||||
{
|
||||
void store_cpu_user_regs(struct cpu_user_regs *regs);
|
||||
|
||||
if ( test_bit(_DOMF_debugging, &v->domain->domain_flags) )
|
||||
{
|
||||
store_cpu_user_regs(regs);
|
||||
@@ -2193,8 +2199,7 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
|
||||
vmx_do_extint(regs);
|
||||
break;
|
||||
case EXIT_REASON_TRIPLE_FAULT:
|
||||
domain_crash_synchronous();
|
||||
break;
|
||||
goto exit_and_crash;
|
||||
case EXIT_REASON_PENDING_INTERRUPT:
|
||||
/* Disable the interrupt window. */
|
||||
v->arch.hvm_vcpu.u.vmx.exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING;
|
||||
@@ -2202,8 +2207,7 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
|
||||
v->arch.hvm_vcpu.u.vmx.exec_control);
|
||||
break;
|
||||
case EXIT_REASON_TASK_SWITCH:
|
||||
domain_crash_synchronous();
|
||||
break;
|
||||
goto exit_and_crash;
|
||||
case EXIT_REASON_CPUID:
|
||||
inst_len = __get_instruction_length(); /* Safe: CPUID */
|
||||
__update_guest_eip(inst_len);
|
||||
@@ -2268,8 +2272,7 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
|
||||
case EXIT_REASON_MWAIT_INSTRUCTION:
|
||||
case EXIT_REASON_MONITOR_INSTRUCTION:
|
||||
case EXIT_REASON_PAUSE_INSTRUCTION:
|
||||
domain_crash_synchronous();
|
||||
break;
|
||||
goto exit_and_crash;
|
||||
case EXIT_REASON_VMCLEAR:
|
||||
case EXIT_REASON_VMLAUNCH:
|
||||
case EXIT_REASON_VMPTRLD:
|
||||
@@ -2289,7 +2292,10 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
|
||||
break;
|
||||
|
||||
default:
|
||||
domain_crash_synchronous(); /* should not happen */
|
||||
exit_and_crash:
|
||||
gdprintk(XENLOG_ERR, "Bad vmexit (reason %x)\n", exit_reason);
|
||||
domain_crash(v->domain);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+13
-6
@@ -1717,7 +1717,7 @@ int new_guest_cr3(unsigned long mfn)
|
||||
unsigned long old_base_mfn;
|
||||
|
||||
if ( is_hvm_domain(d) && !hvm_paging_enabled(v) )
|
||||
domain_crash_synchronous();
|
||||
return 0;
|
||||
|
||||
if ( shadow_mode_refcounts(d) )
|
||||
{
|
||||
@@ -2134,13 +2134,14 @@ int do_mmuext_op(
|
||||
|
||||
default:
|
||||
MEM_LOG("Invalid extended pt command 0x%x", op.cmd);
|
||||
rc = -ENOSYS;
|
||||
okay = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( unlikely(!okay) )
|
||||
{
|
||||
rc = -EINVAL;
|
||||
rc = rc ? rc : -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2151,9 +2152,11 @@ int do_mmuext_op(
|
||||
process_deferred_ops();
|
||||
|
||||
/* Add incremental work we have done to the @done output parameter. */
|
||||
done += i;
|
||||
if ( unlikely(!guest_handle_is_null(pdone)) )
|
||||
{
|
||||
done += i;
|
||||
copy_to_guest(pdone, &done, 1);
|
||||
}
|
||||
|
||||
UNLOCK_BIGLOCK(d);
|
||||
return rc;
|
||||
@@ -2351,12 +2354,14 @@ int do_mmu_update(
|
||||
|
||||
default:
|
||||
MEM_LOG("Invalid page update command %x", cmd);
|
||||
rc = -ENOSYS;
|
||||
okay = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( unlikely(!okay) )
|
||||
{
|
||||
rc = -EINVAL;
|
||||
rc = rc ? rc : -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2370,9 +2375,11 @@ int do_mmu_update(
|
||||
process_deferred_ops();
|
||||
|
||||
/* Add incremental work we have done to the @done output parameter. */
|
||||
done += i;
|
||||
if ( unlikely(!guest_handle_is_null(pdone)) )
|
||||
{
|
||||
done += i;
|
||||
copy_to_guest(pdone, &done, 1);
|
||||
}
|
||||
|
||||
UNLOCK_BIGLOCK(d);
|
||||
return rc;
|
||||
@@ -3106,7 +3113,7 @@ static int ptwr_emulated_update(
|
||||
* zap the PRESENT bit on the assumption the bottom half will be
|
||||
* written immediately after we return to the guest.
|
||||
*/
|
||||
MEM_LOG("ptwr_emulate: fixing up invalid PAE PTE %"PRIpte"\n",
|
||||
MEM_LOG("ptwr_emulate: fixing up invalid PAE PTE %"PRIpte,
|
||||
l1e_get_intpte(nl1e));
|
||||
l1e_remove_flags(nl1e, _PAGE_PRESENT);
|
||||
}
|
||||
|
||||
@@ -684,7 +684,7 @@ int do_xenoprof_op(int op, XEN_GUEST_HANDLE(void) arg)
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
ret = -ENOSYS;
|
||||
}
|
||||
|
||||
spin_unlock(&xenoprof_lock);
|
||||
|
||||
@@ -135,7 +135,7 @@ long do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
|
||||
}
|
||||
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
ret = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -1310,8 +1310,10 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
|
||||
|
||||
case 3: /* Write CR3 */
|
||||
LOCK_BIGLOCK(v->domain);
|
||||
(void)new_guest_cr3(gmfn_to_mfn(v->domain, xen_cr3_to_pfn(*reg)));
|
||||
rc = new_guest_cr3(gmfn_to_mfn(v->domain, xen_cr3_to_pfn(*reg)));
|
||||
UNLOCK_BIGLOCK(v->domain);
|
||||
if ( rc == 0 ) /* not okay */
|
||||
goto fail;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
|
||||
+23
-10
@@ -179,16 +179,16 @@ unsigned long do_iret(void)
|
||||
|
||||
/* Check worst-case stack frame for overlap with Xen protected area. */
|
||||
if ( unlikely(!access_ok(regs->esp, 40)) )
|
||||
domain_crash_synchronous();
|
||||
goto exit_and_crash;
|
||||
|
||||
/* Pop and restore EAX (clobbered by hypercall). */
|
||||
if ( unlikely(__copy_from_user(®s->eax, (void __user *)regs->esp, 4)) )
|
||||
domain_crash_synchronous();
|
||||
goto exit_and_crash;
|
||||
regs->esp += 4;
|
||||
|
||||
/* Pop and restore CS and EIP. */
|
||||
if ( unlikely(__copy_from_user(®s->eip, (void __user *)regs->esp, 8)) )
|
||||
domain_crash_synchronous();
|
||||
goto exit_and_crash;
|
||||
regs->esp += 8;
|
||||
|
||||
/*
|
||||
@@ -196,7 +196,7 @@ unsigned long do_iret(void)
|
||||
* to avoid firing the BUG_ON(IOPL) check in arch_getdomaininfo_ctxt.
|
||||
*/
|
||||
if ( unlikely(__copy_from_user(&eflags, (void __user *)regs->esp, 4)) )
|
||||
domain_crash_synchronous();
|
||||
goto exit_and_crash;
|
||||
regs->esp += 4;
|
||||
regs->eflags = (eflags & ~X86_EFLAGS_IOPL) | X86_EFLAGS_IF;
|
||||
|
||||
@@ -204,17 +204,17 @@ unsigned long do_iret(void)
|
||||
{
|
||||
/* Return to VM86 mode: pop and restore ESP,SS,ES,DS,FS and GS. */
|
||||
if ( __copy_from_user(®s->esp, (void __user *)regs->esp, 24) )
|
||||
domain_crash_synchronous();
|
||||
goto exit_and_crash;
|
||||
}
|
||||
else if ( unlikely(ring_0(regs)) )
|
||||
{
|
||||
domain_crash_synchronous();
|
||||
goto exit_and_crash;
|
||||
}
|
||||
else if ( !ring_1(regs) )
|
||||
{
|
||||
/* Return to ring 2/3: pop and restore ESP and SS. */
|
||||
if ( __copy_from_user(®s->esp, (void __user *)regs->esp, 8) )
|
||||
domain_crash_synchronous();
|
||||
goto exit_and_crash;
|
||||
}
|
||||
|
||||
/* No longer in NMI context. */
|
||||
@@ -228,6 +228,11 @@ unsigned long do_iret(void)
|
||||
* value.
|
||||
*/
|
||||
return regs->eax;
|
||||
|
||||
exit_and_crash:
|
||||
gdprintk(XENLOG_ERR, "Fatal error\n");
|
||||
domain_crash(current->domain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <asm/asm_defns.h>
|
||||
@@ -355,7 +360,7 @@ static long register_guest_callback(struct callback_register *reg)
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
ret = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -368,12 +373,20 @@ static long unregister_guest_callback(struct callback_unregister *unreg)
|
||||
|
||||
switch ( unreg->type )
|
||||
{
|
||||
case CALLBACKTYPE_event:
|
||||
case CALLBACKTYPE_failsafe:
|
||||
#ifdef CONFIG_X86_SUPERVISOR_MODE_KERNEL
|
||||
case CALLBACKTYPE_sysenter:
|
||||
#endif
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
|
||||
case CALLBACKTYPE_nmi:
|
||||
ret = unregister_guest_nmi_callback();
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
ret = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -412,7 +425,7 @@ long do_callback_op(int cmd, XEN_GUEST_HANDLE(void) arg)
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
ret = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ restore_all_guest:
|
||||
addq $8,%rsp
|
||||
popq %rcx # RIP
|
||||
popq %r11 # CS
|
||||
cmpw $__GUEST_CS32,%r11
|
||||
cmpw $FLAT_KERNEL_CS32,%r11
|
||||
popq %r11 # RFLAGS
|
||||
popq %rsp # RSP
|
||||
je 1f
|
||||
@@ -119,7 +119,7 @@ restore_all_xen:
|
||||
ALIGN
|
||||
ENTRY(syscall_enter)
|
||||
sti
|
||||
movl $__GUEST_SS,24(%rsp)
|
||||
movl $FLAT_KERNEL_SS,24(%rsp)
|
||||
pushq %rcx
|
||||
pushq $0
|
||||
movl $TRAP_syscall,4(%rsp)
|
||||
@@ -298,9 +298,9 @@ FLT13: movq %rax,(%rsi) # RCX
|
||||
movl $TRAP_syscall,UREGS_entry_vector+8(%rsp)
|
||||
andl $~(X86_EFLAGS_AC|X86_EFLAGS_VM|X86_EFLAGS_RF|\
|
||||
X86_EFLAGS_NT|X86_EFLAGS_TF),UREGS_eflags+8(%rsp)
|
||||
movq $__GUEST_SS,UREGS_ss+8(%rsp)
|
||||
movq $FLAT_KERNEL_SS,UREGS_ss+8(%rsp)
|
||||
movq %rsi,UREGS_rsp+8(%rsp)
|
||||
movq $__GUEST_CS,UREGS_cs+8(%rsp)
|
||||
movq $FLAT_KERNEL_CS,UREGS_cs+8(%rsp)
|
||||
movq TRAPBOUNCE_eip(%rdx),%rax
|
||||
testq %rax,%rax
|
||||
jz domain_crash_synchronous
|
||||
|
||||
+20
-16
@@ -76,17 +76,17 @@ l2_pgentry_t *virt_to_xen_l2e(unsigned long v)
|
||||
|
||||
void __init paging_init(void)
|
||||
{
|
||||
unsigned long i, mpt_size;
|
||||
unsigned long i, mpt_size, va;
|
||||
l3_pgentry_t *l3_ro_mpt;
|
||||
l2_pgentry_t *l2_ro_mpt = NULL;
|
||||
struct page_info *pg;
|
||||
struct page_info *l1_pg, *l2_pg;
|
||||
|
||||
/* Create user-accessible L2 directory to map the MPT for guests. */
|
||||
l3_ro_mpt = alloc_xenheap_page();
|
||||
clear_page(l3_ro_mpt);
|
||||
if ( (l2_pg = alloc_domheap_page(NULL)) == NULL )
|
||||
goto nomem;
|
||||
l3_ro_mpt = clear_page(page_to_virt(l2_pg));
|
||||
idle_pg_table[l4_table_offset(RO_MPT_VIRT_START)] =
|
||||
l4e_from_page(
|
||||
virt_to_page(l3_ro_mpt), __PAGE_HYPERVISOR | _PAGE_USER);
|
||||
l4e_from_page(l2_pg, __PAGE_HYPERVISOR | _PAGE_USER);
|
||||
|
||||
/*
|
||||
* Allocate and map the machine-to-phys table.
|
||||
@@ -96,33 +96,37 @@ void __init paging_init(void)
|
||||
mpt_size &= ~((1UL << L2_PAGETABLE_SHIFT) - 1UL);
|
||||
for ( i = 0; i < (mpt_size >> L2_PAGETABLE_SHIFT); i++ )
|
||||
{
|
||||
if ( (pg = alloc_domheap_pages(NULL, PAGETABLE_ORDER, 0)) == NULL )
|
||||
panic("Not enough memory for m2p table\n");
|
||||
if ( (l1_pg = alloc_domheap_pages(NULL, PAGETABLE_ORDER, 0)) == NULL )
|
||||
goto nomem;
|
||||
map_pages_to_xen(
|
||||
RDWR_MPT_VIRT_START + (i << L2_PAGETABLE_SHIFT), page_to_mfn(pg),
|
||||
RDWR_MPT_VIRT_START + (i << L2_PAGETABLE_SHIFT),
|
||||
page_to_mfn(l1_pg),
|
||||
1UL << PAGETABLE_ORDER,
|
||||
PAGE_HYPERVISOR);
|
||||
memset((void *)(RDWR_MPT_VIRT_START + (i << L2_PAGETABLE_SHIFT)), 0x55,
|
||||
1UL << L2_PAGETABLE_SHIFT);
|
||||
if ( !((unsigned long)l2_ro_mpt & ~PAGE_MASK) )
|
||||
{
|
||||
unsigned long va = RO_MPT_VIRT_START + (i << L2_PAGETABLE_SHIFT);
|
||||
|
||||
l2_ro_mpt = alloc_xenheap_page();
|
||||
clear_page(l2_ro_mpt);
|
||||
if ( (l2_pg = alloc_domheap_page(NULL)) == NULL )
|
||||
goto nomem;
|
||||
va = RO_MPT_VIRT_START + (i << L2_PAGETABLE_SHIFT);
|
||||
l2_ro_mpt = clear_page(page_to_virt(l2_pg));
|
||||
l3_ro_mpt[l3_table_offset(va)] =
|
||||
l3e_from_page(
|
||||
virt_to_page(l2_ro_mpt), __PAGE_HYPERVISOR | _PAGE_USER);
|
||||
l3e_from_page(l2_pg, __PAGE_HYPERVISOR | _PAGE_USER);
|
||||
l2_ro_mpt += l2_table_offset(va);
|
||||
}
|
||||
/* NB. Cannot be GLOBAL as shadow_mode_translate reuses this area. */
|
||||
*l2_ro_mpt++ = l2e_from_page(
|
||||
pg, /*_PAGE_GLOBAL|*/_PAGE_PSE|_PAGE_USER|_PAGE_PRESENT);
|
||||
l1_pg, /*_PAGE_GLOBAL|*/_PAGE_PSE|_PAGE_USER|_PAGE_PRESENT);
|
||||
}
|
||||
|
||||
/* Set up linear page table mapping. */
|
||||
idle_pg_table[l4_table_offset(LINEAR_PT_VIRT_START)] =
|
||||
l4e_from_paddr(__pa(idle_pg_table), __PAGE_HYPERVISOR);
|
||||
return;
|
||||
|
||||
nomem:
|
||||
panic("Not enough memory for m2p table\n");
|
||||
}
|
||||
|
||||
void __init setup_idle_pagetable(void)
|
||||
|
||||
@@ -200,7 +200,7 @@ unsigned long do_iret(void)
|
||||
{
|
||||
gdprintk(XENLOG_ERR, "Fault while reading IRET context from "
|
||||
"guest stack\n");
|
||||
domain_crash_synchronous();
|
||||
goto exit_and_crash;
|
||||
}
|
||||
|
||||
/* Returning to user mode? */
|
||||
@@ -210,7 +210,7 @@ unsigned long do_iret(void)
|
||||
{
|
||||
gdprintk(XENLOG_ERR, "Guest switching to user mode with no "
|
||||
"user page tables\n");
|
||||
domain_crash_synchronous();
|
||||
goto exit_and_crash;
|
||||
}
|
||||
toggle_guest_mode(v);
|
||||
}
|
||||
@@ -236,6 +236,11 @@ unsigned long do_iret(void)
|
||||
|
||||
/* Saved %rax gets written back to regs->rax in entry.S. */
|
||||
return iret_saved.rax;
|
||||
|
||||
exit_and_crash:
|
||||
gdprintk(XENLOG_ERR, "Fatal error\n");
|
||||
domain_crash(v->domain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
asmlinkage void syscall_enter(void);
|
||||
@@ -285,9 +290,9 @@ void __init percpu_traps_init(void)
|
||||
stack[14] = 0x41;
|
||||
stack[15] = 0x53;
|
||||
|
||||
/* pushq $__GUEST_CS64 */
|
||||
/* pushq $FLAT_KERNEL_CS64 */
|
||||
stack[16] = 0x68;
|
||||
*(u32 *)&stack[17] = __GUEST_CS64;
|
||||
*(u32 *)&stack[17] = FLAT_KERNEL_CS64;
|
||||
|
||||
/* jmp syscall_enter */
|
||||
stack[21] = 0xe9;
|
||||
@@ -317,9 +322,9 @@ void __init percpu_traps_init(void)
|
||||
stack[14] = 0x41;
|
||||
stack[15] = 0x53;
|
||||
|
||||
/* pushq $__GUEST_CS32 */
|
||||
/* pushq $FLAT_KERNEL_CS32 */
|
||||
stack[16] = 0x68;
|
||||
*(u32 *)&stack[17] = __GUEST_CS32;
|
||||
*(u32 *)&stack[17] = FLAT_KERNEL_CS32;
|
||||
|
||||
/* jmp syscall_enter */
|
||||
stack[21] = 0xe9;
|
||||
@@ -369,7 +374,7 @@ static long register_guest_callback(struct callback_register *reg)
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
ret = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -382,12 +387,18 @@ static long unregister_guest_callback(struct callback_unregister *unreg)
|
||||
|
||||
switch ( unreg->type )
|
||||
{
|
||||
case CALLBACKTYPE_event:
|
||||
case CALLBACKTYPE_failsafe:
|
||||
case CALLBACKTYPE_syscall:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
|
||||
case CALLBACKTYPE_nmi:
|
||||
ret = unregister_guest_nmi_callback();
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
ret = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -426,7 +437,7 @@ long do_callback_op(int cmd, XEN_GUEST_HANDLE(void) arg)
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
ret = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <xen/delay.h>
|
||||
#include <xen/shutdown.h>
|
||||
#include <xen/percpu.h>
|
||||
#include <xen/multicall.h>
|
||||
#include <asm/debugger.h>
|
||||
#include <public/sched.h>
|
||||
#include <public/vcpu.h>
|
||||
@@ -256,6 +257,10 @@ void __domain_crash(struct domain *d)
|
||||
void __domain_crash_synchronous(void)
|
||||
{
|
||||
__domain_crash(current->domain);
|
||||
|
||||
/* Flush multicall state before dying. */
|
||||
this_cpu(mc_state).flags = 0;
|
||||
|
||||
for ( ; ; )
|
||||
do_softirq();
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ static __inline__ int constant_test_bit(int nr, const volatile void * addr)
|
||||
return ((1U << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
|
||||
}
|
||||
|
||||
static __inline__ int variable_test_bit(int nr, volatile void * addr)
|
||||
static __inline__ int variable_test_bit(int nr, const volatile void * addr)
|
||||
{
|
||||
int oldbit;
|
||||
|
||||
|
||||
@@ -194,12 +194,6 @@ extern unsigned long _end; /* standard ELF symbol */
|
||||
#define __HYPERVISOR_DS32 0xe018
|
||||
#define __HYPERVISOR_DS __HYPERVISOR_DS64
|
||||
|
||||
#define __GUEST_CS64 0xe033
|
||||
#define __GUEST_CS32 0xe023
|
||||
#define __GUEST_CS __GUEST_CS64
|
||||
#define __GUEST_DS 0x0000
|
||||
#define __GUEST_SS 0xe02b
|
||||
|
||||
/* For generic assembly code: use macros to define operation/operand sizes. */
|
||||
#define __OS "q" /* Operation Suffix */
|
||||
#define __OP "r" /* Operand Prefix */
|
||||
|
||||
@@ -155,17 +155,12 @@ __asm__ __volatile__ ("movw %w3,0(%2)\n\t" \
|
||||
#endif
|
||||
|
||||
extern struct desc_struct gdt_table[];
|
||||
extern struct desc_struct *gdt;
|
||||
extern idt_entry_t *idt;
|
||||
|
||||
struct Xgt_desc_struct {
|
||||
unsigned short size;
|
||||
unsigned long address __attribute__((packed));
|
||||
};
|
||||
|
||||
#define idt_descr (*(struct Xgt_desc_struct *)((char *)&idt - 2))
|
||||
#define gdt_descr (*(struct Xgt_desc_struct *)((char *)&gdt - 2))
|
||||
|
||||
extern void set_intr_gate(unsigned int irq, void * addr);
|
||||
extern void set_system_gate(unsigned int n, void *addr);
|
||||
extern void set_task_gate(unsigned int n, unsigned int sel);
|
||||
|
||||
@@ -118,13 +118,6 @@ extern unsigned int opt_hvm_debug_level;
|
||||
#define HVM_DBG_LOG(level, _f, _a...)
|
||||
#endif
|
||||
|
||||
#define __hvm_bug(regs) \
|
||||
do { \
|
||||
printk("__hvm_bug at %s:%d\n", __FILE__, __LINE__); \
|
||||
show_execution_state(regs); \
|
||||
domain_crash_synchronous(); \
|
||||
} while (0)
|
||||
|
||||
#define TRACE_VMEXIT(index, value) \
|
||||
current->arch.hvm_vcpu.hvm_trace_values[index] = (value)
|
||||
|
||||
|
||||
@@ -90,4 +90,6 @@ struct vlapic *apic_round_robin(
|
||||
|
||||
s_time_t get_apictime_scheduled(struct vcpu *v);
|
||||
|
||||
int vlapic_match_logical_addr(struct vlapic *vlapic, uint8_t mda);
|
||||
|
||||
#endif /* __ASM_X86_HVM_VLAPIC_H__ */
|
||||
@@ -138,6 +138,15 @@
|
||||
*/
|
||||
#define XEN_ELFNOTE_BSD_SYMTAB 11
|
||||
|
||||
/*
|
||||
* The lowest address the hypervisor hole can begin at (numeric).
|
||||
*
|
||||
* This must not be set higher than HYPERVISOR_VIRT_START. Its presence
|
||||
* also indicates to the hypervisor that the kernel can deal with the
|
||||
* hole starting at a higher address.
|
||||
*/
|
||||
#define XEN_ELFNOTE_HV_START_LOW 12
|
||||
|
||||
#endif /* __XEN_PUBLIC_ELFNOTE_H__ */
|
||||
|
||||
/*
|
||||
|
||||
@@ -80,7 +80,7 @@ struct buffered_iopage {
|
||||
}; /* sizeof this structure must be in one page */
|
||||
typedef struct buffered_iopage buffered_iopage_t;
|
||||
|
||||
#define ACPI_PM1A_EVT_BLK_ADDRESS 0x000000000000c010
|
||||
#define ACPI_PM1A_EVT_BLK_ADDRESS 0x0000000000001f40
|
||||
#define ACPI_PM1A_CNT_BLK_ADDRESS (ACPI_PM1A_EVT_BLK_ADDRESS + 0x04)
|
||||
#define ACPI_PM_TMR_BLK_ADDRESS (ACPI_PM1A_EVT_BLK_ADDRESS + 0x08)
|
||||
|
||||
|
||||