Compare commits
	
		
			46 Commits
		
	
	
		
			v1.0-rc4
			...
			v0.15.1-qe
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					36f5bc4fdb | ||
| 
						 | 
					82b2b32a32 | ||
| 
						 | 
					4a81ab81e4 | ||
| 
						 | 
					68e3508eaf | ||
| 
						 | 
					fb524042db | ||
| 
						 | 
					336398391a | ||
| 
						 | 
					672aefeb5e | ||
| 
						 | 
					6a10ccca80 | ||
| 
						 | 
					7095e71576 | ||
| 
						 | 
					91b31d6158 | ||
| 
						 | 
					b89f4a7d2a | ||
| 
						 | 
					fbdd7c8bd5 | ||
| 
						 | 
					e19a4e89ae | ||
| 
						 | 
					ff5acedd8f | ||
| 
						 | 
					2af86a2ff7 | ||
| 
						 | 
					e62ad8314a | ||
| 
						 | 
					76e4e1d237 | ||
| 
						 | 
					4fbe5233fd | ||
| 
						 | 
					4bea41dbaa | ||
| 
						 | 
					e2f775205a | ||
| 
						 | 
					51dd7a94c7 | ||
| 
						 | 
					9096de69ff | ||
| 
						 | 
					09afeef1ab | ||
| 
						 | 
					01825a8ddf | ||
| 
						 | 
					ae2dd33693 | ||
| 
						 | 
					a80f53aee3 | ||
| 
						 | 
					88ca9f047b | ||
| 
						 | 
					898517b0bc | ||
| 
						 | 
					9dc9f2b820 | ||
| 
						 | 
					ef942b795a | ||
| 
						 | 
					868aa386b8 | ||
| 
						 | 
					7e10be8c74 | ||
| 
						 | 
					9843621e3b | ||
| 
						 | 
					ab640dbfc0 | ||
| 
						 | 
					eaa8b2778c | ||
| 
						 | 
					7ec7f28019 | ||
| 
						 | 
					31b1308046 | ||
| 
						 | 
					4ec648dd6e | ||
| 
						 | 
					e961d129e1 | ||
| 
						 | 
					8959459386 | ||
| 
						 | 
					e2b40e003a | ||
| 
						 | 
					1a39b0fcff | ||
| 
						 | 
					4a97e18b87 | ||
| 
						 | 
					f1ee0a0ebd | ||
| 
						 | 
					3583bc031e | ||
| 
						 | 
					2798b5e174 | 
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -65,6 +65,8 @@ pc-bios/vgabios-pq/status
 | 
			
		||||
pc-bios/optionrom/linuxboot.bin
 | 
			
		||||
pc-bios/optionrom/multiboot.bin
 | 
			
		||||
pc-bios/optionrom/multiboot.raw
 | 
			
		||||
pc-bios/optionrom/extboot.bin
 | 
			
		||||
pc-bios/optionrom/vapic.bin
 | 
			
		||||
.stgit-*
 | 
			
		||||
cscope.*
 | 
			
		||||
tags
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
[submodule "roms/vgabios"]
 | 
			
		||||
	path = roms/vgabios
 | 
			
		||||
	url = git://git.qemu.org/vgabios.git/
 | 
			
		||||
	url = git://git.kernel.org/pub/scm/virt/kvm/vgabios.git/
 | 
			
		||||
[submodule "roms/seabios"]
 | 
			
		||||
	path = roms/seabios
 | 
			
		||||
	url = git://git.qemu.org/seabios.git/
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								Makefile
									
									
									
									
									
								
							@@ -192,8 +192,10 @@ test-qmp-commands.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types
 | 
			
		||||
test-qmp-commands: test-qmp-commands.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o $(qapi-obj-y) error.o osdep.o qemu-malloc.o $(oslib-obj-y) qjson.o json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o qemu-tool.o $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o $(qapi-dir)/test-qmp-marshal.o module.o
 | 
			
		||||
 | 
			
		||||
QGALIB=qga/guest-agent-command-state.o qga/guest-agent-commands.o
 | 
			
		||||
QGALIB_GEN=$(addprefix $(qapi-dir)/, qga-qapi-types.c qga-qapi-types.h qga-qapi-visit.c qga-qmp-marshal.c)
 | 
			
		||||
 | 
			
		||||
qemu-ga.o: $(addprefix $(qapi-dir)/, qga-qapi-types.c qga-qapi-types.h qga-qapi-visit.c qga-qmp-marshal.c) $(qapi-obj-y)
 | 
			
		||||
$(QGALIB_GEN): $(GENERATED_HEADERS)
 | 
			
		||||
$(QGALIB) qemu-ga.o: $(QGALIB_GEN) $(qapi-obj-y)
 | 
			
		||||
qemu-ga$(EXESUF): qemu-ga.o $(QGALIB) qemu-tool.o qemu-error.o error.o $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) $(qapi-obj-y) qemu-timer-common.o qemu-sockets.o module.o qapi/qmp-dispatch.o qapi/qmp-registry.o $(qapi-dir)/qga-qapi-visit.o $(qapi-dir)/qga-qapi-types.o $(qapi-dir)/qga-qmp-marshal.o
 | 
			
		||||
 | 
			
		||||
QEMULIBS=libhw32 libhw64 libuser libdis libdis-user
 | 
			
		||||
@@ -244,6 +246,8 @@ mpc8544ds.dtb \
 | 
			
		||||
multiboot.bin linuxboot.bin \
 | 
			
		||||
s390-zipl.rom \
 | 
			
		||||
spapr-rtas.bin slof.bin
 | 
			
		||||
BLOBS += extboot.bin
 | 
			
		||||
BLOBS += vapic.bin
 | 
			
		||||
else
 | 
			
		||||
BLOBS=
 | 
			
		||||
endif
 | 
			
		||||
@@ -270,7 +274,12 @@ endif
 | 
			
		||||
ifneq ($(BLOBS),)
 | 
			
		||||
	$(INSTALL_DIR) "$(DESTDIR)$(datadir)"
 | 
			
		||||
	set -e; for x in $(BLOBS); do \
 | 
			
		||||
	    if [ -f $(SRC_PATH)/pc-bios/$$x ];then \
 | 
			
		||||
		$(INSTALL_DATA) $(SRC_PATH)/pc-bios/$$x "$(DESTDIR)$(datadir)"; \
 | 
			
		||||
	    fi \
 | 
			
		||||
	    ; if [ -f pc-bios/optionrom/$$x ];then \
 | 
			
		||||
		$(INSTALL_DATA) pc-bios/optionrom/$$x "$(DESTDIR)$(datadir)"; \
 | 
			
		||||
	    fi \
 | 
			
		||||
	done
 | 
			
		||||
endif
 | 
			
		||||
	$(INSTALL_DIR) "$(DESTDIR)$(datadir)/keymaps"
 | 
			
		||||
@@ -391,6 +400,7 @@ tarbin:
 | 
			
		||||
	$(datadir)/pxe-pcnet.rom \
 | 
			
		||||
	$(datadir)/pxe-rtl8139.rom \
 | 
			
		||||
	$(datadir)/pxe-virtio.rom \
 | 
			
		||||
	$(datadir)/extboot.bin \
 | 
			
		||||
	$(docdir)/qemu-doc.html \
 | 
			
		||||
	$(docdir)/qemu-tech.html \
 | 
			
		||||
	$(mandir)/man1/qemu.1 \
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@ block-obj-y = cutils.o cache-utils.o qemu-malloc.o qemu-option.o module.o async.
 | 
			
		||||
block-obj-y += nbd.o block.o aio.o aes.o qemu-config.o qemu-progress.o qemu-sockets.o
 | 
			
		||||
block-obj-$(CONFIG_POSIX) += posix-aio-compat.o
 | 
			
		||||
block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
 | 
			
		||||
block-obj-$(CONFIG_POSIX) += compatfd.o
 | 
			
		||||
 | 
			
		||||
block-nested-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o
 | 
			
		||||
block-nested-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o
 | 
			
		||||
@@ -145,7 +146,7 @@ common-obj-y += $(addprefix ui/, $(ui-obj-y))
 | 
			
		||||
common-obj-$(CONFIG_VNC) += $(addprefix ui/, $(vnc-obj-y))
 | 
			
		||||
 | 
			
		||||
common-obj-y += iov.o acl.o
 | 
			
		||||
common-obj-$(CONFIG_POSIX) += compatfd.o
 | 
			
		||||
#common-obj-$(CONFIG_POSIX) += compatfd.o
 | 
			
		||||
common-obj-y += notify.o event_notifier.o
 | 
			
		||||
common-obj-y += qemu-timer.o qemu-timer-common.o
 | 
			
		||||
 | 
			
		||||
@@ -170,11 +171,11 @@ user-obj-y += cutils.o cache-utils.o
 | 
			
		||||
# libhw
 | 
			
		||||
 | 
			
		||||
hw-obj-y =
 | 
			
		||||
hw-obj-y += vl.o loader.o
 | 
			
		||||
hw-obj-y += loader.o
 | 
			
		||||
hw-obj-$(CONFIG_VIRTIO) += virtio-console.o
 | 
			
		||||
hw-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
 | 
			
		||||
hw-obj-y += fw_cfg.o
 | 
			
		||||
hw-obj-$(CONFIG_PCI) += pci.o pci_bridge.o
 | 
			
		||||
hw-obj-$(CONFIG_PCI) += pci_bridge.o
 | 
			
		||||
hw-obj-$(CONFIG_PCI) += msix.o msi.o
 | 
			
		||||
hw-obj-$(CONFIG_PCI) += pci_host.o pcie_host.o
 | 
			
		||||
hw-obj-$(CONFIG_PCI) += ioh3420.o xio3130_upstream.o xio3130_downstream.o
 | 
			
		||||
@@ -191,14 +192,16 @@ hw-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o
 | 
			
		||||
 | 
			
		||||
hw-obj-$(CONFIG_SERIAL) += serial.o
 | 
			
		||||
hw-obj-$(CONFIG_PARALLEL) += parallel.o
 | 
			
		||||
hw-obj-$(CONFIG_I8254) += i8254.o
 | 
			
		||||
hw-obj-$(CONFIG_PCSPK) += pcspk.o
 | 
			
		||||
# Moved back to Makefile.target due to #include qemu-kvm.h:
 | 
			
		||||
#hw-obj-$(CONFIG_I8254) += i8254.o
 | 
			
		||||
#hw-obj-$(CONFIG_PCSPK) += pcspk.o
 | 
			
		||||
hw-obj-$(CONFIG_PCKBD) += pckbd.o
 | 
			
		||||
hw-obj-$(CONFIG_USB_UHCI) += usb-uhci.o
 | 
			
		||||
hw-obj-$(CONFIG_USB_OHCI) += usb-ohci.o
 | 
			
		||||
hw-obj-$(CONFIG_USB_EHCI) += usb-ehci.o
 | 
			
		||||
hw-obj-$(CONFIG_FDC) += fdc.o
 | 
			
		||||
hw-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o
 | 
			
		||||
# needs fixes for cpu hotplug, so moved to Makefile.target:
 | 
			
		||||
# hw-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o
 | 
			
		||||
hw-obj-$(CONFIG_APM) += pm_smbus.o apm.o
 | 
			
		||||
hw-obj-$(CONFIG_DMA) += dma.o
 | 
			
		||||
hw-obj-$(CONFIG_HPET) += hpet.o
 | 
			
		||||
 
 | 
			
		||||
@@ -71,14 +71,19 @@ all: $(PROGS) stap
 | 
			
		||||
 | 
			
		||||
#########################################################
 | 
			
		||||
# cpu emulator library
 | 
			
		||||
libobj-y = exec.o translate-all.o cpu-exec.o translate.o
 | 
			
		||||
libobj-y += tcg/tcg.o
 | 
			
		||||
libobj-y = exec.o cpu-exec.o
 | 
			
		||||
libobj-$(CONFIG_NO_CPU_EMULATION) += fake-exec.o
 | 
			
		||||
libobj-$(CONFIG_CPU_EMULATION) += translate-all.o translate.o
 | 
			
		||||
libobj-$(CONFIG_CPU_EMULATION) += tcg/tcg.o
 | 
			
		||||
libobj-y += fpu/softfloat.o
 | 
			
		||||
libobj-y += op_helper.o helper.o
 | 
			
		||||
ifeq ($(TARGET_BASE_ARCH), i386)
 | 
			
		||||
libobj-y += cpuid.o
 | 
			
		||||
endif
 | 
			
		||||
libobj-$(CONFIG_NEED_MMU) += mmu.o
 | 
			
		||||
 | 
			
		||||
libobj-$(CONFIG_KVM) += kvm-tpr-opt.o
 | 
			
		||||
 | 
			
		||||
libobj-$(TARGET_ARM) += neon_helper.o iwmmxt_helper.o
 | 
			
		||||
 | 
			
		||||
libobj-y += disas.o
 | 
			
		||||
@@ -187,10 +192,11 @@ endif #CONFIG_BSD_USER
 | 
			
		||||
# System emulator target
 | 
			
		||||
ifdef CONFIG_SOFTMMU
 | 
			
		||||
 | 
			
		||||
obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o
 | 
			
		||||
obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o vl.o balloon.o
 | 
			
		||||
# virtio has to be here due to weird dependency between PCI and virtio-net.
 | 
			
		||||
# need to fix this properly
 | 
			
		||||
obj-$(CONFIG_NO_PCI) += pci-stub.o
 | 
			
		||||
obj-$(CONFIG_PCI) += pci.o
 | 
			
		||||
obj-$(CONFIG_VIRTIO) += virtio.o virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
 | 
			
		||||
obj-y += vhost_net.o
 | 
			
		||||
obj-$(CONFIG_VHOST_NET) += vhost.o
 | 
			
		||||
@@ -227,10 +233,24 @@ obj-i386-y += mc146818rtc.o i8259.o pc.o
 | 
			
		||||
obj-i386-y += cirrus_vga.o sga.o apic.o ioapic.o piix_pci.o
 | 
			
		||||
obj-i386-y += vmport.o
 | 
			
		||||
obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
 | 
			
		||||
obj-i386-y += extboot.o
 | 
			
		||||
obj-i386-y += debugcon.o multiboot.o
 | 
			
		||||
obj-i386-y += pc_piix.o
 | 
			
		||||
obj-i386-$(CONFIG_KVM) += kvmclock.o
 | 
			
		||||
obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
 | 
			
		||||
obj-i386-y += testdev.o
 | 
			
		||||
obj-i386-y += acpi.o acpi_piix4.o
 | 
			
		||||
 | 
			
		||||
obj-i386-y += pcspk.o i8254.o
 | 
			
		||||
obj-i386-$(CONFIG_KVM_PIT) += i8254-kvm.o
 | 
			
		||||
obj-i386-$(CONFIG_KVM_DEVICE_ASSIGNMENT) += device-assignment.o
 | 
			
		||||
 | 
			
		||||
# Hardware support
 | 
			
		||||
obj-ia64-y += ide.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
 | 
			
		||||
obj-ia64-y += fdc.o mc146818rtc.o serial.o i8259.o ipf.o
 | 
			
		||||
obj-ia64-y += cirrus_vga.o parallel.o acpi.o piix_pci.o
 | 
			
		||||
obj-ia64-y += usb-uhci.o
 | 
			
		||||
obj-ia64-$(CONFIG_KVM_DEVICE_ASSIGNMENT) += device-assignment.o
 | 
			
		||||
 | 
			
		||||
# shared objects
 | 
			
		||||
obj-ppc-y = ppc.o
 | 
			
		||||
@@ -286,6 +306,8 @@ obj-lm32-y += milkymist-vgafb.o
 | 
			
		||||
obj-lm32-y += framebuffer.o
 | 
			
		||||
 | 
			
		||||
obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
 | 
			
		||||
obj-mips-y += pcspk.o i8254.o
 | 
			
		||||
obj-mips-y += acpi.o acpi_piix4.o
 | 
			
		||||
obj-mips-y += mips_addr.o mips_timer.o mips_int.o
 | 
			
		||||
obj-mips-y += vga.o i8259.o
 | 
			
		||||
obj-mips-y += g364fb.o jazz_led.o
 | 
			
		||||
@@ -372,6 +394,11 @@ obj-s390x-y = s390-virtio-bus.o s390-virtio.o
 | 
			
		||||
obj-alpha-y = i8259.o mc146818rtc.o
 | 
			
		||||
obj-alpha-y += vga.o cirrus_vga.o
 | 
			
		||||
 | 
			
		||||
ifeq ($(TARGET_ARCH), ia64)
 | 
			
		||||
firmware.o: firmware.c
 | 
			
		||||
	$(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
 | 
			
		||||
 | 
			
		||||
monitor.o: hmp-commands.h qmp-commands.h
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								arm.ld
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								arm.ld
									
									
									
									
									
								
							@@ -71,23 +71,23 @@ SECTIONS
 | 
			
		||||
  .data1   : { *(.data1) }
 | 
			
		||||
  .preinit_array     :
 | 
			
		||||
  {
 | 
			
		||||
    PROVIDE_HIDDEN (__preinit_array_start = .);
 | 
			
		||||
    PROVIDE (__preinit_array_start = .);
 | 
			
		||||
    KEEP (*(.preinit_array))
 | 
			
		||||
    PROVIDE_HIDDEN (__preinit_array_end = .);
 | 
			
		||||
    PROVIDE (__preinit_array_end = .);
 | 
			
		||||
  }
 | 
			
		||||
  .init_array     :
 | 
			
		||||
  {
 | 
			
		||||
     PROVIDE_HIDDEN (__init_array_start = .);
 | 
			
		||||
     PROVIDE (__init_array_start = .);
 | 
			
		||||
     KEEP (*(SORT(.init_array.*)))
 | 
			
		||||
     KEEP (*(.init_array))
 | 
			
		||||
     PROVIDE_HIDDEN (__init_array_end = .);
 | 
			
		||||
     PROVIDE (__init_array_end = .);
 | 
			
		||||
  }
 | 
			
		||||
  .fini_array     :
 | 
			
		||||
  {
 | 
			
		||||
    PROVIDE_HIDDEN (__fini_array_start = .);
 | 
			
		||||
    PROVIDE (__fini_array_start = .);
 | 
			
		||||
    KEEP (*(.fini_array))
 | 
			
		||||
    KEEP (*(SORT(.fini_array.*)))
 | 
			
		||||
    PROVIDE_HIDDEN (__fini_array_end = .);
 | 
			
		||||
    PROVIDE (__fini_array_end = .);
 | 
			
		||||
  }
 | 
			
		||||
  .ctors         :
 | 
			
		||||
  {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										61
									
								
								balloon.c
									
									
									
									
									
								
							
							
						
						
									
										61
									
								
								balloon.c
									
									
									
									
									
								
							@@ -1,7 +1,9 @@
 | 
			
		||||
/*
 | 
			
		||||
 * QEMU System Emulator
 | 
			
		||||
 * Generic Balloon handlers and management
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2003-2008 Fabrice Bellard
 | 
			
		||||
 * Copyright (C) 2011 Red Hat, Inc.
 | 
			
		||||
 * Copyright (C) 2011 Amit Shah <amit.shah@redhat.com>
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
@@ -30,44 +32,53 @@
 | 
			
		||||
#include "balloon.h"
 | 
			
		||||
#include "trace.h"
 | 
			
		||||
 | 
			
		||||
static QEMUBalloonEvent *balloon_event_fn;
 | 
			
		||||
static QEMUBalloonStatus *balloon_stat_fn;
 | 
			
		||||
static void *balloon_opaque;
 | 
			
		||||
 | 
			
		||||
static QEMUBalloonEvent *qemu_balloon_event;
 | 
			
		||||
void *qemu_balloon_event_opaque;
 | 
			
		||||
 | 
			
		||||
void qemu_add_balloon_handler(QEMUBalloonEvent *func, void *opaque)
 | 
			
		||||
int qemu_add_balloon_handler(QEMUBalloonEvent *event_func,
 | 
			
		||||
                             QEMUBalloonStatus *stat_func, void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    qemu_balloon_event = func;
 | 
			
		||||
    qemu_balloon_event_opaque = opaque;
 | 
			
		||||
    if (balloon_event_fn || balloon_stat_fn || balloon_opaque) {
 | 
			
		||||
        /* We're already registered one balloon handler.  How many can
 | 
			
		||||
         * a guest really have?
 | 
			
		||||
         */
 | 
			
		||||
        error_report("Another balloon device already registered");
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    balloon_event_fn = event_func;
 | 
			
		||||
    balloon_stat_fn = stat_func;
 | 
			
		||||
    balloon_opaque = opaque;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int qemu_balloon(ram_addr_t target, MonitorCompletion cb, void *opaque)
 | 
			
		||||
static int qemu_balloon(ram_addr_t target)
 | 
			
		||||
{
 | 
			
		||||
    if (qemu_balloon_event) {
 | 
			
		||||
        trace_balloon_event(qemu_balloon_event_opaque, target);
 | 
			
		||||
        qemu_balloon_event(qemu_balloon_event_opaque, target, cb, opaque);
 | 
			
		||||
        return 1;
 | 
			
		||||
    } else {
 | 
			
		||||
    if (!balloon_event_fn) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    trace_balloon_event(balloon_opaque, target);
 | 
			
		||||
    balloon_event_fn(balloon_opaque, target);
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int qemu_balloon_status(MonitorCompletion cb, void *opaque)
 | 
			
		||||
static int qemu_balloon_status(MonitorCompletion cb, void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    if (qemu_balloon_event) {
 | 
			
		||||
        qemu_balloon_event(qemu_balloon_event_opaque, 0, cb, opaque);
 | 
			
		||||
        return 1;
 | 
			
		||||
    } else {
 | 
			
		||||
    if (!balloon_stat_fn) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    balloon_stat_fn(balloon_opaque, cb, opaque);
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void print_balloon_stat(const char *key, QObject *obj, void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    Monitor *mon = opaque;
 | 
			
		||||
 | 
			
		||||
    if (strcmp(key, "actual"))
 | 
			
		||||
    if (strcmp(key, "actual")) {
 | 
			
		||||
        monitor_printf(mon, ",%s=%" PRId64, key,
 | 
			
		||||
                       qint_get_int(qobject_to_qint(obj)));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void monitor_print_balloon(Monitor *mon, const QObject *data)
 | 
			
		||||
@@ -75,9 +86,9 @@ void monitor_print_balloon(Monitor *mon, const QObject *data)
 | 
			
		||||
    QDict *qdict;
 | 
			
		||||
 | 
			
		||||
    qdict = qobject_to_qdict(data);
 | 
			
		||||
    if (!qdict_haskey(qdict, "actual"))
 | 
			
		||||
    if (!qdict_haskey(qdict, "actual")) {
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    monitor_printf(mon, "balloon: actual=%" PRId64,
 | 
			
		||||
                   qdict_get_int(qdict, "actual") >> 20);
 | 
			
		||||
    qdict_iter(qdict, print_balloon_stat, mon);
 | 
			
		||||
@@ -129,6 +140,7 @@ int do_info_balloon(Monitor *mon, MonitorCompletion cb, void *opaque)
 | 
			
		||||
int do_balloon(Monitor *mon, const QDict *params,
 | 
			
		||||
	       MonitorCompletion cb, void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    int64_t target;
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    if (kvm_enabled() && !kvm_has_sync_mmu()) {
 | 
			
		||||
@@ -136,7 +148,12 @@ int do_balloon(Monitor *mon, const QDict *params,
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ret = qemu_balloon(qdict_get_int(params, "value"), cb, opaque);
 | 
			
		||||
    target = qdict_get_int(params, "value");
 | 
			
		||||
    if (target <= 0) {
 | 
			
		||||
        qerror_report(QERR_INVALID_PARAMETER_VALUE, "target", "a size");
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    ret = qemu_balloon(target);
 | 
			
		||||
    if (ret == 0) {
 | 
			
		||||
        qerror_report(QERR_DEVICE_NOT_ACTIVE, "balloon");
 | 
			
		||||
        return -1;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								balloon.h
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								balloon.h
									
									
									
									
									
								
							@@ -16,14 +16,12 @@
 | 
			
		||||
 | 
			
		||||
#include "monitor.h"
 | 
			
		||||
 | 
			
		||||
typedef void (QEMUBalloonEvent)(void *opaque, ram_addr_t target,
 | 
			
		||||
                                MonitorCompletion cb, void *cb_data);
 | 
			
		||||
typedef void (QEMUBalloonEvent)(void *opaque, ram_addr_t target);
 | 
			
		||||
typedef void (QEMUBalloonStatus)(void *opaque, MonitorCompletion cb,
 | 
			
		||||
                                 void *cb_data);
 | 
			
		||||
 | 
			
		||||
void qemu_add_balloon_handler(QEMUBalloonEvent *func, void *opaque);
 | 
			
		||||
 | 
			
		||||
int qemu_balloon(ram_addr_t target, MonitorCompletion cb, void *opaque);
 | 
			
		||||
 | 
			
		||||
int qemu_balloon_status(MonitorCompletion cb, void *opaque);
 | 
			
		||||
int qemu_add_balloon_handler(QEMUBalloonEvent *event_func,
 | 
			
		||||
			     QEMUBalloonStatus *stat_func, void *opaque);
 | 
			
		||||
 | 
			
		||||
void monitor_print_balloon(Monitor *mon, const QObject *data);
 | 
			
		||||
int do_info_balloon(Monitor *mon, MonitorCompletion cb, void *opaque);
 | 
			
		||||
 
 | 
			
		||||
@@ -317,7 +317,8 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
 | 
			
		||||
{
 | 
			
		||||
    BDRVQcowState *s = bs->opaque;
 | 
			
		||||
    QCowSnapshot *sn;
 | 
			
		||||
    int i, snapshot_index, l1_size2;
 | 
			
		||||
    int i, snapshot_index;
 | 
			
		||||
    int cur_l1_bytes, sn_l1_bytes;
 | 
			
		||||
 | 
			
		||||
    snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_id);
 | 
			
		||||
    if (snapshot_index < 0)
 | 
			
		||||
@@ -330,14 +331,19 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
 | 
			
		||||
    if (qcow2_grow_l1_table(bs, sn->l1_size, true) < 0)
 | 
			
		||||
        goto fail;
 | 
			
		||||
 | 
			
		||||
    s->l1_size = sn->l1_size;
 | 
			
		||||
    l1_size2 = s->l1_size * sizeof(uint64_t);
 | 
			
		||||
    cur_l1_bytes = s->l1_size * sizeof(uint64_t);
 | 
			
		||||
    sn_l1_bytes = sn->l1_size * sizeof(uint64_t);
 | 
			
		||||
 | 
			
		||||
    if (cur_l1_bytes > sn_l1_bytes) {
 | 
			
		||||
        memset(s->l1_table + sn->l1_size, 0, cur_l1_bytes - sn_l1_bytes);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* copy the snapshot l1 table to the current l1 table */
 | 
			
		||||
    if (bdrv_pread(bs->file, sn->l1_table_offset,
 | 
			
		||||
                   s->l1_table, l1_size2) != l1_size2)
 | 
			
		||||
                   s->l1_table, sn_l1_bytes) < 0)
 | 
			
		||||
        goto fail;
 | 
			
		||||
    if (bdrv_pwrite_sync(bs->file, s->l1_table_offset,
 | 
			
		||||
                    s->l1_table, l1_size2) < 0)
 | 
			
		||||
                    s->l1_table, cur_l1_bytes) < 0)
 | 
			
		||||
        goto fail;
 | 
			
		||||
    for(i = 0;i < s->l1_size; i++) {
 | 
			
		||||
        be64_to_cpus(&s->l1_table[i]);
 | 
			
		||||
 
 | 
			
		||||
@@ -230,21 +230,21 @@ static void qed_read_l2_table_cb(void *opaque, int ret)
 | 
			
		||||
    QEDRequest *request = read_l2_table_cb->request;
 | 
			
		||||
    BDRVQEDState *s = read_l2_table_cb->s;
 | 
			
		||||
    CachedL2Table *l2_table = request->l2_table;
 | 
			
		||||
    uint64_t l2_offset = read_l2_table_cb->l2_offset;
 | 
			
		||||
 | 
			
		||||
    if (ret) {
 | 
			
		||||
        /* can't trust loaded L2 table anymore */
 | 
			
		||||
        qed_unref_l2_cache_entry(l2_table);
 | 
			
		||||
        request->l2_table = NULL;
 | 
			
		||||
    } else {
 | 
			
		||||
        l2_table->offset = read_l2_table_cb->l2_offset;
 | 
			
		||||
        l2_table->offset = l2_offset;
 | 
			
		||||
 | 
			
		||||
        qed_commit_l2_cache_entry(&s->l2_cache, l2_table);
 | 
			
		||||
 | 
			
		||||
        /* This is guaranteed to succeed because we just committed the entry
 | 
			
		||||
         * to the cache.
 | 
			
		||||
         */
 | 
			
		||||
        request->l2_table = qed_find_l2_cache_entry(&s->l2_cache,
 | 
			
		||||
                                                    l2_table->offset);
 | 
			
		||||
        request->l2_table = qed_find_l2_cache_entry(&s->l2_cache, l2_offset);
 | 
			
		||||
        assert(request->l2_table != NULL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -915,14 +915,14 @@ static void qed_commit_l2_update(void *opaque, int ret)
 | 
			
		||||
    QEDAIOCB *acb = opaque;
 | 
			
		||||
    BDRVQEDState *s = acb_to_s(acb);
 | 
			
		||||
    CachedL2Table *l2_table = acb->request.l2_table;
 | 
			
		||||
    uint64_t l2_offset = l2_table->offset;
 | 
			
		||||
 | 
			
		||||
    qed_commit_l2_cache_entry(&s->l2_cache, l2_table);
 | 
			
		||||
 | 
			
		||||
    /* This is guaranteed to succeed because we just committed the entry to the
 | 
			
		||||
     * cache.
 | 
			
		||||
     */
 | 
			
		||||
    acb->request.l2_table = qed_find_l2_cache_entry(&s->l2_cache,
 | 
			
		||||
                                                    l2_table->offset);
 | 
			
		||||
    acb->request.l2_table = qed_find_l2_cache_entry(&s->l2_cache, l2_offset);
 | 
			
		||||
    assert(acb->request.l2_table != NULL);
 | 
			
		||||
 | 
			
		||||
    qed_aio_next_io(opaque, ret);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								blockdev.c
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								blockdev.c
									
									
									
									
									
								
							@@ -17,6 +17,8 @@
 | 
			
		||||
#include "hw/qdev.h"
 | 
			
		||||
#include "block_int.h"
 | 
			
		||||
 | 
			
		||||
DriveInfo *extboot_drive = NULL;
 | 
			
		||||
 | 
			
		||||
static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
 | 
			
		||||
 | 
			
		||||
static const char *const if_name[IF_COUNT] = {
 | 
			
		||||
@@ -236,6 +238,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
 | 
			
		||||
    int on_read_error, on_write_error;
 | 
			
		||||
    const char *devaddr;
 | 
			
		||||
    DriveInfo *dinfo;
 | 
			
		||||
    int is_extboot = 0;
 | 
			
		||||
    int snapshot = 0;
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
@@ -363,6 +366,12 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    is_extboot = qemu_opt_get_bool(opts, "boot", 0);
 | 
			
		||||
    if (is_extboot && extboot_drive) {
 | 
			
		||||
        fprintf(stderr, "qemu: two bootable drives specified\n");
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    on_write_error = BLOCK_ERR_STOP_ENOSPC;
 | 
			
		||||
    if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
 | 
			
		||||
        if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
 | 
			
		||||
@@ -468,6 +477,10 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
 | 
			
		||||
        strncpy(dinfo->serial, serial, sizeof(dinfo->serial) - 1);
 | 
			
		||||
    QTAILQ_INSERT_TAIL(&drives, dinfo, next);
 | 
			
		||||
 | 
			
		||||
    if (is_extboot) {
 | 
			
		||||
        extboot_drive = dinfo;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bdrv_set_on_error(dinfo->bdrv, on_read_error, on_write_error);
 | 
			
		||||
 | 
			
		||||
    switch(type) {
 | 
			
		||||
 
 | 
			
		||||
@@ -66,4 +66,6 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
 | 
			
		||||
int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data);
 | 
			
		||||
int do_block_resize(Monitor *mon, const QDict *qdict, QObject **ret_data);
 | 
			
		||||
 | 
			
		||||
extern DriveInfo *extboot_drive;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -856,9 +856,6 @@ int main(int argc, char **argv)
 | 
			
		||||
            usage();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (optind >= argc)
 | 
			
		||||
        usage();
 | 
			
		||||
    filename = argv[optind];
 | 
			
		||||
 | 
			
		||||
    /* init debug */
 | 
			
		||||
    cpu_set_log_filename(log_file);
 | 
			
		||||
@@ -877,6 +874,11 @@ int main(int argc, char **argv)
 | 
			
		||||
        cpu_set_log(mask);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (optind >= argc) {
 | 
			
		||||
        usage();
 | 
			
		||||
    }
 | 
			
		||||
    filename = argv[optind];
 | 
			
		||||
 | 
			
		||||
    /* Zero out regs */
 | 
			
		||||
    memset(regs, 0, sizeof(struct target_pt_regs));
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -34,7 +34,28 @@ static inline void flush_icache_range(unsigned long start, unsigned long stop)
 | 
			
		||||
    asm volatile ("isync" : : : "memory");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Is this correct for PPC?
 | 
			
		||||
 */
 | 
			
		||||
static inline void dma_flush_range(unsigned long start, unsigned long stop)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif defined(__ia64__)
 | 
			
		||||
static inline void flush_icache_range(unsigned long start, unsigned long stop)
 | 
			
		||||
{
 | 
			
		||||
    while (start < stop) {
 | 
			
		||||
	asm volatile ("fc %0" :: "r"(start));
 | 
			
		||||
	start += 32;
 | 
			
		||||
    }
 | 
			
		||||
    asm volatile (";;sync.i;;srlz.i;;");
 | 
			
		||||
}
 | 
			
		||||
#define dma_flush_range(start, end) flush_icache_range(start, end)
 | 
			
		||||
#define qemu_cache_utils_init(envp) do { (void) (envp); } while (0)
 | 
			
		||||
#else
 | 
			
		||||
static inline void dma_flush_range(unsigned long start, unsigned long stop)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
#define qemu_cache_utils_init(envp) do { (void) (envp); } while (0)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,8 @@ START_TEST(escaped_string)
 | 
			
		||||
        { "\"\\n\"", "\n" },
 | 
			
		||||
        { "\"\\r\"", "\r" },
 | 
			
		||||
        { "\"\\t\"", "\t" },
 | 
			
		||||
        { "\"\\/\"", "\\/" },
 | 
			
		||||
        { "\"/\"", "/" },
 | 
			
		||||
        { "\"\\/\"", "/", .skip = 1 },
 | 
			
		||||
        { "\"\\\\\"", "\\" },
 | 
			
		||||
        { "\"\\\"\"", "\"" },
 | 
			
		||||
        { "\"hello world \\\"embedded string\\\"\"",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										150
									
								
								configure
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										150
									
								
								configure
									
									
									
									
										vendored
									
									
								
							@@ -93,7 +93,17 @@ audio_pt_int=""
 | 
			
		||||
audio_win_int=""
 | 
			
		||||
cc_i386=i386-pc-linux-gnu-gcc
 | 
			
		||||
 | 
			
		||||
target_list=""
 | 
			
		||||
target_list="x86_64-softmmu"
 | 
			
		||||
 | 
			
		||||
kvm_version() {
 | 
			
		||||
    local fname="$(dirname "$0")/KVM_VERSION"
 | 
			
		||||
 | 
			
		||||
    if test -f "$fname"; then
 | 
			
		||||
        cat "$fname"
 | 
			
		||||
    else
 | 
			
		||||
        echo "qemu-kvm-devel"
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Default value for a variable defining feature "foo".
 | 
			
		||||
#  * foo="no"  feature will only be used if --enable-foo arg is given
 | 
			
		||||
@@ -163,11 +173,14 @@ darwin_user="no"
 | 
			
		||||
bsd_user="no"
 | 
			
		||||
guest_base=""
 | 
			
		||||
uname_release=""
 | 
			
		||||
io_thread="no"
 | 
			
		||||
io_thread="yes"
 | 
			
		||||
mixemu="no"
 | 
			
		||||
kvm_cap_pit="yes"
 | 
			
		||||
kvm_cap_device_assignment="yes"
 | 
			
		||||
aix="no"
 | 
			
		||||
blobs="yes"
 | 
			
		||||
pkgversion=""
 | 
			
		||||
pkgversion=" ($(kvm_version))"
 | 
			
		||||
cpu_emulation="yes"
 | 
			
		||||
check_utests="no"
 | 
			
		||||
user_pie="no"
 | 
			
		||||
zero_malloc=""
 | 
			
		||||
@@ -179,6 +192,7 @@ smartcard=""
 | 
			
		||||
smartcard_nss=""
 | 
			
		||||
usb_redir=""
 | 
			
		||||
opengl=""
 | 
			
		||||
guest_agent="yes"
 | 
			
		||||
 | 
			
		||||
# parse CC options first
 | 
			
		||||
for opt do
 | 
			
		||||
@@ -408,6 +422,7 @@ SunOS)
 | 
			
		||||
  make="${MAKE-gmake}"
 | 
			
		||||
  install="${INSTALL-ginstall}"
 | 
			
		||||
  ld="gld"
 | 
			
		||||
  smbd="${SMBD-/usr/sfw/sbin/smbd}"
 | 
			
		||||
  needs_libsunmath="no"
 | 
			
		||||
  solarisrev=`uname -r | cut -f2 -d.`
 | 
			
		||||
  # have to select again, because `uname -m` returns i86pc
 | 
			
		||||
@@ -463,6 +478,13 @@ Haiku)
 | 
			
		||||
  if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
 | 
			
		||||
    audio_possible_drivers="$audio_possible_drivers fmod"
 | 
			
		||||
  fi
 | 
			
		||||
  if [ "$cpu" = "ia64" ] ; then
 | 
			
		||||
     xen="no"
 | 
			
		||||
     target_list="ia64-softmmu"
 | 
			
		||||
     cpu_emulation="no"
 | 
			
		||||
     gdbstub="no"
 | 
			
		||||
     slirp="no"
 | 
			
		||||
  fi
 | 
			
		||||
;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
@@ -476,6 +498,7 @@ fi
 | 
			
		||||
: ${make=${MAKE-make}}
 | 
			
		||||
: ${install=${INSTALL-install}}
 | 
			
		||||
: ${python=${PYTHON-python}}
 | 
			
		||||
: ${smbd=${SMBD-/usr/sbin/smbd}}
 | 
			
		||||
 | 
			
		||||
if test "$mingw32" = "yes" ; then
 | 
			
		||||
  EXESUF=".exe"
 | 
			
		||||
@@ -519,6 +542,8 @@ for opt do
 | 
			
		||||
  ;;
 | 
			
		||||
  --python=*) python="$optarg"
 | 
			
		||||
  ;;
 | 
			
		||||
  --smbd=*) smbd="$optarg"
 | 
			
		||||
  ;;
 | 
			
		||||
  --extra-cflags=*)
 | 
			
		||||
  ;;
 | 
			
		||||
  --extra-ldflags=*)
 | 
			
		||||
@@ -636,6 +661,14 @@ for opt do
 | 
			
		||||
  ;;
 | 
			
		||||
  --enable-kvm) kvm="yes"
 | 
			
		||||
  ;;
 | 
			
		||||
  --disable-kvm-pit) kvm_cap_pit="no"
 | 
			
		||||
  ;;
 | 
			
		||||
  --enable-kvm-pit) kvm_cap_pit="yes"
 | 
			
		||||
  ;;
 | 
			
		||||
  --disable-kvm-device-assignment) kvm_cap_device_assignment="no"
 | 
			
		||||
  ;;
 | 
			
		||||
  --enable-kvm-device-assignment) kvm_cap_device_assignment="yes"
 | 
			
		||||
  ;;
 | 
			
		||||
  --disable-spice) spice="no"
 | 
			
		||||
  ;;
 | 
			
		||||
  --enable-spice) spice="yes"
 | 
			
		||||
@@ -725,6 +758,8 @@ for opt do
 | 
			
		||||
  ;;
 | 
			
		||||
  --enable-docs) docs="yes"
 | 
			
		||||
  ;;
 | 
			
		||||
  --disable-cpu-emulation) cpu_emulation="no"
 | 
			
		||||
  ;;
 | 
			
		||||
  --disable-vhost-net) vhost_net="no"
 | 
			
		||||
  ;;
 | 
			
		||||
  --enable-vhost-net) vhost_net="yes"
 | 
			
		||||
@@ -751,6 +786,10 @@ for opt do
 | 
			
		||||
  ;;
 | 
			
		||||
  --enable-usb-redir) usb_redir="yes"
 | 
			
		||||
  ;;
 | 
			
		||||
  --enable-guest-agent) guest_agent="yes"
 | 
			
		||||
  ;;
 | 
			
		||||
  --disable-guest-agent) guest_agent="no"
 | 
			
		||||
  ;;
 | 
			
		||||
  *) echo "ERROR: unknown option $opt"; show_help="yes"
 | 
			
		||||
  ;;
 | 
			
		||||
  esac
 | 
			
		||||
@@ -840,7 +879,6 @@ if [ "$softmmu" = "yes" ] ; then
 | 
			
		||||
    default_target_list="\
 | 
			
		||||
i386-softmmu \
 | 
			
		||||
x86_64-softmmu \
 | 
			
		||||
alpha-softmmu \
 | 
			
		||||
arm-softmmu \
 | 
			
		||||
cris-softmmu \
 | 
			
		||||
lm32-softmmu \
 | 
			
		||||
@@ -928,6 +966,7 @@ echo "  --extra-ldflags=LDFLAGS  append extra linker flags LDFLAGS"
 | 
			
		||||
echo "  --make=MAKE              use specified make [$make]"
 | 
			
		||||
echo "  --install=INSTALL        use specified install [$install]"
 | 
			
		||||
echo "  --python=PYTHON          use specified python [$python]"
 | 
			
		||||
echo "  --smbd=SMBD              use specified smbd [$smbd]"
 | 
			
		||||
echo "  --static                 enable static build [$static]"
 | 
			
		||||
echo "  --mandir=PATH            install man pages in PATH"
 | 
			
		||||
echo "  --datadir=PATH           install firmware in PATH"
 | 
			
		||||
@@ -980,6 +1019,10 @@ echo "  --enable-bluez           enable bluez stack connectivity"
 | 
			
		||||
echo "  --disable-slirp          disable SLIRP userspace network connectivity"
 | 
			
		||||
echo "  --disable-kvm            disable KVM acceleration support"
 | 
			
		||||
echo "  --enable-kvm             enable KVM acceleration support"
 | 
			
		||||
echo "  --disable-kvm-pit        disable KVM pit support"
 | 
			
		||||
echo "  --enable-kvm-pit         enable KVM pit support"
 | 
			
		||||
echo "  --disable-kvm-device-assignment  disable KVM device assignment support"
 | 
			
		||||
echo "  --enable-kvm-device-assignment   enable KVM device assignment support"
 | 
			
		||||
echo "  --disable-nptl           disable usermode NPTL support"
 | 
			
		||||
echo "  --enable-nptl            enable usermode NPTL support"
 | 
			
		||||
echo "  --enable-system          enable all system emulation targets"
 | 
			
		||||
@@ -1012,6 +1055,7 @@ echo "  --disable-attr           disables attr and xattr support"
 | 
			
		||||
echo "  --enable-attr            enable attr and xattr support"
 | 
			
		||||
echo "  --enable-io-thread       enable IO thread"
 | 
			
		||||
echo "  --disable-blobs          disable installing provided firmware blobs"
 | 
			
		||||
echo "  --disable-cpu-emulation  disables use of qemu cpu emulation code"
 | 
			
		||||
echo "  --enable-docs            enable documentation build"
 | 
			
		||||
echo "  --disable-docs           disable documentation build"
 | 
			
		||||
echo "  --disable-vhost-net      disable vhost-net acceleration support"
 | 
			
		||||
@@ -1029,6 +1073,8 @@ echo "  --disable-smartcard-nss  disable smartcard nss support"
 | 
			
		||||
echo "  --enable-smartcard-nss   enable smartcard nss support"
 | 
			
		||||
echo "  --disable-usb-redir      disable usb network redirection support"
 | 
			
		||||
echo "  --enable-usb-redir       enable usb network redirection support"
 | 
			
		||||
echo "  --disable-guest-agent    disable building of the QEMU Guest Agent"
 | 
			
		||||
echo "  --enable-guest-agent     enable building of the QEMU Guest Agent"
 | 
			
		||||
echo ""
 | 
			
		||||
echo "NOTE: The object files are built at the place where configure is launched"
 | 
			
		||||
exit 1
 | 
			
		||||
@@ -1088,11 +1134,13 @@ if test "$solaris" = "yes" ; then
 | 
			
		||||
  fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if has $python; then
 | 
			
		||||
if test "$guest_agent" != "no" ; then
 | 
			
		||||
  if has $python; then
 | 
			
		||||
    :
 | 
			
		||||
else
 | 
			
		||||
  else
 | 
			
		||||
    echo "Python not found. Use --python=/path/to/python"
 | 
			
		||||
    exit 1
 | 
			
		||||
  fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if test -z "$target_list" ; then
 | 
			
		||||
@@ -1505,11 +1553,17 @@ int main(void) {
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
EOF
 | 
			
		||||
  if $pkg_config libpng --modversion >/dev/null 2>&1; then
 | 
			
		||||
    vnc_png_cflags=`$pkg_config libpng --cflags 2> /dev/null`
 | 
			
		||||
    vnc_png_libs=`$pkg_config libpng --libs 2> /dev/null`
 | 
			
		||||
  else
 | 
			
		||||
    vnc_png_cflags=""
 | 
			
		||||
    vnc_png_libs="-lpng"
 | 
			
		||||
  fi
 | 
			
		||||
  if compile_prog "$vnc_png_cflags" "$vnc_png_libs" ; then
 | 
			
		||||
    vnc_png=yes
 | 
			
		||||
    libs_softmmu="$vnc_png_libs $libs_softmmu"
 | 
			
		||||
    QEMU_CFLAGS="$QEMU_CFLAGS $vnc_png_cflags"
 | 
			
		||||
  else
 | 
			
		||||
    if test "$vnc_png" = "yes" ; then
 | 
			
		||||
      feature_not_found "vnc-png"
 | 
			
		||||
@@ -1822,19 +1876,42 @@ fi
 | 
			
		||||
 | 
			
		||||
##########################################
 | 
			
		||||
# glib support probe
 | 
			
		||||
if $pkg_config --modversion glib-2.0 > /dev/null 2>&1 ; then
 | 
			
		||||
if test "$guest_agent" != "no" ; then
 | 
			
		||||
    if $pkg_config --modversion glib-2.0 > /dev/null 2>&1 ; then
 | 
			
		||||
        glib_cflags=`$pkg_config --cflags glib-2.0 2>/dev/null`
 | 
			
		||||
        glib_libs=`$pkg_config --libs glib-2.0 2>/dev/null`
 | 
			
		||||
        libs_softmmu="$glib_libs $libs_softmmu"
 | 
			
		||||
        libs_tools="$glib_libs $libs_tools"
 | 
			
		||||
else
 | 
			
		||||
    else
 | 
			
		||||
        echo "glib-2.0 required to compile QEMU"
 | 
			
		||||
        exit 1
 | 
			
		||||
    fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
##########################################
 | 
			
		||||
# libpci header probe for kvm_cap_device_assignment
 | 
			
		||||
if test $kvm_cap_device_assignment = "yes" ; then
 | 
			
		||||
  cat > $TMPC << EOF
 | 
			
		||||
#include <pci/header.h>
 | 
			
		||||
#ifndef PCI_VENDOR_ID
 | 
			
		||||
#error NO LIBPCI HEADER
 | 
			
		||||
#endif
 | 
			
		||||
int main(void) { return 0; }
 | 
			
		||||
EOF
 | 
			
		||||
  if compile_prog "" "" ; then
 | 
			
		||||
    kvm_cap_device_assignment=yes
 | 
			
		||||
  else
 | 
			
		||||
    echo
 | 
			
		||||
    echo "Error: libpci header check failed"
 | 
			
		||||
    echo "Disable KVM Device Assignment capability."
 | 
			
		||||
    echo
 | 
			
		||||
    kvm_cap_device_assignment=no
 | 
			
		||||
  fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
##########################################
 | 
			
		||||
# pthread probe
 | 
			
		||||
PTHREADLIBS_LIST="-lpthread -lpthreadGC2"
 | 
			
		||||
PTHREADLIBS_LIST="-pthread -lpthread -lpthreadGC2"
 | 
			
		||||
 | 
			
		||||
pthread=no
 | 
			
		||||
cat > $TMPC << EOF
 | 
			
		||||
@@ -2509,6 +2586,29 @@ if test "$trace_backend" = "dtrace"; then
 | 
			
		||||
  fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
##########################################
 | 
			
		||||
# __sync_fetch_and_and requires at least -march=i486. Many toolchains
 | 
			
		||||
# use i686 as default anyway, but for those that don't, an explicit
 | 
			
		||||
# specification is necessary
 | 
			
		||||
if test $vhost_net = "yes" && test $cpu = "i386"; then
 | 
			
		||||
  cat > $TMPC << EOF
 | 
			
		||||
int sfaa(unsigned *ptr)
 | 
			
		||||
{
 | 
			
		||||
  return __sync_fetch_and_and(ptr, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
  int val = 42;
 | 
			
		||||
  sfaa(&val);
 | 
			
		||||
  return val;
 | 
			
		||||
}
 | 
			
		||||
EOF
 | 
			
		||||
  if ! compile_prog "" "" ; then
 | 
			
		||||
    CFLAGS+="-march=i486"
 | 
			
		||||
  fi
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
##########################################
 | 
			
		||||
# End of CC checks
 | 
			
		||||
# After here, no more $cc or $ld runs
 | 
			
		||||
@@ -2566,7 +2666,9 @@ if test "$softmmu" = yes ; then
 | 
			
		||||
  tools="qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools"
 | 
			
		||||
  if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
 | 
			
		||||
      tools="qemu-nbd\$(EXESUF) $tools"
 | 
			
		||||
    if [ "$guest_agent" = "yes" ]; then
 | 
			
		||||
      tools="qemu-ga\$(EXESUF) $tools"
 | 
			
		||||
    fi
 | 
			
		||||
    if [ "$check_utests" = "yes" ]; then
 | 
			
		||||
      tools="check-qint check-qstring check-qdict check-qlist $tools"
 | 
			
		||||
      tools="check-qfloat check-qjson $tools"
 | 
			
		||||
@@ -2603,6 +2705,9 @@ echo "LDFLAGS           $LDFLAGS"
 | 
			
		||||
echo "make              $make"
 | 
			
		||||
echo "install           $install"
 | 
			
		||||
echo "python            $python"
 | 
			
		||||
if test "$slirp" = "yes" ; then
 | 
			
		||||
    echo "smbd              $smbd"
 | 
			
		||||
fi
 | 
			
		||||
echo "host CPU          $cpu"
 | 
			
		||||
echo "host big endian   $bigendian"
 | 
			
		||||
echo "target list       $target_list"
 | 
			
		||||
@@ -2638,6 +2743,7 @@ if test -n "$sparc_cpu"; then
 | 
			
		||||
    echo "Target Sparc Arch $sparc_cpu"
 | 
			
		||||
fi
 | 
			
		||||
echo "xen support       $xen"
 | 
			
		||||
echo "CPU emulation     $cpu_emulation"
 | 
			
		||||
echo "brlapi support    $brlapi"
 | 
			
		||||
echo "bluez  support    $bluez"
 | 
			
		||||
echo "Documentation     $docs"
 | 
			
		||||
@@ -2652,6 +2758,8 @@ echo "Linux AIO support $linux_aio"
 | 
			
		||||
echo "ATTR/XATTR support $attr"
 | 
			
		||||
echo "Install blobs     $blobs"
 | 
			
		||||
echo "KVM support       $kvm"
 | 
			
		||||
echo "KVM PIT support   $kvm_cap_pit"
 | 
			
		||||
echo "KVM device assig. $kvm_cap_device_assignment"
 | 
			
		||||
echo "fdt support       $fdt"
 | 
			
		||||
echo "preadv support    $preadv"
 | 
			
		||||
echo "fdatasync         $fdatasync"
 | 
			
		||||
@@ -2667,6 +2775,7 @@ echo "xfsctl support    $xfs"
 | 
			
		||||
echo "nss used          $smartcard_nss"
 | 
			
		||||
echo "usb net redir     $usb_redir"
 | 
			
		||||
echo "OpenGL support    $opengl"
 | 
			
		||||
echo "build guest agent $guest_agent"
 | 
			
		||||
 | 
			
		||||
if test $sdl_too_old = "yes"; then
 | 
			
		||||
echo "-> Your SDL version is too old - please upgrade to have SDL support"
 | 
			
		||||
@@ -2760,6 +2869,7 @@ if test $profiler = "yes" ; then
 | 
			
		||||
fi
 | 
			
		||||
if test "$slirp" = "yes" ; then
 | 
			
		||||
  echo "CONFIG_SLIRP=y" >> $config_host_mak
 | 
			
		||||
  echo "CONFIG_SMBD_COMMAND=\"$smbd\"" >> $config_host_mak
 | 
			
		||||
  QEMU_INCLUDES="-I\$(SRC_PATH)/slirp $QEMU_INCLUDES"
 | 
			
		||||
fi
 | 
			
		||||
if test "$vde" = "yes" ; then
 | 
			
		||||
@@ -2941,6 +3051,11 @@ fi
 | 
			
		||||
if test "$fdatasync" = "yes" ; then
 | 
			
		||||
  echo "CONFIG_FDATASYNC=y" >> $config_host_mak
 | 
			
		||||
fi
 | 
			
		||||
if test $cpu_emulation = "yes"; then
 | 
			
		||||
  echo "CONFIG_CPU_EMULATION=y" >> $config_host_mak
 | 
			
		||||
else
 | 
			
		||||
  echo "CONFIG_NO_CPU_EMULATION=y" >> $config_host_mak
 | 
			
		||||
fi
 | 
			
		||||
if test "$madvise" = "yes" ; then
 | 
			
		||||
  echo "CONFIG_MADVISE=y" >> $config_host_mak
 | 
			
		||||
fi
 | 
			
		||||
@@ -3012,9 +3127,9 @@ echo "TOOLS=$tools" >> $config_host_mak
 | 
			
		||||
echo "ROMS=$roms" >> $config_host_mak
 | 
			
		||||
echo "MAKE=$make" >> $config_host_mak
 | 
			
		||||
echo "INSTALL=$install" >> $config_host_mak
 | 
			
		||||
echo "INSTALL_DIR=$install -d -m0755 -p" >> $config_host_mak
 | 
			
		||||
echo "INSTALL_DATA=$install -m0644 -p" >> $config_host_mak
 | 
			
		||||
echo "INSTALL_PROG=$install -m0755 -p" >> $config_host_mak
 | 
			
		||||
echo "INSTALL_DIR=$install -d -m 0755" >> $config_host_mak
 | 
			
		||||
echo "INSTALL_DATA=$install -c -m 0644" >> $config_host_mak
 | 
			
		||||
echo "INSTALL_PROG=$install -c -m 0755" >> $config_host_mak
 | 
			
		||||
echo "PYTHON=$python" >> $config_host_mak
 | 
			
		||||
echo "CC=$cc" >> $config_host_mak
 | 
			
		||||
echo "CC_I386=$cc_i386" >> $config_host_mak
 | 
			
		||||
@@ -3148,6 +3263,9 @@ case "$target_arch2" in
 | 
			
		||||
    target_phys_bits=64
 | 
			
		||||
    target_long_alignment=8
 | 
			
		||||
  ;;
 | 
			
		||||
  ia64)
 | 
			
		||||
    target_phys_bits=64
 | 
			
		||||
  ;;
 | 
			
		||||
  alpha)
 | 
			
		||||
    target_phys_bits=64
 | 
			
		||||
    target_long_alignment=8
 | 
			
		||||
@@ -3310,6 +3428,12 @@ case "$target_arch2" in
 | 
			
		||||
      if test $vhost_net = "yes" ; then
 | 
			
		||||
        echo "CONFIG_VHOST_NET=y" >> $config_target_mak
 | 
			
		||||
      fi
 | 
			
		||||
      if test $kvm_cap_pit = "yes" ; then
 | 
			
		||||
        echo "CONFIG_KVM_PIT=y" >> $config_target_mak
 | 
			
		||||
      fi
 | 
			
		||||
      if test $kvm_cap_device_assignment = "yes" ; then
 | 
			
		||||
        echo "CONFIG_KVM_DEVICE_ASSIGNMENT=y" >> $config_target_mak
 | 
			
		||||
      fi
 | 
			
		||||
    fi
 | 
			
		||||
esac
 | 
			
		||||
if test "$target_bigendian" = "yes" ; then
 | 
			
		||||
@@ -3530,7 +3654,7 @@ DIRS="$DIRS roms/seabios roms/vgabios"
 | 
			
		||||
DIRS="$DIRS fsdev ui"
 | 
			
		||||
DIRS="$DIRS qapi"
 | 
			
		||||
DIRS="$DIRS qga"
 | 
			
		||||
FILES="Makefile tests/Makefile"
 | 
			
		||||
FILES="Makefile tests/Makefile qdict-test-data.txt"
 | 
			
		||||
FILES="$FILES tests/cris/Makefile tests/cris/.gdbinit"
 | 
			
		||||
FILES="$FILES pc-bios/optionrom/Makefile pc-bios/keymaps"
 | 
			
		||||
FILES="$FILES pc-bios/spapr-rtas/Makefile"
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,9 @@
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include "cpu.h"
 | 
			
		||||
#include "disas.h"
 | 
			
		||||
#if !defined(TARGET_IA64)
 | 
			
		||||
#include "tcg.h"
 | 
			
		||||
#endif
 | 
			
		||||
#include "qemu-barrier.h"
 | 
			
		||||
 | 
			
		||||
int tb_invalidated_flag;
 | 
			
		||||
@@ -222,6 +224,7 @@ int cpu_exec(CPUState *env)
 | 
			
		||||
#elif defined(TARGET_SH4)
 | 
			
		||||
#elif defined(TARGET_CRIS)
 | 
			
		||||
#elif defined(TARGET_S390X)
 | 
			
		||||
#elif defined(TARGET_IA64)
 | 
			
		||||
    /* XXXXX */
 | 
			
		||||
#else
 | 
			
		||||
#error unsupported target CPU
 | 
			
		||||
@@ -613,6 +616,7 @@ int cpu_exec(CPUState *env)
 | 
			
		||||
#elif defined(TARGET_MICROBLAZE)
 | 
			
		||||
#elif defined(TARGET_MIPS)
 | 
			
		||||
#elif defined(TARGET_SH4)
 | 
			
		||||
#elif defined(TARGET_IA64)
 | 
			
		||||
#elif defined(TARGET_ALPHA)
 | 
			
		||||
#elif defined(TARGET_CRIS)
 | 
			
		||||
#elif defined(TARGET_S390X)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								cpus.c
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								cpus.c
									
									
									
									
									
								
							@@ -688,6 +688,11 @@ void qemu_main_loop_start(void)
 | 
			
		||||
    qemu_cond_broadcast(&qemu_system_cond);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool qemu_system_is_ready(void)
 | 
			
		||||
{
 | 
			
		||||
    return qemu_system_ready;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void run_on_cpu(CPUState *env, void (*func)(void *data), void *data)
 | 
			
		||||
{
 | 
			
		||||
    struct qemu_work_item wi;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								cpus.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								cpus.h
									
									
									
									
									
								
							@@ -7,6 +7,7 @@ void qemu_main_loop_start(void);
 | 
			
		||||
void resume_all_vcpus(void);
 | 
			
		||||
void pause_all_vcpus(void);
 | 
			
		||||
void cpu_stop_current(void);
 | 
			
		||||
bool qemu_system_is_ready(void);
 | 
			
		||||
 | 
			
		||||
void cpu_synchronize_all_states(void);
 | 
			
		||||
void cpu_synchronize_all_post_reset(void);
 | 
			
		||||
 
 | 
			
		||||
@@ -809,9 +809,6 @@ int main(int argc, char **argv)
 | 
			
		||||
            usage();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (optind >= argc)
 | 
			
		||||
        usage();
 | 
			
		||||
    filename = argv[optind];
 | 
			
		||||
 | 
			
		||||
    /* init debug */
 | 
			
		||||
    cpu_set_log_filename(log_file);
 | 
			
		||||
@@ -830,6 +827,11 @@ int main(int argc, char **argv)
 | 
			
		||||
        cpu_set_log(mask);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (optind >= argc) {
 | 
			
		||||
        usage();
 | 
			
		||||
    }
 | 
			
		||||
    filename = argv[optind];
 | 
			
		||||
 | 
			
		||||
    /* Zero out regs */
 | 
			
		||||
    memset(regs, 0, sizeof(struct target_pt_regs));
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								exec.c
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								exec.c
									
									
									
									
									
								
							@@ -26,7 +26,12 @@
 | 
			
		||||
 | 
			
		||||
#include "qemu-common.h"
 | 
			
		||||
#include "cpu.h"
 | 
			
		||||
#include "cache-utils.h"
 | 
			
		||||
 | 
			
		||||
#if !defined(TARGET_IA64)
 | 
			
		||||
#include "tcg.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "hw/hw.h"
 | 
			
		||||
#include "hw/qdev.h"
 | 
			
		||||
#include "osdep.h"
 | 
			
		||||
@@ -461,6 +466,9 @@ static uint8_t static_code_gen_buffer[DEFAULT_CODE_GEN_BUFFER_SIZE]
 | 
			
		||||
 | 
			
		||||
static void code_gen_alloc(unsigned long tb_size)
 | 
			
		||||
{
 | 
			
		||||
    if (kvm_enabled())
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
#ifdef USE_STATIC_CODE_GEN_BUFFER
 | 
			
		||||
    code_gen_buffer = static_code_gen_buffer;
 | 
			
		||||
    code_gen_buffer_size = DEFAULT_CODE_GEN_BUFFER_SIZE;
 | 
			
		||||
@@ -3910,6 +3918,11 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
 | 
			
		||||
                    cpu_physical_memory_set_dirty_flags(
 | 
			
		||||
                        addr1, (0xff & ~CODE_DIRTY_FLAG));
 | 
			
		||||
                }
 | 
			
		||||
		/* qemu doesn't execute guest code directly, but kvm does
 | 
			
		||||
		   therefore flush instruction caches */
 | 
			
		||||
		if (kvm_enabled())
 | 
			
		||||
		    flush_icache_range((unsigned long)ptr,
 | 
			
		||||
				       ((unsigned long)ptr)+l);
 | 
			
		||||
                qemu_put_ram_ptr(ptr);
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
@@ -4103,6 +4116,8 @@ void *cpu_physical_memory_map(target_phys_addr_t addr,
 | 
			
		||||
void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
 | 
			
		||||
                               int is_write, target_phys_addr_t access_len)
 | 
			
		||||
{
 | 
			
		||||
    unsigned long flush_len = (unsigned long)access_len;
 | 
			
		||||
 | 
			
		||||
    if (buffer != bounce.buffer) {
 | 
			
		||||
        if (is_write) {
 | 
			
		||||
            ram_addr_t addr1 = qemu_ram_addr_from_host_nofail(buffer);
 | 
			
		||||
@@ -4121,6 +4136,8 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
 | 
			
		||||
                addr1 += l;
 | 
			
		||||
                access_len -= l;
 | 
			
		||||
	    }
 | 
			
		||||
	    dma_flush_range((unsigned long)buffer,
 | 
			
		||||
			    (unsigned long)buffer + flush_len);
 | 
			
		||||
        }
 | 
			
		||||
        if (xen_enabled()) {
 | 
			
		||||
            xen_invalidate_map_cache_entry(buffer);
 | 
			
		||||
@@ -4723,7 +4740,9 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
 | 
			
		||||
    cpu_fprintf(f, "TB flush count      %d\n", tb_flush_count);
 | 
			
		||||
    cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count);
 | 
			
		||||
    cpu_fprintf(f, "TLB flush count     %d\n", tlb_flush_count);
 | 
			
		||||
#ifdef CONFIG_PROFILER
 | 
			
		||||
    tcg_dump_info(f, cpu_fprintf);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define MMUSUFFIX _cmmu
 | 
			
		||||
 
 | 
			
		||||
@@ -1213,6 +1213,19 @@ STEXI
 | 
			
		||||
@item block_passwd @var{device} @var{password}
 | 
			
		||||
@findex block_passwd
 | 
			
		||||
Set the encrypted device @var{device} password to @var{password}
 | 
			
		||||
ETEXI
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        .name       = "cpu_set",
 | 
			
		||||
        .args_type  = "cpu:i,state:s",
 | 
			
		||||
        .params     = "cpu [online|offline]",
 | 
			
		||||
        .help       = "change cpu state",
 | 
			
		||||
        .mhandler.cmd  = do_cpu_set_nr,
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
STEXI
 | 
			
		||||
@item cpu_set @var{cpu} [online|offline]
 | 
			
		||||
Set CPU @var{cpu} online or offline.
 | 
			
		||||
ETEXI
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18
									
								
								hppa.ld
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								hppa.ld
									
									
									
									
									
								
							@@ -75,36 +75,34 @@ SECTIONS
 | 
			
		||||
  .sbss2          : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) }
 | 
			
		||||
  .PARISC.unwind   : { *(.PARISC.unwind) }
 | 
			
		||||
  .eh_frame_hdr : { *(.eh_frame_hdr) }
 | 
			
		||||
  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }
 | 
			
		||||
  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
 | 
			
		||||
  /* Adjust the address for the data segment.  We want to adjust up to
 | 
			
		||||
     the same address within the page on the next page up.  */
 | 
			
		||||
  . = ALIGN(0x10000) + (. & (0x10000 - 1));
 | 
			
		||||
  /* Exception handling  */
 | 
			
		||||
  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }
 | 
			
		||||
  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
 | 
			
		||||
  .eh_frame       : { KEEP (*(.eh_frame)) }
 | 
			
		||||
  .gcc_except_table   : { *(.gcc_except_table .gcc_except_table.*) }
 | 
			
		||||
  /* Thread Local Storage sections  */
 | 
			
		||||
  .tdata	  : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
 | 
			
		||||
  .tbss		  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
 | 
			
		||||
  .preinit_array     :
 | 
			
		||||
  {
 | 
			
		||||
    PROVIDE_HIDDEN (__preinit_array_start = .);
 | 
			
		||||
    PROVIDE (__preinit_array_start = .);
 | 
			
		||||
    KEEP (*(.preinit_array))
 | 
			
		||||
    PROVIDE_HIDDEN (__preinit_array_end = .);
 | 
			
		||||
    PROVIDE (__preinit_array_end = .);
 | 
			
		||||
  }
 | 
			
		||||
  .init_array     :
 | 
			
		||||
  {
 | 
			
		||||
     PROVIDE_HIDDEN (__init_array_start = .);
 | 
			
		||||
     PROVIDE (__init_array_start = .);
 | 
			
		||||
     KEEP (*(SORT(.init_array.*)))
 | 
			
		||||
     KEEP (*(.init_array))
 | 
			
		||||
     PROVIDE_HIDDEN (__init_array_end = .);
 | 
			
		||||
     PROVIDE (__init_array_end = .);
 | 
			
		||||
  }
 | 
			
		||||
  .fini_array     :
 | 
			
		||||
  {
 | 
			
		||||
    PROVIDE_HIDDEN (__fini_array_start = .);
 | 
			
		||||
    PROVIDE (__fini_array_start = .);
 | 
			
		||||
    KEEP (*(.fini_array))
 | 
			
		||||
    KEEP (*(SORT(.fini_array.*)))
 | 
			
		||||
    PROVIDE_HIDDEN (__fini_array_end = .);
 | 
			
		||||
    PROVIDE (__fini_array_end = .);
 | 
			
		||||
  }
 | 
			
		||||
  .ctors          :
 | 
			
		||||
  {
 | 
			
		||||
 
 | 
			
		||||
@@ -36,13 +36,19 @@
 | 
			
		||||
#define ACPI_DBG_IO_ADDR  0xb044
 | 
			
		||||
 | 
			
		||||
#define GPE_BASE 0xafe0
 | 
			
		||||
#define PROC_BASE 0xaf00
 | 
			
		||||
#define GPE_LEN 4
 | 
			
		||||
#define PCI_BASE 0xae00
 | 
			
		||||
#define PCI_EJ_BASE 0xae08
 | 
			
		||||
#define PCI_RMV_BASE 0xae0c
 | 
			
		||||
 | 
			
		||||
#define PIIX4_CPU_HOTPLUG_STATUS 4
 | 
			
		||||
#define PIIX4_PCI_HOTPLUG_STATUS 2
 | 
			
		||||
 | 
			
		||||
struct gpe_regs {
 | 
			
		||||
    uint8_t cpus_sts[32];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct pci_status {
 | 
			
		||||
    uint32_t up;
 | 
			
		||||
    uint32_t down;
 | 
			
		||||
@@ -68,6 +74,7 @@ typedef struct PIIX4PMState {
 | 
			
		||||
 | 
			
		||||
    /* for pci hotplug */
 | 
			
		||||
    ACPIGPE gpe;
 | 
			
		||||
    struct gpe_regs gpe_cpu;
 | 
			
		||||
    struct pci_status pci0_status;
 | 
			
		||||
    uint32_t pci0_hotplug_enable;
 | 
			
		||||
} PIIX4PMState;
 | 
			
		||||
@@ -216,10 +223,9 @@ static int vmstate_acpi_post_load(void *opaque, int version_id)
 | 
			
		||||
 {                                                                   \
 | 
			
		||||
     .name       = (stringify(_field)),                              \
 | 
			
		||||
     .version_id = 0,                                                \
 | 
			
		||||
     .num        = GPE_LEN,                                          \
 | 
			
		||||
     .info       = &vmstate_info_uint16,                             \
 | 
			
		||||
     .size       = sizeof(uint16_t),                                 \
 | 
			
		||||
     .flags      = VMS_ARRAY | VMS_POINTER,                          \
 | 
			
		||||
     .flags      = VMS_SINGLE | VMS_POINTER,                         \
 | 
			
		||||
     .offset     = vmstate_offset_pointer(_state, _field, uint8_t),  \
 | 
			
		||||
 }
 | 
			
		||||
 | 
			
		||||
@@ -326,11 +332,16 @@ static void piix4_pm_machine_ready(Notifier *n, void *opaque)
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PIIX4PMState *global_piix4_pm_state; /* cpu hotadd */
 | 
			
		||||
 | 
			
		||||
static int piix4_pm_initfn(PCIDevice *dev)
 | 
			
		||||
{
 | 
			
		||||
    PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev, dev);
 | 
			
		||||
    uint8_t *pci_conf;
 | 
			
		||||
 | 
			
		||||
    /* for cpu hotadd */
 | 
			
		||||
    global_piix4_pm_state = s;
 | 
			
		||||
 | 
			
		||||
    pci_conf = s->dev.config;
 | 
			
		||||
    pci_conf[0x06] = 0x80;
 | 
			
		||||
    pci_conf[0x07] = 0x02;
 | 
			
		||||
@@ -339,6 +350,13 @@ static int piix4_pm_initfn(PCIDevice *dev)
 | 
			
		||||
 | 
			
		||||
    pci_conf[0x40] = 0x01; /* PM io base read only bit */
 | 
			
		||||
 | 
			
		||||
#if defined(TARGET_IA64)
 | 
			
		||||
    pci_conf[0x40] = 0x41; /* PM io base read only bit */
 | 
			
		||||
    pci_conf[0x41] = 0x1f;
 | 
			
		||||
    pm_write_config(s, 0x80, 0x01, 1); /*Set default pm_io_base 0x1f40*/
 | 
			
		||||
    s->pmcntrl = SCI_EN;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /* APM */
 | 
			
		||||
    apm_init(&s->apm, apm_ctrl_changed, s);
 | 
			
		||||
 | 
			
		||||
@@ -422,7 +440,16 @@ device_init(piix4_pm_register);
 | 
			
		||||
static uint32_t gpe_readb(void *opaque, uint32_t addr)
 | 
			
		||||
{
 | 
			
		||||
    PIIX4PMState *s = opaque;
 | 
			
		||||
    uint32_t val = acpi_gpe_ioport_readb(&s->gpe, addr);
 | 
			
		||||
    uint32_t val = 0;
 | 
			
		||||
    struct gpe_regs *g = &s->gpe_cpu;
 | 
			
		||||
 | 
			
		||||
    switch (addr) {
 | 
			
		||||
        case PROC_BASE ... PROC_BASE+31:
 | 
			
		||||
            val = g->cpus_sts[addr - PROC_BASE];
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            val = acpi_gpe_ioport_readb(&s->gpe, addr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    PIIX4_DPRINTF("gpe read %x == %x\n", addr, val);
 | 
			
		||||
    return val;
 | 
			
		||||
@@ -510,17 +537,28 @@ static void pcirmv_write(void *opaque, uint32_t addr, uint32_t val)
 | 
			
		||||
    return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern const char *global_cpu_model;
 | 
			
		||||
 | 
			
		||||
static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
 | 
			
		||||
                                PCIHotplugState state);
 | 
			
		||||
 | 
			
		||||
static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
 | 
			
		||||
{
 | 
			
		||||
    struct pci_status *pci0_status = &s->pci0_status;
 | 
			
		||||
    int i = 0, cpus = smp_cpus;
 | 
			
		||||
 | 
			
		||||
    while (cpus > 0) {
 | 
			
		||||
        s->gpe_cpu.cpus_sts[i++] = (cpus < 8) ? (1 << cpus) - 1 : 0xff;
 | 
			
		||||
        cpus -= 8;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    register_ioport_write(GPE_BASE, GPE_LEN, 1, gpe_writeb, s);
 | 
			
		||||
    register_ioport_read(GPE_BASE, GPE_LEN, 1,  gpe_readb, s);
 | 
			
		||||
    acpi_gpe_blk(&s->gpe, GPE_BASE);
 | 
			
		||||
 | 
			
		||||
    register_ioport_write(PROC_BASE, 32, 1, gpe_writeb, s);
 | 
			
		||||
    register_ioport_read(PROC_BASE, 32, 1,  gpe_readb, s);
 | 
			
		||||
 | 
			
		||||
    register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, pci0_status);
 | 
			
		||||
    register_ioport_read(PCI_BASE, 8, 4,  pcihotplug_read, pci0_status);
 | 
			
		||||
 | 
			
		||||
@@ -533,6 +571,48 @@ static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
 | 
			
		||||
    pci_bus_hotplug(bus, piix4_device_hotplug, &s->dev.qdev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(TARGET_I386)
 | 
			
		||||
static void enable_processor(PIIX4PMState *s, int cpu)
 | 
			
		||||
{
 | 
			
		||||
    struct gpe_regs *g = &s->gpe_cpu;
 | 
			
		||||
    ACPIGPE *gpe = &s->gpe;
 | 
			
		||||
 | 
			
		||||
    *gpe->sts = *gpe->sts | PIIX4_CPU_HOTPLUG_STATUS;
 | 
			
		||||
    g->cpus_sts[cpu/8] |= (1 << (cpu%8));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void disable_processor(PIIX4PMState *s, int cpu)
 | 
			
		||||
{
 | 
			
		||||
    struct gpe_regs *g = &s->gpe_cpu;
 | 
			
		||||
    ACPIGPE *gpe = &s->gpe;
 | 
			
		||||
 | 
			
		||||
    *gpe->sts = *gpe->sts | PIIX4_CPU_HOTPLUG_STATUS;
 | 
			
		||||
    g->cpus_sts[cpu/8] &= ~(1 << (cpu%8));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void qemu_system_cpu_hot_add(int cpu, int state)
 | 
			
		||||
{
 | 
			
		||||
    CPUState *env;
 | 
			
		||||
    PIIX4PMState *s = global_piix4_pm_state;
 | 
			
		||||
 | 
			
		||||
    if (state && !qemu_get_cpu(cpu)) {
 | 
			
		||||
        env = pc_new_cpu(global_cpu_model);
 | 
			
		||||
        if (!env) {
 | 
			
		||||
            fprintf(stderr, "cpu %d creation failed\n", cpu);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        env->cpuid_apic_id = cpu;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (state)
 | 
			
		||||
        enable_processor(s, cpu);
 | 
			
		||||
    else
 | 
			
		||||
        disable_processor(s, cpu);
 | 
			
		||||
 | 
			
		||||
    pm_update_sci(s);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void enable_device(PIIX4PMState *s, int slot)
 | 
			
		||||
{
 | 
			
		||||
    s->gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										116
									
								
								hw/apic.c
									
									
									
									
									
								
							
							
						
						
									
										116
									
								
								hw/apic.c
									
									
									
									
									
								
							@@ -23,6 +23,7 @@
 | 
			
		||||
#include "host-utils.h"
 | 
			
		||||
#include "sysbus.h"
 | 
			
		||||
#include "trace.h"
 | 
			
		||||
#include "kvm.h"
 | 
			
		||||
 | 
			
		||||
/* APIC Local Vector Table */
 | 
			
		||||
#define APIC_LVT_TIMER   0
 | 
			
		||||
@@ -302,6 +303,9 @@ void cpu_set_apic_base(DeviceState *d, uint64_t val)
 | 
			
		||||
 | 
			
		||||
    if (!s)
 | 
			
		||||
        return;
 | 
			
		||||
    if (kvm_enabled() && kvm_irqchip_in_kernel())
 | 
			
		||||
        s->apicbase = val;
 | 
			
		||||
    else
 | 
			
		||||
        s->apicbase = (val & 0xfffff000) |
 | 
			
		||||
            (s->apicbase & (MSR_IA32_APICBASE_BSP | MSR_IA32_APICBASE_ENABLE));
 | 
			
		||||
    /* if disabled, cannot be enabled again */
 | 
			
		||||
@@ -418,6 +422,11 @@ int apic_get_irq_delivered(void)
 | 
			
		||||
    return apic_irq_delivered;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void apic_set_irq_delivered(void)
 | 
			
		||||
{
 | 
			
		||||
    apic_irq_delivered = 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void apic_set_irq(APICState *s, int vector_num, int trigger_mode)
 | 
			
		||||
{
 | 
			
		||||
    apic_irq_delivered += !get_bit(s->irr, vector_num);
 | 
			
		||||
@@ -889,6 +898,113 @@ static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef KVM_CAP_IRQCHIP
 | 
			
		||||
 | 
			
		||||
static inline uint32_t kapic_reg(struct kvm_lapic_state *kapic, int reg_id)
 | 
			
		||||
{
 | 
			
		||||
    return *((uint32_t *) (kapic->regs + (reg_id << 4)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void kapic_set_reg(struct kvm_lapic_state *kapic,
 | 
			
		||||
                                 int reg_id, uint32_t val)
 | 
			
		||||
{
 | 
			
		||||
    *((uint32_t *) (kapic->regs + (reg_id << 4))) = val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void kvm_kernel_lapic_save_to_user(APICState *s)
 | 
			
		||||
{
 | 
			
		||||
    struct kvm_lapic_state apic;
 | 
			
		||||
    struct kvm_lapic_state *kapic = &apic;
 | 
			
		||||
    int i, v;
 | 
			
		||||
 | 
			
		||||
    kvm_get_lapic(s->cpu_env, kapic);
 | 
			
		||||
 | 
			
		||||
    s->id = kapic_reg(kapic, 0x2) >> 24;
 | 
			
		||||
    s->tpr = kapic_reg(kapic, 0x8);
 | 
			
		||||
    s->arb_id = kapic_reg(kapic, 0x9);
 | 
			
		||||
    s->log_dest = kapic_reg(kapic, 0xd) >> 24;
 | 
			
		||||
    s->dest_mode = kapic_reg(kapic, 0xe) >> 28;
 | 
			
		||||
    s->spurious_vec = kapic_reg(kapic, 0xf);
 | 
			
		||||
    for (i = 0; i < 8; i++) {
 | 
			
		||||
        s->isr[i] = kapic_reg(kapic, 0x10 + i);
 | 
			
		||||
        s->tmr[i] = kapic_reg(kapic, 0x18 + i);
 | 
			
		||||
        s->irr[i] = kapic_reg(kapic, 0x20 + i);
 | 
			
		||||
    }
 | 
			
		||||
    s->esr = kapic_reg(kapic, 0x28);
 | 
			
		||||
    s->icr[0] = kapic_reg(kapic, 0x30);
 | 
			
		||||
    s->icr[1] = kapic_reg(kapic, 0x31);
 | 
			
		||||
    for (i = 0; i < APIC_LVT_NB; i++)
 | 
			
		||||
	s->lvt[i] = kapic_reg(kapic, 0x32 + i);
 | 
			
		||||
    s->initial_count = kapic_reg(kapic, 0x38);
 | 
			
		||||
    s->divide_conf = kapic_reg(kapic, 0x3e);
 | 
			
		||||
 | 
			
		||||
    v = (s->divide_conf & 3) | ((s->divide_conf >> 1) & 4);
 | 
			
		||||
    s->count_shift = (v + 1) & 7;
 | 
			
		||||
 | 
			
		||||
    s->initial_count_load_time = qemu_get_clock_ns(vm_clock);
 | 
			
		||||
    apic_timer_update(s, s->initial_count_load_time);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void kvm_kernel_lapic_load_from_user(APICState *s)
 | 
			
		||||
{
 | 
			
		||||
    struct kvm_lapic_state apic;
 | 
			
		||||
    struct kvm_lapic_state *klapic = &apic;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    memset(klapic, 0, sizeof apic);
 | 
			
		||||
    kapic_set_reg(klapic, 0x2, s->id << 24);
 | 
			
		||||
    kapic_set_reg(klapic, 0x8, s->tpr);
 | 
			
		||||
    kapic_set_reg(klapic, 0xd, s->log_dest << 24);
 | 
			
		||||
    kapic_set_reg(klapic, 0xe, s->dest_mode << 28 | 0x0fffffff);
 | 
			
		||||
    kapic_set_reg(klapic, 0xf, s->spurious_vec);
 | 
			
		||||
    for (i = 0; i < 8; i++) {
 | 
			
		||||
        kapic_set_reg(klapic, 0x10 + i, s->isr[i]);
 | 
			
		||||
        kapic_set_reg(klapic, 0x18 + i, s->tmr[i]);
 | 
			
		||||
        kapic_set_reg(klapic, 0x20 + i, s->irr[i]);
 | 
			
		||||
    }
 | 
			
		||||
    kapic_set_reg(klapic, 0x28, s->esr);
 | 
			
		||||
    kapic_set_reg(klapic, 0x30, s->icr[0]);
 | 
			
		||||
    kapic_set_reg(klapic, 0x31, s->icr[1]);
 | 
			
		||||
    for (i = 0; i < APIC_LVT_NB; i++)
 | 
			
		||||
        kapic_set_reg(klapic, 0x32 + i, s->lvt[i]);
 | 
			
		||||
    kapic_set_reg(klapic, 0x38, s->initial_count);
 | 
			
		||||
    kapic_set_reg(klapic, 0x3e, s->divide_conf);
 | 
			
		||||
 | 
			
		||||
    kvm_set_lapic(s->cpu_env, klapic);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void kvm_load_lapic(CPUState *env)
 | 
			
		||||
{
 | 
			
		||||
#ifdef KVM_CAP_IRQCHIP
 | 
			
		||||
    APICState *s = DO_UPCAST(APICState, busdev.qdev, env->apic_state);
 | 
			
		||||
 | 
			
		||||
    if (!s) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
 | 
			
		||||
        kvm_kernel_lapic_load_from_user(s);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void kvm_save_lapic(CPUState *env)
 | 
			
		||||
{
 | 
			
		||||
#ifdef KVM_CAP_IRQCHIP
 | 
			
		||||
    APICState *s = DO_UPCAST(APICState, busdev.qdev, env->apic_state);
 | 
			
		||||
 | 
			
		||||
    if (!s) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
 | 
			
		||||
        kvm_kernel_lapic_save_to_user(s);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This function is only used for old state version 1 and 2 */
 | 
			
		||||
static int apic_load_old(QEMUFile *f, void *opaque, int version_id)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@ void apic_deliver_pic_intr(DeviceState *s, int level);
 | 
			
		||||
int apic_get_interrupt(DeviceState *s);
 | 
			
		||||
void apic_reset_irq_delivered(void);
 | 
			
		||||
int apic_get_irq_delivered(void);
 | 
			
		||||
void apic_set_irq_delivered(void);
 | 
			
		||||
void cpu_set_apic_base(DeviceState *s, uint64_t val);
 | 
			
		||||
uint64_t cpu_get_apic_base(DeviceState *s);
 | 
			
		||||
void cpu_set_apic_tpr(DeviceState *s, uint8_t val);
 | 
			
		||||
 
 | 
			
		||||
@@ -2497,6 +2497,7 @@ static void map_linear_vram(CirrusVGAState *s)
 | 
			
		||||
    if (!s->vga.map_addr)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
#ifndef TARGET_IA64
 | 
			
		||||
    s->vga.lfb_vram_mapped = 0;
 | 
			
		||||
 | 
			
		||||
    if (!(s->cirrus_srcptr != s->cirrus_srcptr_end)
 | 
			
		||||
@@ -2519,6 +2520,7 @@ static void map_linear_vram(CirrusVGAState *s)
 | 
			
		||||
        cpu_register_physical_memory(isa_mem_base + 0xa0000, 0x20000,
 | 
			
		||||
                                     s->vga.vga_io_memory);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    vga_dirty_log_start(&s->vga);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1909
									
								
								hw/device-assignment.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1909
									
								
								hw/device-assignment.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										120
									
								
								hw/device-assignment.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								hw/device-assignment.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,120 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2007, Neocleus Corporation.
 | 
			
		||||
 * Copyright (c) 2007, 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.
 | 
			
		||||
 *
 | 
			
		||||
 *  Data structures for storing PCI state
 | 
			
		||||
 *
 | 
			
		||||
 *  Adapted to kvm by Qumranet
 | 
			
		||||
 *
 | 
			
		||||
 *  Copyright (c) 2007, Neocleus, Alex Novik (alex@neocleus.com)
 | 
			
		||||
 *  Copyright (c) 2007, Neocleus, Guy Zana (guy@neocleus.com)
 | 
			
		||||
 *  Copyright (C) 2008, Qumranet, Amit Shah (amit.shah@qumranet.com)
 | 
			
		||||
 *  Copyright (C) 2008, Red Hat, Amit Shah (amit.shah@redhat.com)
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __DEVICE_ASSIGNMENT_H__
 | 
			
		||||
#define __DEVICE_ASSIGNMENT_H__
 | 
			
		||||
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include "qemu-common.h"
 | 
			
		||||
#include "qemu-queue.h"
 | 
			
		||||
#include "pci.h"
 | 
			
		||||
 | 
			
		||||
/* From include/linux/pci.h in the kernel sources */
 | 
			
		||||
#define PCI_DEVFN(slot, func)   ((((slot) & 0x1f) << 3) | ((func) & 0x07))
 | 
			
		||||
 | 
			
		||||
typedef struct PCIHostDevice {
 | 
			
		||||
    int seg;
 | 
			
		||||
    int bus;
 | 
			
		||||
    int dev;
 | 
			
		||||
    int func;
 | 
			
		||||
} PCIHostDevice;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    int type;           /* Memory or port I/O */
 | 
			
		||||
    int valid;
 | 
			
		||||
    uint32_t base_addr;
 | 
			
		||||
    uint32_t size;    /* size of the region */
 | 
			
		||||
    int resource_fd;
 | 
			
		||||
} PCIRegion;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint8_t bus, dev, func; /* Bus inside domain, device and function */
 | 
			
		||||
    int irq;                /* IRQ number */
 | 
			
		||||
    uint16_t region_number; /* number of active regions */
 | 
			
		||||
 | 
			
		||||
    /* Port I/O or MMIO Regions */
 | 
			
		||||
    PCIRegion regions[PCI_NUM_REGIONS - 1];
 | 
			
		||||
    int config_fd;
 | 
			
		||||
} PCIDevRegions;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    pcibus_t e_physbase;
 | 
			
		||||
    ram_addr_t memory_index;
 | 
			
		||||
    union {
 | 
			
		||||
        void *r_virtbase;    /* mmapped access address for memory regions */
 | 
			
		||||
        uint32_t r_baseport; /* the base guest port for I/O regions */
 | 
			
		||||
    } u;
 | 
			
		||||
    int num;            /* our index within v_addrs[] */
 | 
			
		||||
    pcibus_t e_size;    /* emulated size of region in bytes */
 | 
			
		||||
    pcibus_t r_size;    /* real size of region in bytes */
 | 
			
		||||
    PCIRegion *region;
 | 
			
		||||
} AssignedDevRegion;
 | 
			
		||||
 | 
			
		||||
#define ASSIGNED_DEVICE_USE_IOMMU_BIT	0
 | 
			
		||||
#define ASSIGNED_DEVICE_PREFER_MSI_BIT	1
 | 
			
		||||
 | 
			
		||||
#define ASSIGNED_DEVICE_USE_IOMMU_MASK	(1 << ASSIGNED_DEVICE_USE_IOMMU_BIT)
 | 
			
		||||
#define ASSIGNED_DEVICE_PREFER_MSI_MASK	(1 << ASSIGNED_DEVICE_PREFER_MSI_BIT)
 | 
			
		||||
 | 
			
		||||
typedef struct AssignedDevice {
 | 
			
		||||
    PCIDevice dev;
 | 
			
		||||
    PCIHostDevice host;
 | 
			
		||||
    uint32_t features;
 | 
			
		||||
    int intpin;
 | 
			
		||||
    uint8_t debug_flags;
 | 
			
		||||
    AssignedDevRegion v_addrs[PCI_NUM_REGIONS - 1];
 | 
			
		||||
    PCIDevRegions real_device;
 | 
			
		||||
    int run;
 | 
			
		||||
    int girq;
 | 
			
		||||
    unsigned int h_segnr;
 | 
			
		||||
    unsigned char h_busnr;
 | 
			
		||||
    unsigned int h_devfn;
 | 
			
		||||
    int irq_requested_type;
 | 
			
		||||
    int bound;
 | 
			
		||||
    struct {
 | 
			
		||||
#define ASSIGNED_DEVICE_CAP_MSI (1 << 0)
 | 
			
		||||
#define ASSIGNED_DEVICE_CAP_MSIX (1 << 1)
 | 
			
		||||
        uint32_t available;
 | 
			
		||||
#define ASSIGNED_DEVICE_MSI_ENABLED (1 << 0)
 | 
			
		||||
#define ASSIGNED_DEVICE_MSIX_ENABLED (1 << 1)
 | 
			
		||||
#define ASSIGNED_DEVICE_MSIX_MASKED (1 << 2)
 | 
			
		||||
        uint32_t state;
 | 
			
		||||
    } cap;
 | 
			
		||||
    int irq_entries_nr;
 | 
			
		||||
    struct kvm_irq_routing_entry *entry;
 | 
			
		||||
    void *msix_table_page;
 | 
			
		||||
    target_phys_addr_t msix_table_addr;
 | 
			
		||||
    int mmio_index;
 | 
			
		||||
    uint32_t emulate_cmd_mask;
 | 
			
		||||
    char *configfd_name;
 | 
			
		||||
    int32_t bootindex;
 | 
			
		||||
    QLIST_ENTRY(AssignedDevice) next;
 | 
			
		||||
} AssignedDevice;
 | 
			
		||||
 | 
			
		||||
void assigned_dev_update_irqs(void);
 | 
			
		||||
 | 
			
		||||
#endif              /* __DEVICE_ASSIGNMENT_H__ */
 | 
			
		||||
							
								
								
									
										123
									
								
								hw/extboot.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								hw/extboot.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,123 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Extended boot option ROM support.
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright IBM, Corp. 2007
 | 
			
		||||
 *
 | 
			
		||||
 * Authors:
 | 
			
		||||
 *  Anthony Liguori   <aliguori@us.ibm.com>
 | 
			
		||||
 *
 | 
			
		||||
 * This work is licensed under the terms of the GNU GPL, version 2.  See
 | 
			
		||||
 * the COPYING file in the top-level directory.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "hw.h"
 | 
			
		||||
#include "pc.h"
 | 
			
		||||
#include "isa.h"
 | 
			
		||||
#include "block.h"
 | 
			
		||||
 | 
			
		||||
/* Extended Boot ROM suport */
 | 
			
		||||
 | 
			
		||||
union extboot_cmd
 | 
			
		||||
{
 | 
			
		||||
    uint16_t type;
 | 
			
		||||
    struct {
 | 
			
		||||
	uint16_t type;
 | 
			
		||||
	uint16_t cylinders;
 | 
			
		||||
	uint16_t heads;
 | 
			
		||||
	uint16_t sectors;
 | 
			
		||||
	uint64_t nb_sectors;
 | 
			
		||||
    } query_geometry;
 | 
			
		||||
    struct {
 | 
			
		||||
	uint16_t type;
 | 
			
		||||
	uint16_t nb_sectors;
 | 
			
		||||
	uint16_t segment;
 | 
			
		||||
	uint16_t offset;
 | 
			
		||||
	uint64_t sector;
 | 
			
		||||
    } xfer;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void get_translated_chs(BlockDriverState *bs, int *c, int *h, int *s)
 | 
			
		||||
{
 | 
			
		||||
    bdrv_get_geometry_hint(bs, c, h, s);
 | 
			
		||||
 | 
			
		||||
    if (*c <= 1024) {
 | 
			
		||||
	*c >>= 0;
 | 
			
		||||
	*h <<= 0;
 | 
			
		||||
    } else if (*c <= 2048) {
 | 
			
		||||
	*c >>= 1;
 | 
			
		||||
	*h <<= 1;
 | 
			
		||||
    } else if (*c <= 4096) {
 | 
			
		||||
	*c >>= 2;
 | 
			
		||||
	*h <<= 2;
 | 
			
		||||
    } else if (*c <= 8192) {
 | 
			
		||||
	*c >>= 3;
 | 
			
		||||
	*h <<= 3;
 | 
			
		||||
    } else {
 | 
			
		||||
	*c >>= 4;
 | 
			
		||||
	*h <<= 4;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* what is the correct algorithm for this?? */
 | 
			
		||||
    if (*h == 256) {
 | 
			
		||||
	*h = 255;
 | 
			
		||||
	*c = *c + 1;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void extboot_write_cmd(void *opaque, uint32_t addr, uint32_t value)
 | 
			
		||||
{
 | 
			
		||||
    union extboot_cmd cmd;
 | 
			
		||||
    BlockDriverState *bs = opaque;
 | 
			
		||||
    int cylinders, heads, sectors, err;
 | 
			
		||||
    uint64_t nb_sectors;
 | 
			
		||||
    target_phys_addr_t pa = 0;
 | 
			
		||||
    int blen = 0;
 | 
			
		||||
    void *buf = NULL;
 | 
			
		||||
 | 
			
		||||
    cpu_physical_memory_read((value & 0xFFFF) << 4, (uint8_t *)&cmd,
 | 
			
		||||
                             sizeof(cmd));
 | 
			
		||||
 | 
			
		||||
    if (cmd.type == 0x01 || cmd.type == 0x02) {
 | 
			
		||||
	pa = cmd.xfer.segment * 16 + cmd.xfer.offset;
 | 
			
		||||
        blen = cmd.xfer.nb_sectors * 512;
 | 
			
		||||
        buf = qemu_memalign(512, blen);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    switch (cmd.type) {
 | 
			
		||||
    case 0x00:
 | 
			
		||||
        get_translated_chs(bs, &cylinders, &heads, §ors);
 | 
			
		||||
	bdrv_get_geometry(bs, &nb_sectors);
 | 
			
		||||
	cmd.query_geometry.cylinders = cylinders;
 | 
			
		||||
	cmd.query_geometry.heads = heads;
 | 
			
		||||
	cmd.query_geometry.sectors = sectors;
 | 
			
		||||
	cmd.query_geometry.nb_sectors = nb_sectors;
 | 
			
		||||
	break;
 | 
			
		||||
    case 0x01:
 | 
			
		||||
	err = bdrv_read(bs, cmd.xfer.sector, buf, cmd.xfer.nb_sectors);
 | 
			
		||||
	if (err)
 | 
			
		||||
	    printf("Read failed\n");
 | 
			
		||||
 | 
			
		||||
        cpu_physical_memory_write(pa, buf, blen);
 | 
			
		||||
 | 
			
		||||
	break;
 | 
			
		||||
    case 0x02:
 | 
			
		||||
        cpu_physical_memory_read(pa, buf, blen);
 | 
			
		||||
 | 
			
		||||
	err = bdrv_write(bs, cmd.xfer.sector, buf, cmd.xfer.nb_sectors);
 | 
			
		||||
	if (err)
 | 
			
		||||
	    printf("Write failed\n");
 | 
			
		||||
 | 
			
		||||
	break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    cpu_physical_memory_write((value & 0xFFFF) << 4, (uint8_t *)&cmd,
 | 
			
		||||
                              sizeof(cmd));
 | 
			
		||||
    if (buf)
 | 
			
		||||
        qemu_free(buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void extboot_init(BlockDriverState *bs)
 | 
			
		||||
{
 | 
			
		||||
    register_ioport_write(0x405, 1, 2, extboot_write_cmd, bs);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										51
									
								
								hw/fdc.c
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								hw/fdc.c
									
									
									
									
									
								
							@@ -36,7 +36,6 @@
 | 
			
		||||
#include "qdev-addr.h"
 | 
			
		||||
#include "blockdev.h"
 | 
			
		||||
#include "sysemu.h"
 | 
			
		||||
#include "block_int.h"
 | 
			
		||||
 | 
			
		||||
/********************************************************/
 | 
			
		||||
/* debug Floppy devices */
 | 
			
		||||
@@ -83,7 +82,6 @@ typedef struct FDrive {
 | 
			
		||||
    uint8_t max_track;        /* Nb of tracks           */
 | 
			
		||||
    uint16_t bps;             /* Bytes per sector       */
 | 
			
		||||
    uint8_t ro;               /* Is read-only           */
 | 
			
		||||
    uint8_t media_changed;    /* Is media changed       */
 | 
			
		||||
} FDrive;
 | 
			
		||||
 | 
			
		||||
static void fd_init(FDrive *drv)
 | 
			
		||||
@@ -535,63 +533,16 @@ static CPUWriteMemoryFunc * const fdctrl_mem_write_strict[3] = {
 | 
			
		||||
    NULL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void fdrive_media_changed_pre_save(void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    FDrive *drive = opaque;
 | 
			
		||||
 | 
			
		||||
    drive->media_changed = drive->bs->media_changed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fdrive_media_changed_post_load(void *opaque, int version_id)
 | 
			
		||||
{
 | 
			
		||||
    FDrive *drive = opaque;
 | 
			
		||||
 | 
			
		||||
    if (drive->bs != NULL) {
 | 
			
		||||
        drive->bs->media_changed = drive->media_changed;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* User ejected the floppy when drive->bs == NULL */
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool fdrive_media_changed_needed(void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    FDrive *drive = opaque;
 | 
			
		||||
 | 
			
		||||
    return (drive->bs != NULL && drive->bs->media_changed != 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const VMStateDescription vmstate_fdrive_media_changed = {
 | 
			
		||||
    .name = "fdrive/media_changed",
 | 
			
		||||
    .version_id = 1,
 | 
			
		||||
    .minimum_version_id = 1,
 | 
			
		||||
    .minimum_version_id_old = 1,
 | 
			
		||||
    .pre_save = fdrive_media_changed_pre_save,
 | 
			
		||||
    .post_load = fdrive_media_changed_post_load,
 | 
			
		||||
    .fields      = (VMStateField[]) {
 | 
			
		||||
        VMSTATE_UINT8(media_changed, FDrive),
 | 
			
		||||
        VMSTATE_END_OF_LIST()
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const VMStateDescription vmstate_fdrive = {
 | 
			
		||||
    .name = "fdrive",
 | 
			
		||||
    .version_id = 1,
 | 
			
		||||
    .minimum_version_id = 1,
 | 
			
		||||
    .minimum_version_id_old = 1,
 | 
			
		||||
    .fields      = (VMStateField[]) {
 | 
			
		||||
    .fields      = (VMStateField []) {
 | 
			
		||||
        VMSTATE_UINT8(head, FDrive),
 | 
			
		||||
        VMSTATE_UINT8(track, FDrive),
 | 
			
		||||
        VMSTATE_UINT8(sect, FDrive),
 | 
			
		||||
        VMSTATE_END_OF_LIST()
 | 
			
		||||
    },
 | 
			
		||||
    .subsections = (VMStateSubsection[]) {
 | 
			
		||||
        {
 | 
			
		||||
            .vmsd = &vmstate_fdrive_media_changed,
 | 
			
		||||
            .needed = &fdrive_media_changed_needed,
 | 
			
		||||
        } , {
 | 
			
		||||
            /* empty */
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -236,6 +236,11 @@ static int hpet_post_load(void *opaque, int version_id)
 | 
			
		||||
    if (s->timer[0].config & HPET_TN_FSB_CAP) {
 | 
			
		||||
        s->flags |= 1 << HPET_MSI_SUPPORT;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (hpet_in_legacy_mode(s)) {
 | 
			
		||||
        hpet_pit_disable();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										115
									
								
								hw/i8254-kvm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								hw/i8254-kvm.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,115 @@
 | 
			
		||||
/*
 | 
			
		||||
 * QEMU 8253/8254 interval timer emulation
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2003-2004 Fabrice Bellard
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 * in the Software without restriction, including without limitation the rights
 | 
			
		||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
 * furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 | 
			
		||||
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
#include "hw.h"
 | 
			
		||||
#include "pc.h"
 | 
			
		||||
#include "isa.h"
 | 
			
		||||
#include "qemu-timer.h"
 | 
			
		||||
#include "i8254.h"
 | 
			
		||||
#include "qemu-kvm.h"
 | 
			
		||||
 | 
			
		||||
extern VMStateDescription vmstate_pit;
 | 
			
		||||
 | 
			
		||||
static void kvm_pit_pre_save(void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    PITState *s = (void *)opaque;
 | 
			
		||||
    struct kvm_pit_state2 pit2;
 | 
			
		||||
    struct kvm_pit_channel_state *c;
 | 
			
		||||
    struct PITChannelState *sc;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    if (kvm_has_pit_state2()) {
 | 
			
		||||
        kvm_get_pit2(kvm_state, &pit2);
 | 
			
		||||
        s->flags = pit2.flags;
 | 
			
		||||
    } else {
 | 
			
		||||
        /* pit2 is superset of pit struct so just cast it and use it */
 | 
			
		||||
        kvm_get_pit(kvm_state, (struct kvm_pit_state *)&pit2);
 | 
			
		||||
    }
 | 
			
		||||
    for (i = 0; i < 3; i++) {
 | 
			
		||||
	c = &pit2.channels[i];
 | 
			
		||||
	sc = &s->channels[i];
 | 
			
		||||
	sc->count = c->count;
 | 
			
		||||
	sc->latched_count = c->latched_count;
 | 
			
		||||
	sc->count_latched = c->count_latched;
 | 
			
		||||
	sc->status_latched = c->status_latched;
 | 
			
		||||
	sc->status = c->status;
 | 
			
		||||
	sc->read_state = c->read_state;
 | 
			
		||||
	sc->write_state = c->write_state;
 | 
			
		||||
	sc->write_latch = c->write_latch;
 | 
			
		||||
	sc->rw_mode = c->rw_mode;
 | 
			
		||||
	sc->mode = c->mode;
 | 
			
		||||
	sc->bcd = c->bcd;
 | 
			
		||||
	sc->gate = c->gate;
 | 
			
		||||
	sc->count_load_time = c->count_load_time;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int kvm_pit_post_load(void *opaque, int version_id)
 | 
			
		||||
{
 | 
			
		||||
    PITState *s = opaque;
 | 
			
		||||
    struct kvm_pit_state2 pit2;
 | 
			
		||||
    struct kvm_pit_channel_state *c;
 | 
			
		||||
    struct PITChannelState *sc;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    pit2.flags = s->flags;
 | 
			
		||||
    for (i = 0; i < 3; i++) {
 | 
			
		||||
	c = &pit2.channels[i];
 | 
			
		||||
	sc = &s->channels[i];
 | 
			
		||||
	c->count = sc->count;
 | 
			
		||||
	c->latched_count = sc->latched_count;
 | 
			
		||||
	c->count_latched = sc->count_latched;
 | 
			
		||||
	c->status_latched = sc->status_latched;
 | 
			
		||||
	c->status = sc->status;
 | 
			
		||||
	c->read_state = sc->read_state;
 | 
			
		||||
	c->write_state = sc->write_state;
 | 
			
		||||
	c->write_latch = sc->write_latch;
 | 
			
		||||
	c->rw_mode = sc->rw_mode;
 | 
			
		||||
	c->mode = sc->mode;
 | 
			
		||||
	c->bcd = sc->bcd;
 | 
			
		||||
	c->gate = sc->gate;
 | 
			
		||||
	c->count_load_time = sc->count_load_time;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (kvm_has_pit_state2()) {
 | 
			
		||||
        kvm_set_pit2(kvm_state, &pit2);
 | 
			
		||||
    } else {
 | 
			
		||||
        kvm_set_pit(kvm_state, (struct kvm_pit_state *)&pit2);
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void dummy_timer(void *opaque)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void kvm_pit_init(PITState *pit)
 | 
			
		||||
{
 | 
			
		||||
    PITChannelState *s;
 | 
			
		||||
 | 
			
		||||
    s = &pit->channels[0];
 | 
			
		||||
    s->irq_timer = qemu_new_timer_ns(vm_clock, dummy_timer, s);
 | 
			
		||||
    vmstate_pit.pre_save = kvm_pit_pre_save;
 | 
			
		||||
    vmstate_pit.post_load = kvm_pit_post_load;
 | 
			
		||||
    return;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										146
									
								
								hw/i8254.c
									
									
									
									
									
								
							
							
						
						
									
										146
									
								
								hw/i8254.c
									
									
									
									
									
								
							@@ -25,41 +25,11 @@
 | 
			
		||||
#include "pc.h"
 | 
			
		||||
#include "isa.h"
 | 
			
		||||
#include "qemu-timer.h"
 | 
			
		||||
#include "kvm.h"
 | 
			
		||||
#include "i8254.h"
 | 
			
		||||
 | 
			
		||||
//#define DEBUG_PIT
 | 
			
		||||
 | 
			
		||||
#define RW_STATE_LSB 1
 | 
			
		||||
#define RW_STATE_MSB 2
 | 
			
		||||
#define RW_STATE_WORD0 3
 | 
			
		||||
#define RW_STATE_WORD1 4
 | 
			
		||||
 | 
			
		||||
typedef struct PITChannelState {
 | 
			
		||||
    int count; /* can be 65536 */
 | 
			
		||||
    uint16_t latched_count;
 | 
			
		||||
    uint8_t count_latched;
 | 
			
		||||
    uint8_t status_latched;
 | 
			
		||||
    uint8_t status;
 | 
			
		||||
    uint8_t read_state;
 | 
			
		||||
    uint8_t write_state;
 | 
			
		||||
    uint8_t write_latch;
 | 
			
		||||
    uint8_t rw_mode;
 | 
			
		||||
    uint8_t mode;
 | 
			
		||||
    uint8_t bcd; /* not supported */
 | 
			
		||||
    uint8_t gate; /* timer start */
 | 
			
		||||
    int64_t count_load_time;
 | 
			
		||||
    /* irq handling */
 | 
			
		||||
    int64_t next_transition_time;
 | 
			
		||||
    QEMUTimer *irq_timer;
 | 
			
		||||
    qemu_irq irq;
 | 
			
		||||
} PITChannelState;
 | 
			
		||||
 | 
			
		||||
typedef struct PITState {
 | 
			
		||||
    ISADevice dev;
 | 
			
		||||
    uint32_t irq;
 | 
			
		||||
    uint32_t iobase;
 | 
			
		||||
    PITChannelState channels[3];
 | 
			
		||||
} PITState;
 | 
			
		||||
 | 
			
		||||
static PITState pit_state;
 | 
			
		||||
 | 
			
		||||
static void pit_irq_timer_update(PITChannelState *s, int64_t current_time);
 | 
			
		||||
@@ -236,13 +206,18 @@ int pit_get_mode(ISADevice *dev, int channel)
 | 
			
		||||
    return s->mode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void pit_load_count(PITChannelState *s, int val)
 | 
			
		||||
static inline void pit_load_count(PITState *s, int val, int chan)
 | 
			
		||||
{
 | 
			
		||||
    if (val == 0)
 | 
			
		||||
        val = 0x10000;
 | 
			
		||||
    s->count_load_time = qemu_get_clock_ns(vm_clock);
 | 
			
		||||
    s->count = val;
 | 
			
		||||
    pit_irq_timer_update(s, s->count_load_time);
 | 
			
		||||
    s->channels[chan].count_load_time = qemu_get_clock_ns(vm_clock);
 | 
			
		||||
    s->channels[chan].count = val;
 | 
			
		||||
#ifdef TARGET_I386
 | 
			
		||||
    if (chan == 0 && pit_state.flags & PIT_FLAGS_HPET_LEGACY) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    pit_irq_timer_update(&s->channels[chan], s->channels[chan].count_load_time);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* if already latched, do not latch again */
 | 
			
		||||
@@ -302,17 +277,17 @@ static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 | 
			
		||||
        switch(s->write_state) {
 | 
			
		||||
        default:
 | 
			
		||||
        case RW_STATE_LSB:
 | 
			
		||||
            pit_load_count(s, val);
 | 
			
		||||
            pit_load_count(pit, val, addr);
 | 
			
		||||
            break;
 | 
			
		||||
        case RW_STATE_MSB:
 | 
			
		||||
            pit_load_count(s, val << 8);
 | 
			
		||||
            pit_load_count(pit, val << 8, addr);
 | 
			
		||||
            break;
 | 
			
		||||
        case RW_STATE_WORD0:
 | 
			
		||||
            s->write_latch = val;
 | 
			
		||||
            s->write_state = RW_STATE_WORD1;
 | 
			
		||||
            break;
 | 
			
		||||
        case RW_STATE_WORD1:
 | 
			
		||||
            pit_load_count(s, s->write_latch | (val << 8));
 | 
			
		||||
            pit_load_count(pit, s->write_latch | (val << 8), addr);
 | 
			
		||||
            s->write_state = RW_STATE_WORD0;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
@@ -372,6 +347,11 @@ static uint32_t pit_ioport_read(void *opaque, uint32_t addr)
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* global counters for time-drift fix */
 | 
			
		||||
int64_t timer_acks=0, timer_interrupts=0, timer_ints_to_push=0;
 | 
			
		||||
 | 
			
		||||
extern int time_drift_fix;
 | 
			
		||||
 | 
			
		||||
static void pit_irq_timer_update(PITChannelState *s, int64_t current_time)
 | 
			
		||||
{
 | 
			
		||||
    int64_t expire_time;
 | 
			
		||||
@@ -382,16 +362,35 @@ static void pit_irq_timer_update(PITChannelState *s, int64_t current_time)
 | 
			
		||||
    expire_time = pit_get_next_transition_time(s, current_time);
 | 
			
		||||
    irq_level = pit_get_out1(s, current_time);
 | 
			
		||||
    qemu_set_irq(s->irq, irq_level);
 | 
			
		||||
    if (time_drift_fix && irq_level==1) {
 | 
			
		||||
        /* FIXME: fine tune timer_max_fix (max fix per tick). 
 | 
			
		||||
         *        Should it be 1 (double time), 2 , 4, 10 ? 
 | 
			
		||||
         *        Currently setting it to 5% of PIT-ticks-per-second (per PIT-tick)
 | 
			
		||||
         */
 | 
			
		||||
        const long pit_ticks_per_sec = (s->count>0) ? (PIT_FREQ/s->count) : 0;
 | 
			
		||||
        const long timer_max_fix = pit_ticks_per_sec/20;
 | 
			
		||||
        const long delta = timer_interrupts - timer_acks;
 | 
			
		||||
        const long max_delta = pit_ticks_per_sec * 60; /* one minute */
 | 
			
		||||
        if ((delta >  max_delta) && (pit_ticks_per_sec > 0)) {
 | 
			
		||||
            printf("time drift is too long, %ld seconds were lost\n", delta/pit_ticks_per_sec);
 | 
			
		||||
            timer_acks = timer_interrupts;
 | 
			
		||||
            timer_ints_to_push = 0;
 | 
			
		||||
        } else if (delta > 0) {
 | 
			
		||||
            timer_ints_to_push = MIN(delta, timer_max_fix);
 | 
			
		||||
        }
 | 
			
		||||
        timer_interrupts++;
 | 
			
		||||
    }
 | 
			
		||||
#ifdef DEBUG_PIT
 | 
			
		||||
    printf("irq_level=%d next_delay=%f\n",
 | 
			
		||||
           irq_level,
 | 
			
		||||
           (double)(expire_time - current_time) / get_ticks_per_sec());
 | 
			
		||||
#endif
 | 
			
		||||
    s->next_transition_time = expire_time;
 | 
			
		||||
    if (expire_time != -1)
 | 
			
		||||
    if (expire_time != -1) {
 | 
			
		||||
        qemu_mod_timer(s->irq_timer, expire_time);
 | 
			
		||||
    else
 | 
			
		||||
    } else {
 | 
			
		||||
        qemu_del_timer(s->irq_timer);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pit_irq_timer(void *opaque)
 | 
			
		||||
@@ -431,9 +430,10 @@ static int pit_load_old(QEMUFile *f, void *opaque, int version_id)
 | 
			
		||||
    PITChannelState *s;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    if (version_id != 1)
 | 
			
		||||
    if (version_id != PIT_SAVEVM_VERSION)
 | 
			
		||||
        return -EINVAL;
 | 
			
		||||
 | 
			
		||||
    pit->flags = qemu_get_be32(f);
 | 
			
		||||
    for(i = 0; i < 3; i++) {
 | 
			
		||||
        s = &pit->channels[i];
 | 
			
		||||
        s->count=qemu_get_be32(f);
 | 
			
		||||
@@ -454,16 +454,18 @@ static int pit_load_old(QEMUFile *f, void *opaque, int version_id)
 | 
			
		||||
            qemu_get_timer(f, s->irq_timer);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const VMStateDescription vmstate_pit = {
 | 
			
		||||
VMStateDescription vmstate_pit = {
 | 
			
		||||
    .name = "i8254",
 | 
			
		||||
    .version_id = 2,
 | 
			
		||||
    .minimum_version_id = 2,
 | 
			
		||||
    .minimum_version_id_old = 1,
 | 
			
		||||
    .load_state_old = pit_load_old,
 | 
			
		||||
    .fields      = (VMStateField []) {
 | 
			
		||||
        VMSTATE_UINT32(flags, PITState),
 | 
			
		||||
        VMSTATE_STRUCT_ARRAY(channels, PITState, 3, 2, vmstate_pit_channel, PITChannelState),
 | 
			
		||||
        VMSTATE_TIMER(channels[0].irq_timer, PITState),
 | 
			
		||||
        VMSTATE_END_OF_LIST()
 | 
			
		||||
@@ -476,20 +478,40 @@ static void pit_reset(DeviceState *dev)
 | 
			
		||||
    PITChannelState *s;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
#ifdef TARGET_I386
 | 
			
		||||
    pit->flags &= ~PIT_FLAGS_HPET_LEGACY;
 | 
			
		||||
#endif
 | 
			
		||||
    for(i = 0;i < 3; i++) {
 | 
			
		||||
        s = &pit->channels[i];
 | 
			
		||||
        s->mode = 3;
 | 
			
		||||
        s->gate = (i != 2);
 | 
			
		||||
        pit_load_count(s, 0);
 | 
			
		||||
        pit_load_count(pit, 0, i);
 | 
			
		||||
    }
 | 
			
		||||
    if (vmstate_pit.post_load) {
 | 
			
		||||
        vmstate_pit.post_load(pit, 2);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef TARGET_I386
 | 
			
		||||
/* When HPET is operating in legacy mode, i8254 timer0 is disabled */
 | 
			
		||||
void hpet_pit_disable(void) {
 | 
			
		||||
    PITChannelState *s;
 | 
			
		||||
    s = &pit_state.channels[0];
 | 
			
		||||
    if (s->irq_timer)
 | 
			
		||||
 | 
			
		||||
void hpet_pit_disable(void)
 | 
			
		||||
{
 | 
			
		||||
    PITChannelState *s = &pit_state.channels[0];
 | 
			
		||||
 | 
			
		||||
    if (kvm_enabled() && kvm_pit_in_kernel()) {
 | 
			
		||||
        if (kvm_has_pit_state2()) {
 | 
			
		||||
            kvm_hpet_disable_kpit();
 | 
			
		||||
        } else {
 | 
			
		||||
             fprintf(stderr, "%s: kvm does not support pit_state2!\n", __FUNCTION__);
 | 
			
		||||
             exit(1);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        pit_state.flags |= PIT_FLAGS_HPET_LEGACY;
 | 
			
		||||
        if (s->irq_timer) {
 | 
			
		||||
            qemu_del_timer(s->irq_timer);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* When HPET is reset or leaving legacy mode, it must reenable i8254
 | 
			
		||||
@@ -499,18 +521,33 @@ void hpet_pit_disable(void) {
 | 
			
		||||
void hpet_pit_enable(void)
 | 
			
		||||
{
 | 
			
		||||
    PITState *pit = &pit_state;
 | 
			
		||||
    PITChannelState *s;
 | 
			
		||||
    s = &pit->channels[0];
 | 
			
		||||
    s->mode = 3;
 | 
			
		||||
    s->gate = 1;
 | 
			
		||||
    pit_load_count(s, 0);
 | 
			
		||||
    PITChannelState *s = &pit->channels[0];
 | 
			
		||||
 | 
			
		||||
    if (kvm_enabled() && kvm_pit_in_kernel()) {
 | 
			
		||||
        if (kvm_has_pit_state2()) {
 | 
			
		||||
            kvm_hpet_enable_kpit();
 | 
			
		||||
        } else {
 | 
			
		||||
             fprintf(stderr, "%s: kvm does not support pit_state2!\n", __FUNCTION__);
 | 
			
		||||
             exit(1);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        pit_state.flags &= ~PIT_FLAGS_HPET_LEGACY;
 | 
			
		||||
        pit_load_count(pit, s->count, 0);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static int pit_initfn(ISADevice *dev)
 | 
			
		||||
{
 | 
			
		||||
    PITState *pit = DO_UPCAST(PITState, dev, dev);
 | 
			
		||||
    PITChannelState *s;
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_KVM_PIT
 | 
			
		||||
    if (kvm_enabled() && kvm_pit_in_kernel())
 | 
			
		||||
        kvm_pit_init(pit);
 | 
			
		||||
    else {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    s = &pit->channels[0];
 | 
			
		||||
    /* the timer 0 is connected to an IRQ */
 | 
			
		||||
    s->irq_timer = qemu_new_timer_ns(vm_clock, pit_irq_timer, s);
 | 
			
		||||
@@ -520,6 +557,9 @@ static int pit_initfn(ISADevice *dev)
 | 
			
		||||
    register_ioport_read(pit->iobase, 3, 1, pit_ioport_read, pit);
 | 
			
		||||
    isa_init_ioport(dev, pit->iobase);
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_KVM_PIT
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    qdev_set_legacy_instance_id(&dev->qdev, pit->iobase, 2);
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										75
									
								
								hw/i8254.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								hw/i8254.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
			
		||||
/*
 | 
			
		||||
 * QEMU 8253/8254 interval timer emulation
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2003-2004 Fabrice Bellard
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 * in the Software without restriction, including without limitation the rights
 | 
			
		||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
 * furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 | 
			
		||||
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef QEMU_I8254_H
 | 
			
		||||
#define QEMU_I8254_H
 | 
			
		||||
 | 
			
		||||
#define PIT_SAVEVM_NAME "i8254"
 | 
			
		||||
#define PIT_SAVEVM_VERSION 2
 | 
			
		||||
 | 
			
		||||
#define RW_STATE_LSB 1
 | 
			
		||||
#define RW_STATE_MSB 2
 | 
			
		||||
#define RW_STATE_WORD0 3
 | 
			
		||||
#define RW_STATE_WORD1 4
 | 
			
		||||
 | 
			
		||||
#define PIT_FLAGS_HPET_LEGACY  1
 | 
			
		||||
 | 
			
		||||
typedef struct PITChannelState {
 | 
			
		||||
    int count; /* can be 65536 */
 | 
			
		||||
    uint16_t latched_count;
 | 
			
		||||
    uint8_t count_latched;
 | 
			
		||||
    uint8_t status_latched;
 | 
			
		||||
    uint8_t status;
 | 
			
		||||
    uint8_t read_state;
 | 
			
		||||
    uint8_t write_state;
 | 
			
		||||
    uint8_t write_latch;
 | 
			
		||||
    uint8_t rw_mode;
 | 
			
		||||
    uint8_t mode;
 | 
			
		||||
    uint8_t bcd; /* not supported */
 | 
			
		||||
    uint8_t gate; /* timer start */
 | 
			
		||||
    int64_t count_load_time;
 | 
			
		||||
    /* irq handling */
 | 
			
		||||
    int64_t next_transition_time;
 | 
			
		||||
    QEMUTimer *irq_timer;
 | 
			
		||||
    qemu_irq irq;
 | 
			
		||||
} PITChannelState;
 | 
			
		||||
 | 
			
		||||
struct PITState {
 | 
			
		||||
    ISADevice dev;
 | 
			
		||||
    uint32_t irq;
 | 
			
		||||
    uint32_t iobase;
 | 
			
		||||
    PITChannelState channels[3];
 | 
			
		||||
    uint32_t flags;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void pit_save(QEMUFile *f, void *opaque);
 | 
			
		||||
 | 
			
		||||
int pit_load(QEMUFile *f, void *opaque, int version_id);
 | 
			
		||||
 | 
			
		||||
typedef struct PITState PITState;
 | 
			
		||||
 | 
			
		||||
/* i8254-kvm.c */
 | 
			
		||||
void kvm_pit_init(PITState *pit);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										145
									
								
								hw/i8259.c
									
									
									
									
									
								
							
							
						
						
									
										145
									
								
								hw/i8259.c
									
									
									
									
									
								
							@@ -27,6 +27,8 @@
 | 
			
		||||
#include "monitor.h"
 | 
			
		||||
#include "qemu-timer.h"
 | 
			
		||||
 | 
			
		||||
#include "kvm.h"
 | 
			
		||||
 | 
			
		||||
/* debug PIC */
 | 
			
		||||
//#define DEBUG_PIC
 | 
			
		||||
 | 
			
		||||
@@ -223,6 +225,9 @@ static inline void pic_intack(PicState *s, int irq)
 | 
			
		||||
        s->irr &= ~(1 << irq);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern int time_drift_fix;
 | 
			
		||||
extern int64_t timer_acks, timer_ints_to_push;
 | 
			
		||||
 | 
			
		||||
int pic_read_irq(PicState2 *s)
 | 
			
		||||
{
 | 
			
		||||
    int irq, irq2, intno;
 | 
			
		||||
@@ -230,6 +235,17 @@ int pic_read_irq(PicState2 *s)
 | 
			
		||||
    irq = pic_get_irq(&s->pics[0]);
 | 
			
		||||
    if (irq >= 0) {
 | 
			
		||||
        pic_intack(&s->pics[0], irq);
 | 
			
		||||
#ifdef TARGET_I386
 | 
			
		||||
	if (time_drift_fix && irq == 0) {
 | 
			
		||||
	    timer_acks++;
 | 
			
		||||
	    if (timer_ints_to_push > 0) {
 | 
			
		||||
		timer_ints_to_push--;
 | 
			
		||||
                /* simulate an edge irq0, like the one generated by i8254 */
 | 
			
		||||
                pic_set_irq1(&s->pics[0], 0, 0);
 | 
			
		||||
                pic_set_irq1(&s->pics[0], 0, 1);
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
        if (irq == 2) {
 | 
			
		||||
            irq2 = pic_get_irq(&s->pics[1]);
 | 
			
		||||
            if (irq2 >= 0) {
 | 
			
		||||
@@ -262,6 +278,8 @@ int pic_read_irq(PicState2 *s)
 | 
			
		||||
    return intno;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int kvm_kernel_pic_load_from_user(PicState *s);
 | 
			
		||||
 | 
			
		||||
static void pic_reset(void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    PicState *s = opaque;
 | 
			
		||||
@@ -282,6 +300,10 @@ static void pic_reset(void *opaque)
 | 
			
		||||
    s->init4 = 0;
 | 
			
		||||
    s->single_mode = 0;
 | 
			
		||||
    /* Note: ELCR is not reset */
 | 
			
		||||
 | 
			
		||||
    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
 | 
			
		||||
        kvm_kernel_pic_load_from_user(s);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 | 
			
		||||
@@ -448,9 +470,32 @@ static uint32_t elcr_ioport_read(void *opaque, uint32_t addr1)
 | 
			
		||||
    return s->elcr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void kvm_kernel_pic_save_to_user(PicState *s);
 | 
			
		||||
 | 
			
		||||
static void pic_pre_save(void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    PicState *s = opaque;
 | 
			
		||||
 | 
			
		||||
    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
 | 
			
		||||
        kvm_kernel_pic_save_to_user(s);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int pic_post_load(void *opaque, int version_id)
 | 
			
		||||
{
 | 
			
		||||
    PicState *s = opaque;
 | 
			
		||||
 | 
			
		||||
    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
 | 
			
		||||
        kvm_kernel_pic_load_from_user(s);
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const VMStateDescription vmstate_pic = {
 | 
			
		||||
    .name = "i8259",
 | 
			
		||||
    .version_id = 1,
 | 
			
		||||
    .pre_save = pic_pre_save,
 | 
			
		||||
    .post_load = pic_post_load,
 | 
			
		||||
    .minimum_version_id = 1,
 | 
			
		||||
    .minimum_version_id_old = 1,
 | 
			
		||||
    .fields      = (VMStateField []) {
 | 
			
		||||
@@ -537,3 +582,103 @@ qemu_irq *i8259_init(qemu_irq parent_irq)
 | 
			
		||||
    isa_pic = s;
 | 
			
		||||
    return qemu_allocate_irqs(i8259_set_irq, s, 16);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void kvm_kernel_pic_save_to_user(PicState *s)
 | 
			
		||||
{
 | 
			
		||||
#ifdef KVM_CAP_IRQCHIP
 | 
			
		||||
    struct kvm_irqchip chip;
 | 
			
		||||
    struct kvm_pic_state *kpic;
 | 
			
		||||
 | 
			
		||||
    chip.chip_id = (&s->pics_state->pics[0] == s) ?
 | 
			
		||||
                   KVM_IRQCHIP_PIC_MASTER :
 | 
			
		||||
                   KVM_IRQCHIP_PIC_SLAVE;
 | 
			
		||||
    kvm_get_irqchip(kvm_state, &chip);
 | 
			
		||||
    kpic = &chip.chip.pic;
 | 
			
		||||
 | 
			
		||||
    s->last_irr = kpic->last_irr;
 | 
			
		||||
    s->irr = kpic->irr;
 | 
			
		||||
    s->imr = kpic->imr;
 | 
			
		||||
    s->isr = kpic->isr;
 | 
			
		||||
    s->priority_add = kpic->priority_add;
 | 
			
		||||
    s->irq_base = kpic->irq_base;
 | 
			
		||||
    s->read_reg_select = kpic->read_reg_select;
 | 
			
		||||
    s->poll = kpic->poll;
 | 
			
		||||
    s->special_mask = kpic->special_mask;
 | 
			
		||||
    s->init_state = kpic->init_state;
 | 
			
		||||
    s->auto_eoi = kpic->auto_eoi;
 | 
			
		||||
    s->rotate_on_auto_eoi = kpic->rotate_on_auto_eoi;
 | 
			
		||||
    s->special_fully_nested_mode = kpic->special_fully_nested_mode;
 | 
			
		||||
    s->init4 = kpic->init4;
 | 
			
		||||
    s->elcr = kpic->elcr;
 | 
			
		||||
    s->elcr_mask = kpic->elcr_mask;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int kvm_kernel_pic_load_from_user(PicState *s)
 | 
			
		||||
{
 | 
			
		||||
#ifdef KVM_CAP_IRQCHIP
 | 
			
		||||
    struct kvm_irqchip chip;
 | 
			
		||||
    struct kvm_pic_state *kpic;
 | 
			
		||||
 | 
			
		||||
    chip.chip_id = (&s->pics_state->pics[0] == s) ?
 | 
			
		||||
                   KVM_IRQCHIP_PIC_MASTER :
 | 
			
		||||
                   KVM_IRQCHIP_PIC_SLAVE;
 | 
			
		||||
    kpic = &chip.chip.pic;
 | 
			
		||||
 | 
			
		||||
    kpic->last_irr = s->last_irr;
 | 
			
		||||
    kpic->irr = s->irr;
 | 
			
		||||
    kpic->imr = s->imr;
 | 
			
		||||
    kpic->isr = s->isr;
 | 
			
		||||
    kpic->priority_add = s->priority_add;
 | 
			
		||||
    kpic->irq_base = s->irq_base;
 | 
			
		||||
    kpic->read_reg_select = s->read_reg_select;
 | 
			
		||||
    kpic->poll = s->poll;
 | 
			
		||||
    kpic->special_mask = s->special_mask;
 | 
			
		||||
    kpic->init_state = s->init_state;
 | 
			
		||||
    kpic->auto_eoi = s->auto_eoi;
 | 
			
		||||
    kpic->rotate_on_auto_eoi = s->rotate_on_auto_eoi;
 | 
			
		||||
    kpic->special_fully_nested_mode = s->special_fully_nested_mode;
 | 
			
		||||
    kpic->init4 = s->init4;
 | 
			
		||||
    kpic->elcr = s->elcr;
 | 
			
		||||
    kpic->elcr_mask = s->elcr_mask;
 | 
			
		||||
 | 
			
		||||
    kvm_set_irqchip(kvm_state, &chip);
 | 
			
		||||
#endif
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef KVM_CAP_IRQCHIP
 | 
			
		||||
static void kvm_i8259_set_irq(void *opaque, int irq, int level)
 | 
			
		||||
{
 | 
			
		||||
    int pic_ret;
 | 
			
		||||
    if (kvm_set_irq(irq, level, &pic_ret)) {
 | 
			
		||||
        if (pic_ret != 0)
 | 
			
		||||
            apic_set_irq_delivered();
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void kvm_pic_init1(int io_addr, PicState *s)
 | 
			
		||||
{
 | 
			
		||||
    vmstate_register(NULL, io_addr, &vmstate_pic, s);
 | 
			
		||||
    qemu_register_reset(pic_reset, s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
qemu_irq *kvm_i8259_init(qemu_irq parent_irq)
 | 
			
		||||
{
 | 
			
		||||
    PicState2 *s;
 | 
			
		||||
 | 
			
		||||
    s = qemu_mallocz(sizeof(PicState2));
 | 
			
		||||
 | 
			
		||||
    kvm_pic_init1(0x20, &s->pics[0]);
 | 
			
		||||
    kvm_pic_init1(0xa0, &s->pics[1]);
 | 
			
		||||
    s->parent_irq = parent_irq;
 | 
			
		||||
    s->pics[0].pics_state = s;
 | 
			
		||||
    s->pics[1].pics_state = s;
 | 
			
		||||
    isa_pic = s;
 | 
			
		||||
    return qemu_allocate_irqs(kvm_i8259_set_irq, s, 24);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										66
									
								
								hw/ioapic.c
									
									
									
									
									
								
							
							
						
						
									
										66
									
								
								hw/ioapic.c
									
									
									
									
									
								
							@@ -28,6 +28,8 @@
 | 
			
		||||
#include "host-utils.h"
 | 
			
		||||
#include "sysbus.h"
 | 
			
		||||
 | 
			
		||||
#include "kvm.h"
 | 
			
		||||
 | 
			
		||||
//#define DEBUG_IOAPIC
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG_IOAPIC
 | 
			
		||||
@@ -268,6 +270,57 @@ ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void kvm_kernel_ioapic_save_to_user(IOAPICState *s)
 | 
			
		||||
{
 | 
			
		||||
#if defined(KVM_CAP_IRQCHIP) && defined(TARGET_I386)
 | 
			
		||||
    struct kvm_irqchip chip;
 | 
			
		||||
    struct kvm_ioapic_state *kioapic;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    chip.chip_id = KVM_IRQCHIP_IOAPIC;
 | 
			
		||||
    kvm_get_irqchip(kvm_state, &chip);
 | 
			
		||||
    kioapic = &chip.chip.ioapic;
 | 
			
		||||
 | 
			
		||||
    s->id = kioapic->id;
 | 
			
		||||
    s->ioregsel = kioapic->ioregsel;
 | 
			
		||||
    s->irr = kioapic->irr;
 | 
			
		||||
    for (i = 0; i < IOAPIC_NUM_PINS; i++) {
 | 
			
		||||
        s->ioredtbl[i] = kioapic->redirtbl[i].bits;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void kvm_kernel_ioapic_load_from_user(IOAPICState *s)
 | 
			
		||||
{
 | 
			
		||||
#if defined(KVM_CAP_IRQCHIP) && defined(TARGET_I386)
 | 
			
		||||
    struct kvm_irqchip chip;
 | 
			
		||||
    struct kvm_ioapic_state *kioapic;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    chip.chip_id = KVM_IRQCHIP_IOAPIC;
 | 
			
		||||
    kioapic = &chip.chip.ioapic;
 | 
			
		||||
 | 
			
		||||
    kioapic->id = s->id;
 | 
			
		||||
    kioapic->ioregsel = s->ioregsel;
 | 
			
		||||
    kioapic->base_address = s->busdev.mmio[0].addr;
 | 
			
		||||
    kioapic->irr = s->irr;
 | 
			
		||||
    for (i = 0; i < IOAPIC_NUM_PINS; i++) {
 | 
			
		||||
        kioapic->redirtbl[i].bits = s->ioredtbl[i];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    kvm_set_irqchip(kvm_state, &chip);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ioapic_pre_save(void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    IOAPICState *s = (void *)opaque;
 | 
			
		||||
 | 
			
		||||
    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
 | 
			
		||||
        kvm_kernel_ioapic_save_to_user(s);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int ioapic_post_load(void *opaque, int version_id)
 | 
			
		||||
{
 | 
			
		||||
    IOAPICState *s = opaque;
 | 
			
		||||
@@ -276,15 +329,21 @@ static int ioapic_post_load(void *opaque, int version_id)
 | 
			
		||||
        /* set sane value */
 | 
			
		||||
        s->irr = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
 | 
			
		||||
        kvm_kernel_ioapic_load_from_user(s);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const VMStateDescription vmstate_ioapic = {
 | 
			
		||||
    .name = "ioapic",
 | 
			
		||||
    .version_id = 3,
 | 
			
		||||
    .post_load = ioapic_post_load,
 | 
			
		||||
    .minimum_version_id = 1,
 | 
			
		||||
    .minimum_version_id_old = 1,
 | 
			
		||||
    .post_load = ioapic_post_load,
 | 
			
		||||
    .pre_save = ioapic_pre_save,
 | 
			
		||||
    .fields = (VMStateField[]) {
 | 
			
		||||
        VMSTATE_UINT8(id, IOAPICState),
 | 
			
		||||
        VMSTATE_UINT8(ioregsel, IOAPICState),
 | 
			
		||||
@@ -306,6 +365,11 @@ static void ioapic_reset(DeviceState *d)
 | 
			
		||||
    for (i = 0; i < IOAPIC_NUM_PINS; i++) {
 | 
			
		||||
        s->ioredtbl[i] = 1 << IOAPIC_LVT_MASKED_SHIFT;
 | 
			
		||||
    }
 | 
			
		||||
#ifdef KVM_CAP_IRQCHIP
 | 
			
		||||
    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
 | 
			
		||||
        kvm_kernel_ioapic_load_from_user(s);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static CPUReadMemoryFunc * const ioapic_mem_read[3] = {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										707
									
								
								hw/ipf.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										707
									
								
								hw/ipf.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,707 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Itanium Platform Emulator derived from QEMU PC System Emulator
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2003-2004 Fabrice Bellard
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 2007 Intel
 | 
			
		||||
 * Ported for IA64 Platform Zhang Xiantao <xiantao.zhang@intel.com>
 | 
			
		||||
 *
 | 
			
		||||
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
 * of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 * in the Software without restriction, including without limitation the rights
 | 
			
		||||
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
 * copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
 * furnished to do so, subject to the following conditions:
 | 
			
		||||
 *
 | 
			
		||||
 * The above copyright notice and this permission notice shall be included in
 | 
			
		||||
 * all copies or substantial portions of the Software.
 | 
			
		||||
 *
 | 
			
		||||
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 | 
			
		||||
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
 * THE SOFTWARE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "hw.h"
 | 
			
		||||
#include "pc.h"
 | 
			
		||||
#include "fdc.h"
 | 
			
		||||
#include "pci.h"
 | 
			
		||||
#include "block.h"
 | 
			
		||||
#include "sysemu.h"
 | 
			
		||||
#include "audio/audio.h"
 | 
			
		||||
#include "net.h"
 | 
			
		||||
#include "smbus.h"
 | 
			
		||||
#include "boards.h"
 | 
			
		||||
#include "firmware.h"
 | 
			
		||||
#include "ia64intrin.h"
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include "device-assignment.h"
 | 
			
		||||
#include "virtio-blk.h"
 | 
			
		||||
 | 
			
		||||
#include "qemu-kvm.h"
 | 
			
		||||
 | 
			
		||||
#define FW_FILENAME "Flash.fd"
 | 
			
		||||
 | 
			
		||||
/* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables.  */
 | 
			
		||||
#define ACPI_DATA_SIZE       0x10000
 | 
			
		||||
 | 
			
		||||
#define MAX_IDE_BUS 2
 | 
			
		||||
 | 
			
		||||
static fdctrl_t *floppy_controller;
 | 
			
		||||
static RTCState *rtc_state;
 | 
			
		||||
static PCIDevice *i440fx_state;
 | 
			
		||||
 | 
			
		||||
static uint32_t ipf_to_legacy_io(target_phys_addr_t addr)
 | 
			
		||||
{
 | 
			
		||||
    return (uint32_t)(((addr&0x3ffffff) >> 12 << 2)|((addr) & 0x3));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ipf_legacy_io_writeb(void *opaque, target_phys_addr_t addr,
 | 
			
		||||
				 uint32_t val) {
 | 
			
		||||
    uint32_t port = ipf_to_legacy_io(addr);
 | 
			
		||||
 | 
			
		||||
    cpu_outb(0, port, val);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ipf_legacy_io_writew(void *opaque, target_phys_addr_t addr,
 | 
			
		||||
				 uint32_t val) {
 | 
			
		||||
    uint32_t port = ipf_to_legacy_io(addr);
 | 
			
		||||
 | 
			
		||||
    cpu_outw(0, port, val);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ipf_legacy_io_writel(void *opaque, target_phys_addr_t addr,
 | 
			
		||||
				 uint32_t val) {
 | 
			
		||||
    uint32_t port = ipf_to_legacy_io(addr);
 | 
			
		||||
 | 
			
		||||
    cpu_outl(0, port, val);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t ipf_legacy_io_readb(void *opaque, target_phys_addr_t addr)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t port = ipf_to_legacy_io(addr);
 | 
			
		||||
 | 
			
		||||
    return cpu_inb(0, port);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t ipf_legacy_io_readw(void *opaque, target_phys_addr_t addr)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t port = ipf_to_legacy_io(addr);
 | 
			
		||||
 | 
			
		||||
    return cpu_inw(0, port);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t ipf_legacy_io_readl(void *opaque, target_phys_addr_t addr)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t port = ipf_to_legacy_io(addr);
 | 
			
		||||
 | 
			
		||||
    return cpu_inl(0, port);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static CPUReadMemoryFunc *ipf_legacy_io_read[3] = {
 | 
			
		||||
    ipf_legacy_io_readb,
 | 
			
		||||
    ipf_legacy_io_readw,
 | 
			
		||||
    ipf_legacy_io_readl,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static CPUWriteMemoryFunc *ipf_legacy_io_write[3] = {
 | 
			
		||||
    ipf_legacy_io_writeb,
 | 
			
		||||
    ipf_legacy_io_writew,
 | 
			
		||||
    ipf_legacy_io_writel,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void pic_irq_request(void *opaque, int irq, int level)
 | 
			
		||||
{
 | 
			
		||||
    fprintf(stderr,"pic_irq_request called!\n");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* PC cmos mappings */
 | 
			
		||||
 | 
			
		||||
#define REG_EQUIPMENT_BYTE          0x14
 | 
			
		||||
 | 
			
		||||
static int cmos_get_fd_drive_type(int fd0)
 | 
			
		||||
{
 | 
			
		||||
    int val;
 | 
			
		||||
 | 
			
		||||
    switch (fd0) {
 | 
			
		||||
    case 0:
 | 
			
		||||
        /* 1.44 Mb 3"5 drive */
 | 
			
		||||
        val = 4;
 | 
			
		||||
        break;
 | 
			
		||||
    case 1:
 | 
			
		||||
        /* 2.88 Mb 3"5 drive */
 | 
			
		||||
        val = 5;
 | 
			
		||||
        break;
 | 
			
		||||
    case 2:
 | 
			
		||||
        /* 1.2 Mb 5"5 drive */
 | 
			
		||||
        val = 2;
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        val = 0;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void cmos_init_hd(int type_ofs, int info_ofs, BlockDriverState *hd)
 | 
			
		||||
{
 | 
			
		||||
    RTCState *s = rtc_state;
 | 
			
		||||
    int cylinders, heads, sectors;
 | 
			
		||||
 | 
			
		||||
    bdrv_get_geometry_hint(hd, &cylinders, &heads, §ors);
 | 
			
		||||
    rtc_set_memory(s, type_ofs, 47);
 | 
			
		||||
    rtc_set_memory(s, info_ofs, cylinders);
 | 
			
		||||
    rtc_set_memory(s, info_ofs + 1, cylinders >> 8);
 | 
			
		||||
    rtc_set_memory(s, info_ofs + 2, heads);
 | 
			
		||||
    rtc_set_memory(s, info_ofs + 3, 0xff);
 | 
			
		||||
    rtc_set_memory(s, info_ofs + 4, 0xff);
 | 
			
		||||
    rtc_set_memory(s, info_ofs + 5, 0xc0 | ((heads > 8) << 3));
 | 
			
		||||
    rtc_set_memory(s, info_ofs + 6, cylinders);
 | 
			
		||||
    rtc_set_memory(s, info_ofs + 7, cylinders >> 8);
 | 
			
		||||
    rtc_set_memory(s, info_ofs + 8, sectors);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* convert boot_device letter to something recognizable by the bios */
 | 
			
		||||
static int boot_device2nibble(char boot_device)
 | 
			
		||||
{
 | 
			
		||||
    switch(boot_device) {
 | 
			
		||||
    case 'a':
 | 
			
		||||
    case 'b':
 | 
			
		||||
        return 0x01; /* floppy boot */
 | 
			
		||||
    case 'c':
 | 
			
		||||
        return 0x02; /* hard drive boot */
 | 
			
		||||
    case 'd':
 | 
			
		||||
        return 0x03; /* CD-ROM boot */
 | 
			
		||||
    case 'n':
 | 
			
		||||
        return 0x04; /* Network boot */
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* hd_table must contain 4 block drivers */
 | 
			
		||||
static void cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
 | 
			
		||||
                      const char *boot_device, BlockDriverState **hd_table)
 | 
			
		||||
{
 | 
			
		||||
    RTCState *s = rtc_state;
 | 
			
		||||
    int nbds, bds[3] = { 0, };
 | 
			
		||||
    int val;
 | 
			
		||||
    int fd0, fd1, nb;
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    /* various important CMOS locations needed by PC/Bochs bios */
 | 
			
		||||
 | 
			
		||||
    /* memory size */
 | 
			
		||||
    val = 640; /* base memory in K */
 | 
			
		||||
    rtc_set_memory(s, 0x15, val);
 | 
			
		||||
    rtc_set_memory(s, 0x16, val >> 8);
 | 
			
		||||
 | 
			
		||||
    val = (ram_size / 1024) - 1024;
 | 
			
		||||
    if (val > 65535)
 | 
			
		||||
        val = 65535;
 | 
			
		||||
    rtc_set_memory(s, 0x17, val);
 | 
			
		||||
    rtc_set_memory(s, 0x18, val >> 8);
 | 
			
		||||
    rtc_set_memory(s, 0x30, val);
 | 
			
		||||
    rtc_set_memory(s, 0x31, val >> 8);
 | 
			
		||||
 | 
			
		||||
    if (above_4g_mem_size) {
 | 
			
		||||
        rtc_set_memory(s, 0x5b, (unsigned int)above_4g_mem_size >> 16);
 | 
			
		||||
        rtc_set_memory(s, 0x5c, (unsigned int)above_4g_mem_size >> 24);
 | 
			
		||||
        rtc_set_memory(s, 0x5d, above_4g_mem_size >> 32);
 | 
			
		||||
    }
 | 
			
		||||
    rtc_set_memory(s, 0x5f, smp_cpus - 1);
 | 
			
		||||
 | 
			
		||||
    if (ram_size > (16 * 1024 * 1024))
 | 
			
		||||
        val = (ram_size / 65536) - ((16 * 1024 * 1024) / 65536);
 | 
			
		||||
    else
 | 
			
		||||
        val = 0;
 | 
			
		||||
    if (val > 65535)
 | 
			
		||||
        val = 65535;
 | 
			
		||||
    rtc_set_memory(s, 0x34, val);
 | 
			
		||||
    rtc_set_memory(s, 0x35, val >> 8);
 | 
			
		||||
 | 
			
		||||
    /* set boot devices, and disable floppy signature check if requested */
 | 
			
		||||
#define PC_MAX_BOOT_DEVICES 3
 | 
			
		||||
    nbds = strlen(boot_device);
 | 
			
		||||
 | 
			
		||||
    if (nbds > PC_MAX_BOOT_DEVICES) {
 | 
			
		||||
        fprintf(stderr, "Too many boot devices for PC\n");
 | 
			
		||||
        exit(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < nbds; i++) {
 | 
			
		||||
        bds[i] = boot_device2nibble(boot_device[i]);
 | 
			
		||||
        if (bds[i] == 0) {
 | 
			
		||||
            fprintf(stderr, "Invalid boot device for PC: '%c'\n",
 | 
			
		||||
                    boot_device[i]);
 | 
			
		||||
            exit(1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    rtc_set_memory(s, 0x3d, (bds[1] << 4) | bds[0]);
 | 
			
		||||
    rtc_set_memory(s, 0x38, (bds[2] << 4) | (fd_bootchk ?  0x0 : 0x1));
 | 
			
		||||
 | 
			
		||||
    /* floppy type */
 | 
			
		||||
 | 
			
		||||
    fd0 = fdctrl_get_drive_type(floppy_controller, 0);
 | 
			
		||||
    fd1 = fdctrl_get_drive_type(floppy_controller, 1);
 | 
			
		||||
 | 
			
		||||
    val = (cmos_get_fd_drive_type(fd0) << 4) | cmos_get_fd_drive_type(fd1);
 | 
			
		||||
    rtc_set_memory(s, 0x10, val);
 | 
			
		||||
 | 
			
		||||
    val = 0;
 | 
			
		||||
    nb = 0;
 | 
			
		||||
    if (fd0 < 3)
 | 
			
		||||
        nb++;
 | 
			
		||||
    if (fd1 < 3)
 | 
			
		||||
        nb++;
 | 
			
		||||
 | 
			
		||||
    switch (nb) {
 | 
			
		||||
    case 0:
 | 
			
		||||
        break;
 | 
			
		||||
    case 1:
 | 
			
		||||
        val |= 0x01; /* 1 drive, ready for boot */
 | 
			
		||||
        break;
 | 
			
		||||
    case 2:
 | 
			
		||||
        val |= 0x41; /* 2 drives, ready for boot */
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    val |= 0x02; /* FPU is there */
 | 
			
		||||
    val |= 0x04; /* PS/2 mouse installed */
 | 
			
		||||
    rtc_set_memory(s, REG_EQUIPMENT_BYTE, val);
 | 
			
		||||
 | 
			
		||||
    /* hard drives */
 | 
			
		||||
 | 
			
		||||
    rtc_set_memory(s, 0x12, (hd_table[0] ? 0xf0 : 0) | (hd_table[1] ? 0x0f : 0));
 | 
			
		||||
    if (hd_table[0])
 | 
			
		||||
        cmos_init_hd(0x19, 0x1b, hd_table[0]);
 | 
			
		||||
    if (hd_table[1])
 | 
			
		||||
        cmos_init_hd(0x1a, 0x24, hd_table[1]);
 | 
			
		||||
 | 
			
		||||
    val = 0;
 | 
			
		||||
    for (i = 0; i < 4; i++) {
 | 
			
		||||
        if (hd_table[i]) {
 | 
			
		||||
            int cylinders, heads, sectors, translation;
 | 
			
		||||
            /* NOTE: bdrv_get_geometry_hint() returns the physical
 | 
			
		||||
               geometry.  It is always such that: 1 <= sects <= 63, 1
 | 
			
		||||
               <= heads <= 16, 1 <= cylinders <= 16383. The BIOS
 | 
			
		||||
               geometry can be different if a translation is done. */
 | 
			
		||||
            translation = bdrv_get_translation_hint(hd_table[i]);
 | 
			
		||||
            if (translation == BIOS_ATA_TRANSLATION_AUTO) {
 | 
			
		||||
                bdrv_get_geometry_hint(hd_table[i], &cylinders,
 | 
			
		||||
                                       &heads, §ors);
 | 
			
		||||
                if (cylinders <= 1024 && heads <= 16 && sectors <= 63) {
 | 
			
		||||
                    /* No translation. */
 | 
			
		||||
                    translation = 0;
 | 
			
		||||
                } else {
 | 
			
		||||
                    /* LBA translation. */
 | 
			
		||||
                    translation = 1;
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                translation--;
 | 
			
		||||
            }
 | 
			
		||||
            val |= translation << (i * 2);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    rtc_set_memory(s, 0x39, val);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void main_cpu_reset(void *opaque)
 | 
			
		||||
{
 | 
			
		||||
    CPUState *env = opaque;
 | 
			
		||||
    cpu_reset(env);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const int ide_iobase[2] = { 0x1f0, 0x170 };
 | 
			
		||||
static const int ide_iobase2[2] = { 0x3f6, 0x376 };
 | 
			
		||||
static const int ide_irq[2] = { 14, 15 };
 | 
			
		||||
 | 
			
		||||
#define NE2000_NB_MAX 6
 | 
			
		||||
 | 
			
		||||
static int ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340,
 | 
			
		||||
                                        0x360, 0x280, 0x380 };
 | 
			
		||||
static int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
 | 
			
		||||
 | 
			
		||||
static int serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
 | 
			
		||||
static int serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 };
 | 
			
		||||
 | 
			
		||||
static int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
 | 
			
		||||
static int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
 | 
			
		||||
 | 
			
		||||
#ifdef HAS_AUDIO
 | 
			
		||||
static void audio_init (PCIBus *pci_bus, qemu_irq *pic)
 | 
			
		||||
{
 | 
			
		||||
    struct soundhw *c;
 | 
			
		||||
    int audio_enabled = 0;
 | 
			
		||||
 | 
			
		||||
    for (c = soundhw; !audio_enabled && c->name; ++c) {
 | 
			
		||||
        audio_enabled = c->enabled;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (audio_enabled) {
 | 
			
		||||
        AudioState *s;
 | 
			
		||||
 | 
			
		||||
        s = AUD_init ();
 | 
			
		||||
        if (s) {
 | 
			
		||||
            for (c = soundhw; c->name; ++c) {
 | 
			
		||||
                if (c->enabled) {
 | 
			
		||||
                    if (c->isa) {
 | 
			
		||||
                        c->init.init_isa (s, pic);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        if (pci_bus) {
 | 
			
		||||
                            c->init.init_pci (pci_bus, s);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static void pc_init_ne2k_isa(NICInfo *nd, qemu_irq *pic)
 | 
			
		||||
{
 | 
			
		||||
    static int nb_ne2k = 0;
 | 
			
		||||
 | 
			
		||||
    if (nb_ne2k == NE2000_NB_MAX)
 | 
			
		||||
        return;
 | 
			
		||||
    isa_ne2000_init(ne2000_io[nb_ne2k], pic[ne2000_irq[nb_ne2k]], nd);
 | 
			
		||||
    nb_ne2k++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Itanium hardware initialisation */
 | 
			
		||||
static void ipf_init1(ram_addr_t ram_size,
 | 
			
		||||
                      const char *boot_device, DisplayState *ds,
 | 
			
		||||
                      const char *kernel_filename, const char *kernel_cmdline,
 | 
			
		||||
                      const char *initrd_filename,
 | 
			
		||||
                      int pci_enabled, const char *cpu_model)
 | 
			
		||||
{
 | 
			
		||||
    char buf[1024];
 | 
			
		||||
    int i;
 | 
			
		||||
    ram_addr_t ram_addr;
 | 
			
		||||
    ram_addr_t above_4g_mem_size = 0;
 | 
			
		||||
    PCIBus *pci_bus;
 | 
			
		||||
    PCIDevice *pci_dev;
 | 
			
		||||
    int piix3_devfn = -1;
 | 
			
		||||
    CPUState *env;
 | 
			
		||||
    qemu_irq *cpu_irq;
 | 
			
		||||
    qemu_irq *i8259;
 | 
			
		||||
    int page_size;
 | 
			
		||||
    int index;
 | 
			
		||||
    unsigned long ipf_legacy_io_base, ipf_legacy_io_mem;
 | 
			
		||||
    BlockDriverState *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
 | 
			
		||||
    BlockDriverState *fd[MAX_FD];
 | 
			
		||||
 | 
			
		||||
    page_size = getpagesize();
 | 
			
		||||
    if (page_size != TARGET_PAGE_SIZE) {
 | 
			
		||||
	fprintf(stderr,"Error! Host page size != qemu target page size,"
 | 
			
		||||
                " you may need to change TARGET_PAGE_BITS in qemu!"
 | 
			
		||||
                "host page size:0x%x\n", page_size);
 | 
			
		||||
        exit(-1);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (ram_size >= 0xc0000000 ) {
 | 
			
		||||
        above_4g_mem_size = ram_size - 0xc0000000;
 | 
			
		||||
        ram_size = 0xc0000000;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* init CPUs */
 | 
			
		||||
    if (cpu_model == NULL) {
 | 
			
		||||
        cpu_model = "IA64";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for(i = 0; i < smp_cpus; i++) {
 | 
			
		||||
        env = cpu_init(cpu_model);
 | 
			
		||||
        if (!env) {
 | 
			
		||||
            fprintf(stderr, "Unable to find CPU definition\n");
 | 
			
		||||
            exit(1);
 | 
			
		||||
        }
 | 
			
		||||
        if (i != 0)
 | 
			
		||||
            env->hflags |= HF_HALTED_MASK;
 | 
			
		||||
        register_savevm("cpu", i, 4, cpu_save, cpu_load, env);
 | 
			
		||||
        qemu_register_reset(main_cpu_reset, 0, env);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* allocate RAM */
 | 
			
		||||
    if (kvm_enabled()) {
 | 
			
		||||
        ram_addr = qemu_ram_alloc(0xa0000);
 | 
			
		||||
        cpu_register_physical_memory(0, 0xa0000, ram_addr);
 | 
			
		||||
 | 
			
		||||
        ram_addr = qemu_ram_alloc(0x20000); // Workaround 0xa0000-0xc0000
 | 
			
		||||
 | 
			
		||||
        ram_addr = qemu_ram_alloc(0x40000);
 | 
			
		||||
        cpu_register_physical_memory(0xc0000, 0x40000, ram_addr);
 | 
			
		||||
 | 
			
		||||
        ram_addr = qemu_ram_alloc(ram_size - 0x100000);
 | 
			
		||||
        cpu_register_physical_memory(0x100000, ram_size - 0x100000, ram_addr);
 | 
			
		||||
    } else {
 | 
			
		||||
        ram_addr = qemu_ram_alloc(ram_size);
 | 
			
		||||
        cpu_register_physical_memory(0, ram_size, ram_addr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* above 4giga memory allocation */
 | 
			
		||||
    if (above_4g_mem_size > 0) {
 | 
			
		||||
        ram_addr = qemu_ram_alloc(above_4g_mem_size);
 | 
			
		||||
        cpu_register_physical_memory(0x100000000, above_4g_mem_size, ram_addr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*Load firware to its proper position.*/
 | 
			
		||||
    if (kvm_enabled()) {
 | 
			
		||||
        unsigned long  image_size;
 | 
			
		||||
        uint8_t *image = NULL;
 | 
			
		||||
        unsigned long nvram_addr;
 | 
			
		||||
        unsigned long nvram_fd = 0;
 | 
			
		||||
        unsigned long type = READ_FROM_NVRAM;
 | 
			
		||||
        unsigned long i = 0;
 | 
			
		||||
        unsigned long fw_offset;
 | 
			
		||||
        ram_addr_t fw_mem = qemu_ram_alloc(GFW_SIZE);
 | 
			
		||||
 | 
			
		||||
        snprintf(buf, sizeof(buf), "%s/%s", bios_dir, FW_FILENAME);
 | 
			
		||||
        image = read_image(buf, &image_size );
 | 
			
		||||
        if (NULL == image || !image_size) {
 | 
			
		||||
            fprintf(stderr, "Error when reading Guest Firmware!\n");
 | 
			
		||||
            fprintf(stderr, "Please check Guest firmware at %s\n", buf);
 | 
			
		||||
            exit(1);
 | 
			
		||||
        }
 | 
			
		||||
        fw_offset = GFW_START + GFW_SIZE - image_size;
 | 
			
		||||
 | 
			
		||||
        cpu_register_physical_memory(GFW_START, GFW_SIZE, fw_mem);
 | 
			
		||||
        cpu_physical_memory_write(fw_offset, image, image_size);
 | 
			
		||||
 | 
			
		||||
        free(image);
 | 
			
		||||
 | 
			
		||||
        if (nvram) {
 | 
			
		||||
            nvram_addr = NVRAM_START;
 | 
			
		||||
            nvram_fd = kvm_ia64_nvram_init(type);
 | 
			
		||||
            if (nvram_fd != -1) {
 | 
			
		||||
                kvm_ia64_copy_from_nvram_to_GFW(nvram_fd);
 | 
			
		||||
                close(nvram_fd);
 | 
			
		||||
            }
 | 
			
		||||
            i = atexit((void *)kvm_ia64_copy_from_GFW_to_nvram);
 | 
			
		||||
            if (i != 0)
 | 
			
		||||
                fprintf(stderr, "cannot set exit function\n");
 | 
			
		||||
        } else
 | 
			
		||||
            nvram_addr = 0;
 | 
			
		||||
 | 
			
		||||
        kvm_ia64_build_hob(ram_size + above_4g_mem_size, smp_cpus, nvram_addr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*Register legacy io address space, size:64M*/
 | 
			
		||||
    ipf_legacy_io_base = 0xE0000000;
 | 
			
		||||
    ipf_legacy_io_mem = cpu_register_io_memory(0, ipf_legacy_io_read,
 | 
			
		||||
                                               ipf_legacy_io_write, NULL);
 | 
			
		||||
    cpu_register_physical_memory(ipf_legacy_io_base, 64*1024*1024,
 | 
			
		||||
                                 ipf_legacy_io_mem);
 | 
			
		||||
 | 
			
		||||
    cpu_irq = qemu_allocate_irqs(pic_irq_request, first_cpu, 1);
 | 
			
		||||
    i8259 = kvm_i8259_init(cpu_irq[0]);
 | 
			
		||||
 | 
			
		||||
    if (pci_enabled) {
 | 
			
		||||
        pci_bus = i440fx_init(&i440fx_state, i8259);
 | 
			
		||||
        piix3_devfn = piix3_init(pci_bus, -1);
 | 
			
		||||
    } else {
 | 
			
		||||
        pci_bus = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (cirrus_vga_enabled) {
 | 
			
		||||
        if (pci_enabled)
 | 
			
		||||
            pci_cirrus_vga_init(pci_bus);
 | 
			
		||||
        else
 | 
			
		||||
            isa_cirrus_vga_init();
 | 
			
		||||
    } else {
 | 
			
		||||
        if (pci_enabled)
 | 
			
		||||
            pci_vga_init(pci_bus, 0, 0);
 | 
			
		||||
        else
 | 
			
		||||
            isa_vga_init();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    rtc_state = rtc_init(0x70, i8259[8], 2000);
 | 
			
		||||
 | 
			
		||||
    if (pci_enabled) {
 | 
			
		||||
        pic_set_alt_irq_func(isa_pic, NULL, NULL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for(i = 0; i < MAX_SERIAL_PORTS; i++) {
 | 
			
		||||
        if (serial_hds[i]) {
 | 
			
		||||
            serial_init(serial_io[i], i8259[serial_irq[i]], 115200,
 | 
			
		||||
                        serial_hds[i]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
 | 
			
		||||
        if (parallel_hds[i]) {
 | 
			
		||||
            parallel_init(parallel_io[i], i8259[parallel_irq[i]],
 | 
			
		||||
                          parallel_hds[i]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for(i = 0; i < nb_nics; i++) {
 | 
			
		||||
        NICInfo *nd = &nd_table[i];
 | 
			
		||||
 | 
			
		||||
        if (!pci_enabled || (nd->model && strcmp(nd->model, "ne2k_isa") == 0))
 | 
			
		||||
            pc_init_ne2k_isa(nd, i8259);
 | 
			
		||||
        else
 | 
			
		||||
            pci_nic_init(nd, "e1000", NULL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#undef USE_HYPERCALL  //Disable it now, need to implement later!
 | 
			
		||||
#ifdef USE_HYPERCALL
 | 
			
		||||
    pci_hypercall_init(pci_bus);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
 | 
			
		||||
        fprintf(stderr, "qemu: too many IDE bus\n");
 | 
			
		||||
        exit(1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for(i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) {
 | 
			
		||||
        index = drive_get_index(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
 | 
			
		||||
	if (index != -1)
 | 
			
		||||
	    hd[i] = drives_table[index].bdrv;
 | 
			
		||||
	else
 | 
			
		||||
	    hd[i] = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (pci_enabled) {
 | 
			
		||||
        pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1, i8259);
 | 
			
		||||
    } else {
 | 
			
		||||
        for(i = 0; i < MAX_IDE_BUS; i++) {
 | 
			
		||||
            isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[ide_irq[i]],
 | 
			
		||||
	                 hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    i8042_init(i8259[1], i8259[12], 0x60);
 | 
			
		||||
    DMA_init(0);
 | 
			
		||||
#ifdef HAS_AUDIO
 | 
			
		||||
    audio_init(pci_enabled ? pci_bus : NULL, i8259);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    for(i = 0; i < MAX_FD; i++) {
 | 
			
		||||
        index = drive_get_index(IF_FLOPPY, 0, i);
 | 
			
		||||
	if (index != -1)
 | 
			
		||||
	    fd[i] = drives_table[index].bdrv;
 | 
			
		||||
	else
 | 
			
		||||
	    fd[i] = NULL;
 | 
			
		||||
    }
 | 
			
		||||
    floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd);
 | 
			
		||||
 | 
			
		||||
    cmos_init(ram_size, above_4g_mem_size, boot_device, hd);
 | 
			
		||||
 | 
			
		||||
    if (pci_enabled && usb_enabled) {
 | 
			
		||||
        usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (pci_enabled && acpi_enabled) {
 | 
			
		||||
        uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */
 | 
			
		||||
        i2c_bus *smbus;
 | 
			
		||||
 | 
			
		||||
        /* TODO: Populate SPD eeprom data.  */
 | 
			
		||||
        smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, i8259[9]);
 | 
			
		||||
        for (i = 0; i < 8; i++) {
 | 
			
		||||
            DeviceState *eeprom;
 | 
			
		||||
            eeprom = qdev_create((BusState *)smbus, "smbus-eeprom");
 | 
			
		||||
            qdev_set_prop_int(eeprom, "address", 0x50 + i);
 | 
			
		||||
            qdev_set_prop_ptr(eeprom, "data", eeprom_buf + (i * 256));
 | 
			
		||||
            qdev_init(eeprom);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (i440fx_state) {
 | 
			
		||||
        i440fx_init_memory_mappings(i440fx_state);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (pci_enabled) {
 | 
			
		||||
	int max_bus;
 | 
			
		||||
        int bus;
 | 
			
		||||
 | 
			
		||||
        max_bus = drive_get_max_bus(IF_SCSI);
 | 
			
		||||
	for (bus = 0; bus <= max_bus; bus++) {
 | 
			
		||||
            pci_create_simple(pci_bus, -1, "lsi53c895a");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    /* Add virtio block devices */
 | 
			
		||||
    if (pci_enabled) {
 | 
			
		||||
	int index;
 | 
			
		||||
	int unit_id = 0;
 | 
			
		||||
 | 
			
		||||
	while ((index = drive_get_index(IF_VIRTIO, 0, unit_id)) != -1) {
 | 
			
		||||
            pci_dev = pci_create("virtio-blk-pci",
 | 
			
		||||
                                 drives_table[index].devaddr);
 | 
			
		||||
            qdev_init(&pci_dev->qdev);
 | 
			
		||||
	    unit_id++;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ipf_init_pci(ram_addr_t ram_size,
 | 
			
		||||
                         const char *boot_device, DisplayState *ds,
 | 
			
		||||
                         const char *kernel_filename,
 | 
			
		||||
                         const char *kernel_cmdline,
 | 
			
		||||
                         const char *initrd_filename,
 | 
			
		||||
                         const char *cpu_model)
 | 
			
		||||
{
 | 
			
		||||
    ipf_init1(ram_size, boot_device, ds, kernel_filename,
 | 
			
		||||
              kernel_cmdline, initrd_filename, 1, cpu_model);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QEMUMachine ipf_machine = {
 | 
			
		||||
    .name = "itanium",
 | 
			
		||||
    .desc = "Itanium Platform",
 | 
			
		||||
    .init = (QEMUMachineInitFunc *)ipf_init_pci,
 | 
			
		||||
    .max_cpus = 255,
 | 
			
		||||
    .is_default = 1,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void ipf_machine_init(void)
 | 
			
		||||
{
 | 
			
		||||
    qemu_register_machine(&ipf_machine);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
machine_init(ipf_machine_init);
 | 
			
		||||
 | 
			
		||||
#define IOAPIC_NUM_PINS 48
 | 
			
		||||
 | 
			
		||||
static int ioapic_irq_count[IOAPIC_NUM_PINS];
 | 
			
		||||
 | 
			
		||||
static int ioapic_map_irq(int devfn, int irq_num)
 | 
			
		||||
{
 | 
			
		||||
    int irq, dev;
 | 
			
		||||
    dev = devfn >> 3;
 | 
			
		||||
    irq = ((((dev << 2) + (dev >> 3) + irq_num) & 31) + 16);
 | 
			
		||||
    return irq;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Dummy function to provide match for call from hw/apic.c
 | 
			
		||||
 */
 | 
			
		||||
void apic_set_irq_delivered(void) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ioapic_set_irq(void *opaque, int irq_num, int level)
 | 
			
		||||
{
 | 
			
		||||
    int vector, pic_ret;
 | 
			
		||||
 | 
			
		||||
    PCIDevice *pci_dev = (PCIDevice *)opaque;
 | 
			
		||||
    vector = ioapic_map_irq(pci_dev->devfn, irq_num);
 | 
			
		||||
 | 
			
		||||
    if (level)
 | 
			
		||||
        ioapic_irq_count[vector] += 1;
 | 
			
		||||
    else
 | 
			
		||||
        ioapic_irq_count[vector] -= 1;
 | 
			
		||||
 | 
			
		||||
    if (kvm_enabled()) {
 | 
			
		||||
	if (kvm_set_irq(vector, ioapic_irq_count[vector] == 0, &pic_ret))
 | 
			
		||||
            if (pic_ret != 0)
 | 
			
		||||
                apic_set_irq_delivered();
 | 
			
		||||
	    return;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int ipf_map_irq(PCIDevice *pci_dev, int irq_num)
 | 
			
		||||
{
 | 
			
		||||
	return ioapic_map_irq(pci_dev->devfn, irq_num);
 | 
			
		||||
}
 | 
			
		||||
@@ -66,7 +66,7 @@ void isa_bus_irqs(qemu_irq *irqs)
 | 
			
		||||
 */
 | 
			
		||||
qemu_irq isa_get_irq(int isairq)
 | 
			
		||||
{
 | 
			
		||||
    if (isairq < 0 || isairq > 15) {
 | 
			
		||||
    if (isairq < 0 || isairq > 23) {
 | 
			
		||||
        hw_error("isa irq %d invalid", isairq);
 | 
			
		||||
    }
 | 
			
		||||
    return isabus->irqs[isairq];
 | 
			
		||||
 
 | 
			
		||||
@@ -310,10 +310,12 @@ static int milkymist_softusb_init(SysBusDevice *dev)
 | 
			
		||||
    usb_bus_new(&s->usbbus, &softusb_bus_ops, NULL);
 | 
			
		||||
 | 
			
		||||
    /* our two ports */
 | 
			
		||||
    /* FIXME: claim to support full speed devices. qemu mouse and keyboard
 | 
			
		||||
     * report themselves as full speed devices. */
 | 
			
		||||
    usb_register_port(&s->usbbus, &s->usbport[0], NULL, 0, &softusb_ops,
 | 
			
		||||
            USB_SPEED_MASK_LOW);
 | 
			
		||||
            USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
 | 
			
		||||
    usb_register_port(&s->usbbus, &s->usbport[1], NULL, 1, &softusb_ops,
 | 
			
		||||
            USB_SPEED_MASK_LOW);
 | 
			
		||||
            USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
 | 
			
		||||
 | 
			
		||||
    /* and finally create an usb keyboard */
 | 
			
		||||
    s->usbdev = usb_create_simple(&s->usbbus, "usb-kbd");
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										131
									
								
								hw/msi.c
									
									
									
									
									
								
							
							
						
						
									
										131
									
								
								hw/msi.c
									
									
									
									
									
								
							@@ -20,6 +20,7 @@
 | 
			
		||||
 | 
			
		||||
#include "msi.h"
 | 
			
		||||
#include "range.h"
 | 
			
		||||
#include "kvm.h"
 | 
			
		||||
 | 
			
		||||
/* Eventually those constants should go to Linux pci_regs.h */
 | 
			
		||||
#define PCI_MSI_PENDING_32      0x10
 | 
			
		||||
@@ -109,6 +110,94 @@ bool msi_enabled(const PCIDevice *dev)
 | 
			
		||||
         PCI_MSI_FLAGS_ENABLE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void kvm_msi_message_from_vector(PCIDevice *dev, unsigned vector,
 | 
			
		||||
                                        KVMMsiMessage *kmm)
 | 
			
		||||
{
 | 
			
		||||
    uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
 | 
			
		||||
    bool msi64bit = flags & PCI_MSI_FLAGS_64BIT;
 | 
			
		||||
    unsigned int nr_vectors = msi_nr_vectors(flags);
 | 
			
		||||
 | 
			
		||||
    kmm->addr_lo = pci_get_long(dev->config + msi_address_lo_off(dev));
 | 
			
		||||
    if (msi64bit) {
 | 
			
		||||
        kmm->addr_hi = pci_get_long(dev->config + msi_address_hi_off(dev));
 | 
			
		||||
    } else {
 | 
			
		||||
        kmm->addr_hi = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    kmm->data = pci_get_word(dev->config + msi_data_off(dev, msi64bit));
 | 
			
		||||
    if (nr_vectors > 1) {
 | 
			
		||||
        kmm->data &= ~(nr_vectors - 1);
 | 
			
		||||
        kmm->data |= vector;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void kvm_msi_update(PCIDevice *dev)
 | 
			
		||||
{
 | 
			
		||||
    uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
 | 
			
		||||
    unsigned int max_vectors = 1 <<
 | 
			
		||||
        ((flags & PCI_MSI_FLAGS_QMASK) >> (ffs(PCI_MSI_FLAGS_QMASK) - 1));
 | 
			
		||||
    unsigned int nr_vectors = msi_nr_vectors(flags);
 | 
			
		||||
    KVMMsiMessage new_entry, *entry;
 | 
			
		||||
    bool changed = false;
 | 
			
		||||
    unsigned int vector;
 | 
			
		||||
    int r;
 | 
			
		||||
 | 
			
		||||
    for (vector = 0; vector < max_vectors; vector++) {
 | 
			
		||||
        entry = dev->msi_irq_entries + vector;
 | 
			
		||||
 | 
			
		||||
        if (vector >= nr_vectors) {
 | 
			
		||||
            if (vector < dev->msi_entries_nr) {
 | 
			
		||||
                kvm_msi_message_del(entry);
 | 
			
		||||
                changed = true;
 | 
			
		||||
            }
 | 
			
		||||
        } else if (vector >= dev->msi_entries_nr) {
 | 
			
		||||
            kvm_msi_message_from_vector(dev, vector, entry);
 | 
			
		||||
            r = kvm_msi_message_add(entry);
 | 
			
		||||
            if (r) {
 | 
			
		||||
                fprintf(stderr, "%s: kvm_msi_add failed: %s\n", __func__,
 | 
			
		||||
                        strerror(-r));
 | 
			
		||||
                exit(1);
 | 
			
		||||
            }
 | 
			
		||||
            changed = true;
 | 
			
		||||
        } else {
 | 
			
		||||
            kvm_msi_message_from_vector(dev, vector, &new_entry);
 | 
			
		||||
            r = kvm_msi_message_update(entry, &new_entry);
 | 
			
		||||
            if (r < 0) {
 | 
			
		||||
                fprintf(stderr, "%s: kvm_update_msi failed: %s\n",
 | 
			
		||||
                        __func__, strerror(-r));
 | 
			
		||||
                exit(1);
 | 
			
		||||
            }
 | 
			
		||||
            if (r > 0) {
 | 
			
		||||
                *entry = new_entry;
 | 
			
		||||
                changed = true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    dev->msi_entries_nr = nr_vectors;
 | 
			
		||||
    if (changed) {
 | 
			
		||||
        r = kvm_commit_irq_routes();
 | 
			
		||||
        if (r) {
 | 
			
		||||
            fprintf(stderr, "%s: kvm_commit_irq_routes failed: %s\n", __func__,
 | 
			
		||||
                    strerror(-r));
 | 
			
		||||
            exit(1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* KVM specific MSI helpers */
 | 
			
		||||
static void kvm_msi_free(PCIDevice *dev)
 | 
			
		||||
{
 | 
			
		||||
    unsigned int vector;
 | 
			
		||||
 | 
			
		||||
    for (vector = 0; vector < dev->msi_entries_nr; ++vector) {
 | 
			
		||||
        kvm_msi_message_del(&dev->msi_irq_entries[vector]);
 | 
			
		||||
    }
 | 
			
		||||
    if (dev->msi_entries_nr > 0) {
 | 
			
		||||
        kvm_commit_irq_routes();
 | 
			
		||||
    }
 | 
			
		||||
    dev->msi_entries_nr = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int msi_init(struct PCIDevice *dev, uint8_t offset,
 | 
			
		||||
             unsigned int nr_vectors, bool msi64bit, bool msi_per_vector_mask)
 | 
			
		||||
{
 | 
			
		||||
@@ -121,6 +210,10 @@ int msi_init(struct PCIDevice *dev, uint8_t offset,
 | 
			
		||||
                   " 64bit %d mask %d\n",
 | 
			
		||||
                   offset, nr_vectors, msi64bit, msi_per_vector_mask);
 | 
			
		||||
 | 
			
		||||
    if (kvm_enabled() && kvm_irqchip_in_kernel() && !kvm_has_gsi_routing()) {
 | 
			
		||||
        return -ENOTSUP;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    assert(!(nr_vectors & (nr_vectors - 1)));   /* power of 2 */
 | 
			
		||||
    assert(nr_vectors > 0);
 | 
			
		||||
    assert(nr_vectors <= PCI_MSI_VECTORS_MAX);
 | 
			
		||||
@@ -159,6 +252,12 @@ int msi_init(struct PCIDevice *dev, uint8_t offset,
 | 
			
		||||
        pci_set_long(dev->wmask + msi_mask_off(dev, msi64bit),
 | 
			
		||||
                     0xffffffff >> (PCI_MSI_VECTORS_MAX - nr_vectors));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
 | 
			
		||||
        dev->msi_irq_entries = qemu_malloc(nr_vectors *
 | 
			
		||||
                                           sizeof(*dev->msix_irq_entries));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return config_offset;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -172,6 +271,12 @@ void msi_uninit(struct PCIDevice *dev)
 | 
			
		||||
    }
 | 
			
		||||
    flags = pci_get_word(dev->config + msi_flags_off(dev));
 | 
			
		||||
    cap_size = msi_cap_sizeof(flags);
 | 
			
		||||
 | 
			
		||||
    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
 | 
			
		||||
        kvm_msi_free(dev);
 | 
			
		||||
        qemu_free(dev->msi_irq_entries);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pci_del_capability(dev, PCI_CAP_ID_MSI, cap_size);
 | 
			
		||||
    dev->cap_present &= ~QEMU_PCI_CAP_MSI;
 | 
			
		||||
 | 
			
		||||
@@ -183,6 +288,10 @@ void msi_reset(PCIDevice *dev)
 | 
			
		||||
    uint16_t flags;
 | 
			
		||||
    bool msi64bit;
 | 
			
		||||
 | 
			
		||||
    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
 | 
			
		||||
        kvm_msi_free(dev);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    flags = pci_get_word(dev->config + msi_flags_off(dev));
 | 
			
		||||
    flags &= ~(PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE);
 | 
			
		||||
    msi64bit = flags & PCI_MSI_FLAGS_64BIT;
 | 
			
		||||
@@ -232,6 +341,11 @@ void msi_notify(PCIDevice *dev, unsigned int vector)
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
 | 
			
		||||
        kvm_set_irq(dev->msi_irq_entries[vector].gsi, 1, NULL);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (msi64bit) {
 | 
			
		||||
        address = pci_get_quad(dev->config + msi_address_lo_off(dev));
 | 
			
		||||
    } else {
 | 
			
		||||
@@ -320,6 +434,10 @@ void msi_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len)
 | 
			
		||||
        pci_set_word(dev->config + msi_flags_off(dev), flags);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
 | 
			
		||||
        kvm_msi_update(dev);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!msi_per_vector_mask) {
 | 
			
		||||
        /* if per vector masking isn't supported,
 | 
			
		||||
           there is no pending interrupt. */
 | 
			
		||||
@@ -350,3 +468,16 @@ unsigned int msi_nr_vectors_allocated(const PCIDevice *dev)
 | 
			
		||||
    uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
 | 
			
		||||
    return msi_nr_vectors(flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void msi_post_load(PCIDevice *dev)
 | 
			
		||||
{
 | 
			
		||||
    uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
 | 
			
		||||
 | 
			
		||||
    if (kvm_enabled() && dev->msi_irq_entries) {
 | 
			
		||||
        kvm_msi_free(dev);
 | 
			
		||||
 | 
			
		||||
        if (flags & PCI_MSI_FLAGS_ENABLE) {
 | 
			
		||||
            kvm_msi_update(dev);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								hw/msi.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								hw/msi.h
									
									
									
									
									
								
							@@ -32,6 +32,7 @@ void msi_reset(PCIDevice *dev);
 | 
			
		||||
void msi_notify(PCIDevice *dev, unsigned int vector);
 | 
			
		||||
void msi_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len);
 | 
			
		||||
unsigned int msi_nr_vectors_allocated(const PCIDevice *dev);
 | 
			
		||||
void msi_post_load(PCIDevice *dev);
 | 
			
		||||
 | 
			
		||||
static inline bool msi_present(const PCIDevice *dev)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										221
									
								
								hw/msix.c
									
									
									
									
									
								
							
							
						
						
									
										221
									
								
								hw/msix.c
									
									
									
									
									
								
							@@ -15,6 +15,7 @@
 | 
			
		||||
#include "msix.h"
 | 
			
		||||
#include "pci.h"
 | 
			
		||||
#include "range.h"
 | 
			
		||||
#include "kvm.h"
 | 
			
		||||
 | 
			
		||||
#define MSIX_CAP_LENGTH 12
 | 
			
		||||
 | 
			
		||||
@@ -35,6 +36,93 @@
 | 
			
		||||
/* Flag for interrupt controller to declare MSI-X support */
 | 
			
		||||
int msix_supported;
 | 
			
		||||
 | 
			
		||||
/* KVM specific MSIX helpers */
 | 
			
		||||
static void kvm_msix_free(PCIDevice *dev)
 | 
			
		||||
{
 | 
			
		||||
    int vector, changed = 0;
 | 
			
		||||
 | 
			
		||||
    for (vector = 0; vector < dev->msix_entries_nr; ++vector) {
 | 
			
		||||
        if (dev->msix_entry_used[vector]) {
 | 
			
		||||
            kvm_msi_message_del(&dev->msix_irq_entries[vector]);
 | 
			
		||||
            changed = 1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (changed) {
 | 
			
		||||
        kvm_commit_irq_routes();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void kvm_msix_message_from_vector(PCIDevice *dev, unsigned vector,
 | 
			
		||||
                                         KVMMsiMessage *kmm)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t *table_entry = dev->msix_table_page + vector * PCI_MSIX_ENTRY_SIZE;
 | 
			
		||||
 | 
			
		||||
    kmm->addr_lo = pci_get_long(table_entry + PCI_MSIX_ENTRY_LOWER_ADDR);
 | 
			
		||||
    kmm->addr_hi = pci_get_long(table_entry + PCI_MSIX_ENTRY_UPPER_ADDR);
 | 
			
		||||
    kmm->data = pci_get_long(table_entry + PCI_MSIX_ENTRY_DATA);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void kvm_msix_update(PCIDevice *dev, int vector,
 | 
			
		||||
                            int was_masked, int is_masked)
 | 
			
		||||
{
 | 
			
		||||
    KVMMsiMessage new_entry, *entry;
 | 
			
		||||
    int mask_cleared = was_masked && !is_masked;
 | 
			
		||||
    int r;
 | 
			
		||||
 | 
			
		||||
    /* It is only legal to change an entry when it is masked. Therefore, it is
 | 
			
		||||
     * enough to update the routing in kernel when mask is being cleared. */
 | 
			
		||||
    if (!mask_cleared) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if (!dev->msix_entry_used[vector]) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    entry = dev->msix_irq_entries + vector;
 | 
			
		||||
    kvm_msix_message_from_vector(dev, vector, &new_entry);
 | 
			
		||||
    r = kvm_msi_message_update(entry, &new_entry);
 | 
			
		||||
    if (r < 0) {
 | 
			
		||||
        fprintf(stderr, "%s: kvm_update_msix failed: %s\n", __func__,
 | 
			
		||||
                strerror(-r));
 | 
			
		||||
        exit(1);
 | 
			
		||||
    }
 | 
			
		||||
    if (r > 0) {
 | 
			
		||||
        *entry = new_entry;
 | 
			
		||||
        r = kvm_commit_irq_routes();
 | 
			
		||||
        if (r) {
 | 
			
		||||
            fprintf(stderr, "%s: kvm_commit_irq_routes failed: %s\n", __func__,
 | 
			
		||||
		    strerror(-r));
 | 
			
		||||
            exit(1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int kvm_msix_vector_add(PCIDevice *dev, unsigned vector)
 | 
			
		||||
{
 | 
			
		||||
    KVMMsiMessage *kmm = dev->msix_irq_entries + vector;
 | 
			
		||||
    int r;
 | 
			
		||||
 | 
			
		||||
    kvm_msix_message_from_vector(dev, vector, kmm);
 | 
			
		||||
    r = kvm_msi_message_add(kmm);
 | 
			
		||||
    if (r < 0) {
 | 
			
		||||
        fprintf(stderr, "%s: kvm_add_msix failed: %s\n", __func__, strerror(-r));
 | 
			
		||||
        return r;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    r = kvm_commit_irq_routes();
 | 
			
		||||
    if (r < 0) {
 | 
			
		||||
        fprintf(stderr, "%s: kvm_commit_irq_routes failed: %s\n", __func__, strerror(-r));
 | 
			
		||||
        return r;
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void kvm_msix_vector_del(PCIDevice *dev, unsigned vector)
 | 
			
		||||
{
 | 
			
		||||
    kvm_msi_message_del(&dev->msix_irq_entries[vector]);
 | 
			
		||||
    kvm_commit_irq_routes();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Add MSI-X capability to the config space for the device. */
 | 
			
		||||
/* Given a bar and its size, add MSI-X table on top of it
 | 
			
		||||
 * and fill MSI-X capability in the config space.
 | 
			
		||||
@@ -45,6 +133,12 @@ static int msix_add_config(struct PCIDevice *pdev, unsigned short nentries,
 | 
			
		||||
{
 | 
			
		||||
    int config_offset;
 | 
			
		||||
    uint8_t *config;
 | 
			
		||||
 | 
			
		||||
    pdev->msix_bar_size = bar_size;
 | 
			
		||||
 | 
			
		||||
    config_offset = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
 | 
			
		||||
 | 
			
		||||
    if (!config_offset) {
 | 
			
		||||
        uint32_t new_size;
 | 
			
		||||
 | 
			
		||||
        if (nentries < 1 || nentries > PCI_MSIX_FLAGS_QSIZE + 1)
 | 
			
		||||
@@ -75,6 +169,7 @@ static int msix_add_config(struct PCIDevice *pdev, unsigned short nentries,
 | 
			
		||||
        /* Pending bits on top of that */
 | 
			
		||||
        pci_set_long(config + PCI_MSIX_PBA, (bar_size + MSIX_PAGE_PENDING) |
 | 
			
		||||
                     bar_nr);
 | 
			
		||||
    }
 | 
			
		||||
    pdev->msix_cap = config_offset;
 | 
			
		||||
    /* Make flags bit writable. */
 | 
			
		||||
    pdev->wmask[config_offset + MSIX_CONTROL_OFFSET] |= MSIX_ENABLE_MASK |
 | 
			
		||||
@@ -175,7 +270,16 @@ static void msix_mmio_writel(void *opaque, target_phys_addr_t addr,
 | 
			
		||||
    PCIDevice *dev = opaque;
 | 
			
		||||
    unsigned int offset = addr & (MSIX_PAGE_SIZE - 1) & ~0x3;
 | 
			
		||||
    int vector = offset / PCI_MSIX_ENTRY_SIZE;
 | 
			
		||||
    int was_masked = msix_is_masked(dev, vector);
 | 
			
		||||
    pci_set_long(dev->msix_table_page + offset, val);
 | 
			
		||||
    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
 | 
			
		||||
        kvm_msix_update(dev, vector, was_masked, msix_is_masked(dev, vector));
 | 
			
		||||
    }
 | 
			
		||||
    if (was_masked != msix_is_masked(dev, vector) && dev->msix_mask_notifier) {
 | 
			
		||||
        int r = dev->msix_mask_notifier(dev, vector,
 | 
			
		||||
					msix_is_masked(dev, vector));
 | 
			
		||||
        assert(r >= 0);
 | 
			
		||||
    }
 | 
			
		||||
    msix_handle_mask_update(dev, vector);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -208,17 +312,25 @@ void msix_mmio_map(PCIDevice *d, int region_num,
 | 
			
		||||
        return;
 | 
			
		||||
    if (size <= offset)
 | 
			
		||||
        return;
 | 
			
		||||
    cpu_register_physical_memory(addr + offset, size - offset,
 | 
			
		||||
    cpu_register_physical_memory(addr + offset,
 | 
			
		||||
                                 MIN(size - offset, MSIX_PAGE_SIZE),
 | 
			
		||||
                                 d->msix_mmio_index);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void msix_mask_all(struct PCIDevice *dev, unsigned nentries)
 | 
			
		||||
{
 | 
			
		||||
    int vector;
 | 
			
		||||
    int vector, r;
 | 
			
		||||
    for (vector = 0; vector < nentries; ++vector) {
 | 
			
		||||
        unsigned offset =
 | 
			
		||||
            vector * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL;
 | 
			
		||||
        int was_masked = msix_is_masked(dev, vector);
 | 
			
		||||
        dev->msix_table_page[offset] |= PCI_MSIX_ENTRY_CTRL_MASKBIT;
 | 
			
		||||
        if (was_masked != msix_is_masked(dev, vector) &&
 | 
			
		||||
            dev->msix_mask_notifier) {
 | 
			
		||||
            r = dev->msix_mask_notifier(dev, vector,
 | 
			
		||||
                                        msix_is_masked(dev, vector));
 | 
			
		||||
            assert(r >= 0);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -229,12 +341,15 @@ int msix_init(struct PCIDevice *dev, unsigned short nentries,
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
    /* Nothing to do if MSI is not supported by interrupt controller */
 | 
			
		||||
    if (!msix_supported)
 | 
			
		||||
    if (!msix_supported ||
 | 
			
		||||
        (kvm_enabled() && kvm_irqchip_in_kernel() && !kvm_has_gsi_routing())) {
 | 
			
		||||
        return -ENOTSUP;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (nentries > MSIX_MAX_ENTRIES)
 | 
			
		||||
        return -EINVAL;
 | 
			
		||||
 | 
			
		||||
    dev->msix_mask_notifier = NULL;
 | 
			
		||||
    dev->msix_entry_used = qemu_mallocz(MSIX_MAX_ENTRIES *
 | 
			
		||||
                                        sizeof *dev->msix_entry_used);
 | 
			
		||||
 | 
			
		||||
@@ -254,6 +369,11 @@ int msix_init(struct PCIDevice *dev, unsigned short nentries,
 | 
			
		||||
    if (ret)
 | 
			
		||||
        goto err_config;
 | 
			
		||||
 | 
			
		||||
    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
 | 
			
		||||
        dev->msix_irq_entries = qemu_malloc(nentries *
 | 
			
		||||
                                            sizeof *dev->msix_irq_entries);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    dev->cap_present |= QEMU_PCI_CAP_MSIX;
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
@@ -272,6 +392,10 @@ static void msix_free_irq_entries(PCIDevice *dev)
 | 
			
		||||
{
 | 
			
		||||
    int vector;
 | 
			
		||||
 | 
			
		||||
    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
 | 
			
		||||
        kvm_msix_free(dev);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (vector = 0; vector < dev->msix_entries_nr; ++vector) {
 | 
			
		||||
        dev->msix_entry_used[vector] = 0;
 | 
			
		||||
        msix_clr_pending(dev, vector);
 | 
			
		||||
@@ -292,6 +416,8 @@ int msix_uninit(PCIDevice *dev)
 | 
			
		||||
    dev->msix_table_page = NULL;
 | 
			
		||||
    qemu_free(dev->msix_entry_used);
 | 
			
		||||
    dev->msix_entry_used = NULL;
 | 
			
		||||
    qemu_free(dev->msix_irq_entries);
 | 
			
		||||
    dev->msix_irq_entries = NULL;
 | 
			
		||||
    dev->cap_present &= ~QEMU_PCI_CAP_MSIX;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -300,10 +426,13 @@ void msix_save(PCIDevice *dev, QEMUFile *f)
 | 
			
		||||
{
 | 
			
		||||
    unsigned n = dev->msix_entries_nr;
 | 
			
		||||
 | 
			
		||||
    if (!(dev->cap_present & QEMU_PCI_CAP_MSIX)) {
 | 
			
		||||
    if (!msix_supported) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!(dev->cap_present & QEMU_PCI_CAP_MSIX)) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    qemu_put_buffer(f, dev->msix_table_page, n * PCI_MSIX_ENTRY_SIZE);
 | 
			
		||||
    qemu_put_buffer(f, dev->msix_table_page + MSIX_PAGE_PENDING, (n + 7) / 8);
 | 
			
		||||
}
 | 
			
		||||
@@ -313,6 +442,9 @@ void msix_load(PCIDevice *dev, QEMUFile *f)
 | 
			
		||||
{
 | 
			
		||||
    unsigned n = dev->msix_entries_nr;
 | 
			
		||||
 | 
			
		||||
    if (!msix_supported)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if (!(dev->cap_present & QEMU_PCI_CAP_MSIX)) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
@@ -357,6 +489,11 @@ void msix_notify(PCIDevice *dev, unsigned vector)
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
 | 
			
		||||
        kvm_set_irq(dev->msix_irq_entries[vector].gsi, 1, NULL);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    address = pci_get_quad(table_entry + PCI_MSIX_ENTRY_LOWER_ADDR);
 | 
			
		||||
    data = pci_get_long(table_entry + PCI_MSIX_ENTRY_DATA);
 | 
			
		||||
    stl_le_phys(address, data);
 | 
			
		||||
@@ -384,9 +521,17 @@ void msix_reset(PCIDevice *dev)
 | 
			
		||||
/* Mark vector as used. */
 | 
			
		||||
int msix_vector_use(PCIDevice *dev, unsigned vector)
 | 
			
		||||
{
 | 
			
		||||
    int ret;
 | 
			
		||||
    if (vector >= dev->msix_entries_nr)
 | 
			
		||||
        return -EINVAL;
 | 
			
		||||
    dev->msix_entry_used[vector]++;
 | 
			
		||||
    if (kvm_enabled() && kvm_irqchip_in_kernel() &&
 | 
			
		||||
        !dev->msix_entry_used[vector]) {
 | 
			
		||||
        ret = kvm_msix_vector_add(dev, vector);
 | 
			
		||||
        if (ret) {
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    ++dev->msix_entry_used[vector];
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -399,6 +544,9 @@ void msix_vector_unuse(PCIDevice *dev, unsigned vector)
 | 
			
		||||
    if (--dev->msix_entry_used[vector]) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
 | 
			
		||||
        kvm_msix_vector_del(dev, vector);
 | 
			
		||||
    }
 | 
			
		||||
    msix_clr_pending(dev, vector);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -408,3 +556,66 @@ void msix_unuse_all_vectors(PCIDevice *dev)
 | 
			
		||||
        return;
 | 
			
		||||
    msix_free_irq_entries(dev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Invoke the notifier if vector entry is used and unmasked. */
 | 
			
		||||
static int msix_notify_if_unmasked(PCIDevice *dev, unsigned vector, int masked)
 | 
			
		||||
{
 | 
			
		||||
    assert(dev->msix_mask_notifier);
 | 
			
		||||
    if (!dev->msix_entry_used[vector] || msix_is_masked(dev, vector)) {
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    return dev->msix_mask_notifier(dev, vector, masked);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int msix_set_mask_notifier_for_vector(PCIDevice *dev, unsigned vector)
 | 
			
		||||
{
 | 
			
		||||
	/* Notifier has been set. Invoke it on unmasked vectors. */
 | 
			
		||||
	return msix_notify_if_unmasked(dev, vector, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int msix_unset_mask_notifier_for_vector(PCIDevice *dev, unsigned vector)
 | 
			
		||||
{
 | 
			
		||||
	/* Notifier will be unset. Invoke it to mask unmasked entries. */
 | 
			
		||||
	return msix_notify_if_unmasked(dev, vector, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int msix_set_mask_notifier(PCIDevice *dev, msix_mask_notifier_func f)
 | 
			
		||||
{
 | 
			
		||||
    int r, n;
 | 
			
		||||
    assert(!dev->msix_mask_notifier);
 | 
			
		||||
    dev->msix_mask_notifier = f;
 | 
			
		||||
    for (n = 0; n < dev->msix_entries_nr; ++n) {
 | 
			
		||||
        r = msix_set_mask_notifier_for_vector(dev, n);
 | 
			
		||||
        if (r < 0) {
 | 
			
		||||
            goto undo;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
undo:
 | 
			
		||||
    while (--n >= 0) {
 | 
			
		||||
        msix_unset_mask_notifier_for_vector(dev, n);
 | 
			
		||||
    }
 | 
			
		||||
    dev->msix_mask_notifier = NULL;
 | 
			
		||||
    return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int msix_unset_mask_notifier(PCIDevice *dev)
 | 
			
		||||
{
 | 
			
		||||
    int r, n;
 | 
			
		||||
    assert(dev->msix_mask_notifier);
 | 
			
		||||
    for (n = 0; n < dev->msix_entries_nr; ++n) {
 | 
			
		||||
        r = msix_unset_mask_notifier_for_vector(dev, n);
 | 
			
		||||
        if (r < 0) {
 | 
			
		||||
            goto undo;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    dev->msix_mask_notifier = NULL;
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
undo:
 | 
			
		||||
    while (--n >= 0) {
 | 
			
		||||
        msix_set_mask_notifier_for_vector(dev, n);
 | 
			
		||||
    }
 | 
			
		||||
    return r;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -33,4 +33,6 @@ void msix_reset(PCIDevice *dev);
 | 
			
		||||
 | 
			
		||||
extern int msix_supported;
 | 
			
		||||
 | 
			
		||||
int msix_set_mask_notifier(PCIDevice *dev, msix_mask_notifier_func);
 | 
			
		||||
int msix_unset_mask_notifier(PCIDevice *dev);
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										46
									
								
								hw/pc.c
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								hw/pc.c
									
									
									
									
									
								
							@@ -39,6 +39,7 @@
 | 
			
		||||
#include "msix.h"
 | 
			
		||||
#include "sysbus.h"
 | 
			
		||||
#include "sysemu.h"
 | 
			
		||||
#include "kvm.h"
 | 
			
		||||
#include "blockdev.h"
 | 
			
		||||
#include "ui/qemu-spice.h"
 | 
			
		||||
 | 
			
		||||
@@ -56,6 +57,8 @@
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define BIOS_FILENAME "bios.bin"
 | 
			
		||||
#define EXTBOOT_FILENAME "extboot.bin"
 | 
			
		||||
#define VAPIC_FILENAME "vapic.bin"
 | 
			
		||||
 | 
			
		||||
#define PC_MAX_BIOS_SIZE (4 * 1024 * 1024)
 | 
			
		||||
 | 
			
		||||
@@ -601,7 +604,7 @@ static void *bochs_bios_init(void)
 | 
			
		||||
    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
 | 
			
		||||
    fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES, (uint8_t *)acpi_tables,
 | 
			
		||||
                     acpi_tables_len);
 | 
			
		||||
    fw_cfg_add_bytes(fw_cfg, FW_CFG_IRQ0_OVERRIDE, &irq0override, 1);
 | 
			
		||||
    fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, kvm_allows_irq0_override());
 | 
			
		||||
 | 
			
		||||
    smbios_table = smbios_get_table(&smbios_len);
 | 
			
		||||
    if (smbios_table)
 | 
			
		||||
@@ -921,10 +924,18 @@ static void pc_cpu_reset(void *opaque)
 | 
			
		||||
    env->halted = !cpu_is_bsp(env);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static CPUState *pc_new_cpu(const char *cpu_model)
 | 
			
		||||
CPUState *pc_new_cpu(const char *cpu_model)
 | 
			
		||||
{
 | 
			
		||||
    CPUState *env;
 | 
			
		||||
 | 
			
		||||
    if (cpu_model == NULL) {
 | 
			
		||||
#ifdef TARGET_X86_64
 | 
			
		||||
        cpu_model = "qemu64";
 | 
			
		||||
#else
 | 
			
		||||
        cpu_model = "qemu32";
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    env = cpu_init(cpu_model);
 | 
			
		||||
    if (!env) {
 | 
			
		||||
        fprintf(stderr, "Unable to find x86 CPU definition\n");
 | 
			
		||||
@@ -944,14 +955,6 @@ void pc_cpus_init(const char *cpu_model)
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    /* init CPUs */
 | 
			
		||||
    if (cpu_model == NULL) {
 | 
			
		||||
#ifdef TARGET_X86_64
 | 
			
		||||
        cpu_model = "qemu64";
 | 
			
		||||
#else
 | 
			
		||||
        cpu_model = "qemu32";
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for(i = 0; i < smp_cpus; i++) {
 | 
			
		||||
        pc_new_cpu(cpu_model);
 | 
			
		||||
    }
 | 
			
		||||
@@ -1010,10 +1013,21 @@ void pc_memory_init(const char *kernel_filename,
 | 
			
		||||
    isa_bios_size = bios_size;
 | 
			
		||||
    if (isa_bios_size > (128 * 1024))
 | 
			
		||||
        isa_bios_size = 128 * 1024;
 | 
			
		||||
    cpu_register_physical_memory(0xd0000, (192 * 1024) - isa_bios_size,
 | 
			
		||||
                                 IO_MEM_UNASSIGNED);
 | 
			
		||||
    cpu_register_physical_memory(0x100000 - isa_bios_size,
 | 
			
		||||
                                 isa_bios_size,
 | 
			
		||||
                                 (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM);
 | 
			
		||||
 | 
			
		||||
    if (extboot_drive) {
 | 
			
		||||
        option_rom[nb_option_roms].name = qemu_strdup(EXTBOOT_FILENAME);
 | 
			
		||||
        option_rom[nb_option_roms].bootindex = 0;
 | 
			
		||||
        nb_option_roms++;
 | 
			
		||||
    }
 | 
			
		||||
    option_rom[nb_option_roms].name = qemu_strdup(VAPIC_FILENAME);
 | 
			
		||||
    option_rom[nb_option_roms].bootindex = -1;
 | 
			
		||||
    nb_option_roms++;
 | 
			
		||||
 | 
			
		||||
    option_rom_offset = qemu_ram_alloc(NULL, "pc.rom", PC_ROM_SIZE);
 | 
			
		||||
    cpu_register_physical_memory(PC_ROM_MIN_VGA, PC_ROM_SIZE, option_rom_offset);
 | 
			
		||||
 | 
			
		||||
@@ -1168,4 +1182,16 @@ void pc_pci_device_init(PCIBus *pci_bus)
 | 
			
		||||
    for (bus = 0; bus <= max_bus; bus++) {
 | 
			
		||||
        pci_create_simple(pci_bus, -1, "lsi53c895a");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (extboot_drive) {
 | 
			
		||||
        DriveInfo *info = extboot_drive;
 | 
			
		||||
        int cyls, heads, secs;
 | 
			
		||||
 | 
			
		||||
        if (info->type != IF_IDE && info->type != IF_VIRTIO) {
 | 
			
		||||
            bdrv_guess_geometry(info->bdrv, &cyls, &heads, &secs);
 | 
			
		||||
            bdrv_set_geometry_hint(info->bdrv, cyls, heads, secs);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        extboot_init(info->bdrv);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								hw/pc.h
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								hw/pc.h
									
									
									
									
									
								
							@@ -62,6 +62,7 @@ extern PicState2 *isa_pic;
 | 
			
		||||
void pic_set_irq(int irq, int level);
 | 
			
		||||
void pic_set_irq_new(void *opaque, int irq, int level);
 | 
			
		||||
qemu_irq *i8259_init(qemu_irq parent_irq);
 | 
			
		||||
qemu_irq *kvm_i8259_init(qemu_irq parent_irq);
 | 
			
		||||
int pic_read_irq(PicState2 *s);
 | 
			
		||||
void pic_update_irq(PicState2 *s);
 | 
			
		||||
uint32_t pic_intack_read(PicState2 *s);
 | 
			
		||||
@@ -172,6 +173,9 @@ void pcspk_init(ISADevice *pit);
 | 
			
		||||
int pcspk_audio_init(qemu_irq *pic);
 | 
			
		||||
 | 
			
		||||
/* piix_pci.c */
 | 
			
		||||
/* config space register for IRQ routing */
 | 
			
		||||
#define PIIX_CONFIG_IRQ_ROUTE 0x60
 | 
			
		||||
 | 
			
		||||
struct PCII440FXState;
 | 
			
		||||
typedef struct PCII440FXState PCII440FXState;
 | 
			
		||||
 | 
			
		||||
@@ -182,6 +186,10 @@ void i440fx_init_memory_mappings(PCII440FXState *d);
 | 
			
		||||
extern PCIDevice *piix4_dev;
 | 
			
		||||
int piix4_init(PCIBus *bus, int devfn);
 | 
			
		||||
 | 
			
		||||
int piix_get_irq(int pin);
 | 
			
		||||
 | 
			
		||||
int ipf_map_irq(PCIDevice *pci_dev, int irq_num);
 | 
			
		||||
 | 
			
		||||
/* vga.c */
 | 
			
		||||
enum vga_retrace_method {
 | 
			
		||||
    VGA_RETRACE_DUMB,
 | 
			
		||||
@@ -229,6 +237,10 @@ static inline bool isa_ne2000_init(int base, int irq, NICInfo *nd)
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* extboot.c */
 | 
			
		||||
 | 
			
		||||
void extboot_init(BlockDriverState *bs);
 | 
			
		||||
 | 
			
		||||
/* e820 types */
 | 
			
		||||
#define E820_RAM        1
 | 
			
		||||
#define E820_RESERVED   2
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								hw/pc_piix.c
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								hw/pc_piix.c
									
									
									
									
									
								
							@@ -43,12 +43,16 @@
 | 
			
		||||
#  include <xen/hvm/hvm_info_table.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
qemu_irq *ioapic_irq_hack;
 | 
			
		||||
 | 
			
		||||
#define MAX_IDE_BUS 2
 | 
			
		||||
 | 
			
		||||
static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 };
 | 
			
		||||
static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
 | 
			
		||||
static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
 | 
			
		||||
 | 
			
		||||
const char *global_cpu_model; /* cpu hotadd */
 | 
			
		||||
 | 
			
		||||
static void ioapic_init(IsaIrqState *isa_irq_state)
 | 
			
		||||
{
 | 
			
		||||
    DeviceState *dev;
 | 
			
		||||
@@ -90,6 +94,8 @@ static void pc_init1(ram_addr_t ram_size,
 | 
			
		||||
    BusState *idebus[MAX_IDE_BUS];
 | 
			
		||||
    ISADevice *rtc_state;
 | 
			
		||||
 | 
			
		||||
    global_cpu_model = cpu_model;
 | 
			
		||||
 | 
			
		||||
    pc_cpus_init(cpu_model);
 | 
			
		||||
 | 
			
		||||
    if (kvmclock_enabled) {
 | 
			
		||||
@@ -112,7 +118,11 @@ static void pc_init1(ram_addr_t ram_size,
 | 
			
		||||
 | 
			
		||||
    if (!xen_enabled()) {
 | 
			
		||||
        cpu_irq = pc_allocate_cpu_irq();
 | 
			
		||||
        if (!(kvm_enabled() && kvm_irqchip_in_kernel())) {
 | 
			
		||||
            i8259 = i8259_init(cpu_irq[0]);
 | 
			
		||||
        } else {
 | 
			
		||||
            i8259 = kvm_i8259_init(cpu_irq[0]);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        i8259 = xen_interrupt_controller_init();
 | 
			
		||||
    }
 | 
			
		||||
@@ -121,7 +131,11 @@ static void pc_init1(ram_addr_t ram_size,
 | 
			
		||||
    if (pci_enabled) {
 | 
			
		||||
        ioapic_init(isa_irq_state);
 | 
			
		||||
    }
 | 
			
		||||
    if (!(kvm_enabled() && kvm_irqchip_in_kernel())) {
 | 
			
		||||
        isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
 | 
			
		||||
    } else {
 | 
			
		||||
        isa_irq = i8259;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (pci_enabled) {
 | 
			
		||||
        pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq, ram_size);
 | 
			
		||||
@@ -149,7 +163,7 @@ static void pc_init1(ram_addr_t ram_size,
 | 
			
		||||
        if (!pci_enabled || (nd->model && strcmp(nd->model, "ne2k_isa") == 0))
 | 
			
		||||
            pc_init_ne2k_isa(nd);
 | 
			
		||||
        else
 | 
			
		||||
            pci_nic_init_nofail(nd, "e1000", NULL);
 | 
			
		||||
            pci_nic_init_nofail(nd, "rtl8139", NULL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ide_drive_get(hd, MAX_IDE_BUS);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										140
									
								
								hw/pci.c
									
									
									
									
									
								
							
							
						
						
									
										140
									
								
								hw/pci.c
									
									
									
									
									
								
							@@ -29,8 +29,12 @@
 | 
			
		||||
#include "net.h"
 | 
			
		||||
#include "sysemu.h"
 | 
			
		||||
#include "loader.h"
 | 
			
		||||
#include "hw/pc.h"
 | 
			
		||||
#include "kvm.h"
 | 
			
		||||
#include "device-assignment.h"
 | 
			
		||||
#include "qemu-objects.h"
 | 
			
		||||
#include "range.h"
 | 
			
		||||
#include "msi.h"
 | 
			
		||||
 | 
			
		||||
//#define DEBUG_PCI
 | 
			
		||||
#ifdef DEBUG_PCI
 | 
			
		||||
@@ -346,6 +350,7 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size)
 | 
			
		||||
    memcpy(s->config, config, size);
 | 
			
		||||
 | 
			
		||||
    pci_update_mappings(s);
 | 
			
		||||
    msi_post_load(s);
 | 
			
		||||
 | 
			
		||||
    qemu_free(config);
 | 
			
		||||
    return 0;
 | 
			
		||||
@@ -537,6 +542,83 @@ int pci_parse_devaddr(const char *addr, int *domp, int *busp,
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Parse device seg and bdf in device assignment command:
 | 
			
		||||
 *
 | 
			
		||||
 * -pcidevice host=[seg:]bus:dev.func
 | 
			
		||||
 *
 | 
			
		||||
 * Parse [seg:]<bus>:<slot>.<func> return -1 on error
 | 
			
		||||
 */
 | 
			
		||||
int pci_parse_host_devaddr(const char *addr, int *segp, int *busp,
 | 
			
		||||
                           int *slotp, int *funcp)
 | 
			
		||||
{
 | 
			
		||||
    const char *p;
 | 
			
		||||
    char *e;
 | 
			
		||||
    int val;
 | 
			
		||||
    int seg = 0, bus = 0, slot = 0, func = 0;
 | 
			
		||||
 | 
			
		||||
    /* parse optional seg */
 | 
			
		||||
    p = addr;
 | 
			
		||||
    val = 0;
 | 
			
		||||
    while (1) {
 | 
			
		||||
        p = strchr(p, ':');
 | 
			
		||||
        if (p) {
 | 
			
		||||
            val++;
 | 
			
		||||
            p++;
 | 
			
		||||
        } else
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
    if (val <= 0 || val > 2)
 | 
			
		||||
        return -1;
 | 
			
		||||
 | 
			
		||||
    p = addr;
 | 
			
		||||
    if (val == 2) {
 | 
			
		||||
        val = strtoul(p, &e, 16);
 | 
			
		||||
        if (e == p)
 | 
			
		||||
            return -1;
 | 
			
		||||
        if (*e == ':') {
 | 
			
		||||
            seg = val;
 | 
			
		||||
            p = e + 1;
 | 
			
		||||
        }
 | 
			
		||||
    } else
 | 
			
		||||
        seg = 0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /* parse bdf */
 | 
			
		||||
    val = strtoul(p, &e, 16);
 | 
			
		||||
    if (e == p)
 | 
			
		||||
	return -1;
 | 
			
		||||
    if (*e == ':') {
 | 
			
		||||
	bus = val;
 | 
			
		||||
	p = e + 1;
 | 
			
		||||
	val = strtoul(p, &e, 16);
 | 
			
		||||
	if (e == p)
 | 
			
		||||
	    return -1;
 | 
			
		||||
	if (*e == '.') {
 | 
			
		||||
	    slot = val;
 | 
			
		||||
	    p = e + 1;
 | 
			
		||||
	    val = strtoul(p, &e, 16);
 | 
			
		||||
	    if (e == p)
 | 
			
		||||
		return -1;
 | 
			
		||||
	    func = val;
 | 
			
		||||
	} else
 | 
			
		||||
	    return -1;
 | 
			
		||||
    } else
 | 
			
		||||
	return -1;
 | 
			
		||||
 | 
			
		||||
    if (seg > 0xffff || bus > 0xff || slot > 0x1f || func > 0x7)
 | 
			
		||||
	return -1;
 | 
			
		||||
 | 
			
		||||
    if (*e)
 | 
			
		||||
	return -1;
 | 
			
		||||
 | 
			
		||||
    *segp = seg;
 | 
			
		||||
    *busp = bus;
 | 
			
		||||
    *slotp = slot;
 | 
			
		||||
    *funcp = func;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
 | 
			
		||||
                     unsigned *slotp)
 | 
			
		||||
{
 | 
			
		||||
@@ -711,7 +793,7 @@ static void pci_config_alloc(PCIDevice *pci_dev)
 | 
			
		||||
    pci_dev->cmask = qemu_mallocz(config_size);
 | 
			
		||||
    pci_dev->wmask = qemu_mallocz(config_size);
 | 
			
		||||
    pci_dev->w1cmask = qemu_mallocz(config_size);
 | 
			
		||||
    pci_dev->used = qemu_mallocz(config_size);
 | 
			
		||||
    pci_dev->config_map = qemu_mallocz(config_size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pci_config_free(PCIDevice *pci_dev)
 | 
			
		||||
@@ -720,7 +802,7 @@ static void pci_config_free(PCIDevice *pci_dev)
 | 
			
		||||
    qemu_free(pci_dev->cmask);
 | 
			
		||||
    qemu_free(pci_dev->wmask);
 | 
			
		||||
    qemu_free(pci_dev->w1cmask);
 | 
			
		||||
    qemu_free(pci_dev->used);
 | 
			
		||||
    qemu_free(pci_dev->config_map);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* -1 for devfn means auto assign */
 | 
			
		||||
@@ -751,6 +833,8 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
 | 
			
		||||
    pci_dev->irq_state = 0;
 | 
			
		||||
    pci_config_alloc(pci_dev);
 | 
			
		||||
 | 
			
		||||
    memset(pci_dev->config_map, 0xff, PCI_CONFIG_HEADER_SIZE);
 | 
			
		||||
 | 
			
		||||
    pci_config_set_vendor_id(pci_dev->config, info->vendor_id);
 | 
			
		||||
    pci_config_set_device_id(pci_dev->config, info->device_id);
 | 
			
		||||
    pci_config_set_revision(pci_dev->config, info->revision);
 | 
			
		||||
@@ -1126,6 +1210,14 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
 | 
			
		||||
        d->config[addr + i] = (d->config[addr + i] & ~wmask) | (val & wmask);
 | 
			
		||||
        d->config[addr + i] &= ~(val & w1cmask); /* W1C: Write 1 to Clear */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_KVM_DEVICE_ASSIGNMENT
 | 
			
		||||
    if (kvm_enabled() && kvm_irqchip_in_kernel() &&
 | 
			
		||||
        addr >= PIIX_CONFIG_IRQ_ROUTE &&
 | 
			
		||||
	addr < PIIX_CONFIG_IRQ_ROUTE + 4)
 | 
			
		||||
        assigned_dev_update_irqs();
 | 
			
		||||
#endif /* CONFIG_KVM_DEVICE_ASSIGNMENT */
 | 
			
		||||
 | 
			
		||||
    if (ranges_overlap(addr, l, PCI_BASE_ADDRESS_0, 24) ||
 | 
			
		||||
        ranges_overlap(addr, l, PCI_ROM_ADDRESS, 4) ||
 | 
			
		||||
        ranges_overlap(addr, l, PCI_ROM_ADDRESS1, 4) ||
 | 
			
		||||
@@ -1149,6 +1241,10 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
 | 
			
		||||
    if (!change)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
#if defined(TARGET_IA64)
 | 
			
		||||
    ioapic_set_irq(pci_dev, irq_num, level);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    pci_set_irq_state(pci_dev, irq_num, level);
 | 
			
		||||
    pci_update_irq_status(pci_dev);
 | 
			
		||||
    if (pci_irq_disabled(pci_dev))
 | 
			
		||||
@@ -1156,6 +1252,11 @@ static void pci_set_irq(void *opaque, int irq_num, int level)
 | 
			
		||||
    pci_change_irq_level(pci_dev, irq_num, change);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int pci_map_irq(PCIDevice *pci_dev, int pin)
 | 
			
		||||
{
 | 
			
		||||
    return pci_dev->bus->map_irq(pci_dev, pin);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/***********************************************************/
 | 
			
		||||
/* monitor info on PCI */
 | 
			
		||||
 | 
			
		||||
@@ -1798,7 +1899,7 @@ static int pci_find_space(PCIDevice *pdev, uint8_t size)
 | 
			
		||||
    int offset = PCI_CONFIG_HEADER_SIZE;
 | 
			
		||||
    int i;
 | 
			
		||||
    for (i = PCI_CONFIG_HEADER_SIZE; i < config_size; ++i)
 | 
			
		||||
        if (pdev->used[i])
 | 
			
		||||
        if (pdev->config_map[i])
 | 
			
		||||
            offset = i + 1;
 | 
			
		||||
        else if (i - offset + 1 == size)
 | 
			
		||||
            return offset;
 | 
			
		||||
@@ -1823,7 +1924,7 @@ static uint8_t pci_find_capability_list(PCIDevice *pdev, uint8_t cap_id,
 | 
			
		||||
    return next;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pci_map_option_rom(PCIDevice *pdev, int region_num, pcibus_t addr, pcibus_t size, int type)
 | 
			
		||||
void pci_map_option_rom(PCIDevice *pdev, int region_num, pcibus_t addr, pcibus_t size, int type)
 | 
			
		||||
{
 | 
			
		||||
    cpu_register_physical_memory(addr, size, pdev->rom_offset);
 | 
			
		||||
}
 | 
			
		||||
@@ -1975,18 +2076,34 @@ int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
 | 
			
		||||
        if (!offset) {
 | 
			
		||||
            return -ENOSPC;
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        int i;
 | 
			
		||||
 | 
			
		||||
        for (i = offset; i < offset + size; i++) {
 | 
			
		||||
            if (pdev->config_map[i]) {
 | 
			
		||||
                fprintf(stderr, "ERROR: %04x:%02x:%02x.%x "
 | 
			
		||||
                        "Attempt to add PCI capability %x at offset "
 | 
			
		||||
                        "%x overlaps existing capability %x at offset %x\n",
 | 
			
		||||
                        pci_find_domain(pdev->bus), pci_bus_num(pdev->bus),
 | 
			
		||||
                        PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
 | 
			
		||||
                        cap_id, offset, pdev->config_map[i], i);
 | 
			
		||||
                return -EINVAL;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    config = pdev->config + offset;
 | 
			
		||||
    config[PCI_CAP_LIST_ID] = cap_id;
 | 
			
		||||
    config[PCI_CAP_LIST_NEXT] = pdev->config[PCI_CAPABILITY_LIST];
 | 
			
		||||
    pdev->config[PCI_CAPABILITY_LIST] = offset;
 | 
			
		||||
    pdev->config[PCI_STATUS] |= PCI_STATUS_CAP_LIST;
 | 
			
		||||
    memset(pdev->used + offset, 0xFF, size);
 | 
			
		||||
    memset(pdev->config_map + offset, cap_id, size);
 | 
			
		||||
    /* Make capability read-only by default */
 | 
			
		||||
    memset(pdev->wmask + offset, 0, size);
 | 
			
		||||
    /* Check capability by default */
 | 
			
		||||
    memset(pdev->cmask + offset, 0xFF, size);
 | 
			
		||||
 | 
			
		||||
    pdev->config[PCI_STATUS] |= PCI_STATUS_CAP_LIST;
 | 
			
		||||
 | 
			
		||||
    return offset;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -2002,16 +2119,11 @@ void pci_del_capability(PCIDevice *pdev, uint8_t cap_id, uint8_t size)
 | 
			
		||||
    memset(pdev->w1cmask + offset, 0, size);
 | 
			
		||||
    /* Clear cmask as device-specific registers can't be checked */
 | 
			
		||||
    memset(pdev->cmask + offset, 0, size);
 | 
			
		||||
    memset(pdev->used + offset, 0, size);
 | 
			
		||||
    memset(pdev->config_map + offset, 0, size);
 | 
			
		||||
 | 
			
		||||
    if (!pdev->config[PCI_CAPABILITY_LIST])
 | 
			
		||||
    if (!pdev->config[PCI_CAPABILITY_LIST]) {
 | 
			
		||||
        pdev->config[PCI_STATUS] &= ~PCI_STATUS_CAP_LIST;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Reserve space for capability at a known offset (to call after load). */
 | 
			
		||||
void pci_reserve_capability(PCIDevice *pdev, uint8_t offset, uint8_t size)
 | 
			
		||||
{
 | 
			
		||||
    memset(pdev->used + offset, 0xff, size);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint8_t pci_find_capability(PCIDevice *pdev, uint8_t cap_id)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										35
									
								
								hw/pci.h
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								hw/pci.h
									
									
									
									
									
								
							@@ -5,6 +5,7 @@
 | 
			
		||||
#include "qobject.h"
 | 
			
		||||
 | 
			
		||||
#include "qdev.h"
 | 
			
		||||
#include "kvm.h"
 | 
			
		||||
 | 
			
		||||
/* PCI includes legacy ISA access.  */
 | 
			
		||||
#include "isa.h"
 | 
			
		||||
@@ -127,6 +128,9 @@ enum {
 | 
			
		||||
    QEMU_PCI_CAP_SERR = (1 << QEMU_PCI_CAP_SERR_BITNR),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef int (*msix_mask_notifier_func)(PCIDevice *, unsigned vector,
 | 
			
		||||
				       int masked);
 | 
			
		||||
 | 
			
		||||
struct PCIDevice {
 | 
			
		||||
    DeviceState qdev;
 | 
			
		||||
    /* PCI config space */
 | 
			
		||||
@@ -142,8 +146,8 @@ struct PCIDevice {
 | 
			
		||||
    /* Used to implement RW1C(Write 1 to Clear) bytes */
 | 
			
		||||
    uint8_t *w1cmask;
 | 
			
		||||
 | 
			
		||||
    /* Used to allocate config space for capabilities. */
 | 
			
		||||
    uint8_t *used;
 | 
			
		||||
    /* Used to allocate config space and track capabilities. */
 | 
			
		||||
    uint8_t *config_map;
 | 
			
		||||
 | 
			
		||||
    /* the following fields are read only */
 | 
			
		||||
    PCIBus *bus;
 | 
			
		||||
@@ -191,6 +195,21 @@ struct PCIDevice {
 | 
			
		||||
    char *romfile;
 | 
			
		||||
    ram_addr_t rom_offset;
 | 
			
		||||
    uint32_t rom_bar;
 | 
			
		||||
 | 
			
		||||
    /* MSI entries */
 | 
			
		||||
    int msi_entries_nr;
 | 
			
		||||
    struct KVMMsiMessage *msi_irq_entries;
 | 
			
		||||
 | 
			
		||||
    /* How much space does an MSIX table need. */
 | 
			
		||||
    /* The spec requires giving the table structure
 | 
			
		||||
     * a 4K aligned region all by itself. Align it to
 | 
			
		||||
     * target pages so that drivers can do passthrough
 | 
			
		||||
     * on the rest of the region. */
 | 
			
		||||
    target_phys_addr_t msix_page_size;
 | 
			
		||||
 | 
			
		||||
    KVMMsiMessage *msix_irq_entries;
 | 
			
		||||
 | 
			
		||||
    msix_mask_notifier_func msix_mask_notifier;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
PCIDevice *pci_register_device(PCIBus *bus, const char *name,
 | 
			
		||||
@@ -204,23 +223,24 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num,
 | 
			
		||||
void pci_register_bar_simple(PCIDevice *pci_dev, int region_num,
 | 
			
		||||
                             pcibus_t size, uint8_t attr, ram_addr_t ram_addr);
 | 
			
		||||
 | 
			
		||||
void pci_map_option_rom(PCIDevice *pdev, int region_num, pcibus_t addr,
 | 
			
		||||
                        pcibus_t size, int type);
 | 
			
		||||
 | 
			
		||||
int pci_map_irq(PCIDevice *pci_dev, int pin);
 | 
			
		||||
 | 
			
		||||
int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
 | 
			
		||||
                       uint8_t offset, uint8_t size);
 | 
			
		||||
 | 
			
		||||
void pci_del_capability(PCIDevice *pci_dev, uint8_t cap_id, uint8_t cap_size);
 | 
			
		||||
 | 
			
		||||
void pci_reserve_capability(PCIDevice *pci_dev, uint8_t offset, uint8_t size);
 | 
			
		||||
 | 
			
		||||
uint8_t pci_find_capability(PCIDevice *pci_dev, uint8_t cap_id);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
uint32_t pci_default_read_config(PCIDevice *d,
 | 
			
		||||
                                 uint32_t address, int len);
 | 
			
		||||
void pci_default_write_config(PCIDevice *d,
 | 
			
		||||
                              uint32_t address, uint32_t val, int len);
 | 
			
		||||
void pci_device_save(PCIDevice *s, QEMUFile *f);
 | 
			
		||||
int pci_device_load(PCIDevice *s, QEMUFile *f);
 | 
			
		||||
 | 
			
		||||
typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level);
 | 
			
		||||
typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num);
 | 
			
		||||
 | 
			
		||||
@@ -265,6 +285,9 @@ int pci_parse_devaddr(const char *addr, int *domp, int *busp,
 | 
			
		||||
int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
 | 
			
		||||
                     unsigned *slotp);
 | 
			
		||||
 | 
			
		||||
int pci_parse_host_devaddr(const char *addr, int *segp, int *busp,
 | 
			
		||||
                           int *slotp, int *funcp);
 | 
			
		||||
 | 
			
		||||
void do_pci_info_print(Monitor *mon, const QObject *data);
 | 
			
		||||
void do_pci_info(Monitor *mon, QObject **ret_data);
 | 
			
		||||
void pci_bridge_update_mappings(PCIBus *b);
 | 
			
		||||
 
 | 
			
		||||
@@ -44,9 +44,16 @@
 | 
			
		||||
#define PCI_STATUS		0x06	/* 16 bits */
 | 
			
		||||
#define  PCI_STATUS_INTERRUPT	0x08	/* Interrupt status */
 | 
			
		||||
#define  PCI_STATUS_CAP_LIST	0x10	/* Support Capability List */
 | 
			
		||||
 | 
			
		||||
#ifndef PCI_STATUS_66MHZ
 | 
			
		||||
#define  PCI_STATUS_66MHZ	0x20	/* Support 66 Mhz PCI 2.1 bus */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define  PCI_STATUS_UDF		0x40	/* Support User Definable Features [obsolete] */
 | 
			
		||||
#ifndef PCI_STATUS_FAST_BACK
 | 
			
		||||
#define  PCI_STATUS_FAST_BACK	0x80	/* Accept fast-back to back */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define  PCI_STATUS_PARITY	0x100	/* Detected parity error */
 | 
			
		||||
#define  PCI_STATUS_DEVSEL_MASK	0x600	/* DEVSEL timing */
 | 
			
		||||
#define  PCI_STATUS_DEVSEL_FAST		0x000
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										51
									
								
								hw/pcspk.c
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								hw/pcspk.c
									
									
									
									
									
								
							@@ -27,6 +27,8 @@
 | 
			
		||||
#include "isa.h"
 | 
			
		||||
#include "audio/audio.h"
 | 
			
		||||
#include "qemu-timer.h"
 | 
			
		||||
#include "i8254.h"
 | 
			
		||||
#include "qemu-kvm.h"
 | 
			
		||||
 | 
			
		||||
#define PCSPK_BUF_LEN 1792
 | 
			
		||||
#define PCSPK_SAMPLE_RATE 32000
 | 
			
		||||
@@ -48,6 +50,46 @@ typedef struct {
 | 
			
		||||
static const char *s_spk = "pcspk";
 | 
			
		||||
static PCSpkState pcspk_state;
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_KVM_PIT
 | 
			
		||||
static void kvm_get_pit_ch2(ISADevice *dev,
 | 
			
		||||
                            struct kvm_pit_state *inkernel_state)
 | 
			
		||||
{
 | 
			
		||||
    struct PITState *pit = DO_UPCAST(struct PITState, dev, dev);
 | 
			
		||||
    struct kvm_pit_state pit_state;
 | 
			
		||||
 | 
			
		||||
    if (kvm_enabled() && kvm_pit_in_kernel()) {
 | 
			
		||||
        kvm_get_pit(kvm_state, &pit_state);
 | 
			
		||||
        pit->channels[2].mode = pit_state.channels[2].mode;
 | 
			
		||||
        pit->channels[2].count = pit_state.channels[2].count;
 | 
			
		||||
        pit->channels[2].count_load_time = pit_state.channels[2].count_load_time;
 | 
			
		||||
        pit->channels[2].gate = pit_state.channels[2].gate;
 | 
			
		||||
        if (inkernel_state) {
 | 
			
		||||
            memcpy(inkernel_state, &pit_state, sizeof(*inkernel_state));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void kvm_set_pit_ch2(ISADevice *dev,
 | 
			
		||||
                            struct kvm_pit_state *inkernel_state)
 | 
			
		||||
{
 | 
			
		||||
    struct PITState *pit = DO_UPCAST(struct PITState, dev, dev);
 | 
			
		||||
 | 
			
		||||
    if (kvm_enabled() && kvm_pit_in_kernel()) {
 | 
			
		||||
        inkernel_state->channels[2].mode = pit->channels[2].mode;
 | 
			
		||||
        inkernel_state->channels[2].count = pit->channels[2].count;
 | 
			
		||||
        inkernel_state->channels[2].count_load_time =
 | 
			
		||||
            pit->channels[2].count_load_time;
 | 
			
		||||
        inkernel_state->channels[2].gate = pit->channels[2].gate;
 | 
			
		||||
        kvm_set_pit(kvm_state, inkernel_state);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
static inline void kvm_get_pit_ch2(ISADevice *dev,
 | 
			
		||||
                                   struct kvm_pit_state *inkernel_state) { }
 | 
			
		||||
static inline void kvm_set_pit_ch2(ISADevice *dev,
 | 
			
		||||
                                   struct kvm_pit_state *inkernel_state) { }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static inline void generate_samples(PCSpkState *s)
 | 
			
		||||
{
 | 
			
		||||
    unsigned int i;
 | 
			
		||||
@@ -72,6 +114,8 @@ static void pcspk_callback(void *opaque, int free)
 | 
			
		||||
    PCSpkState *s = opaque;
 | 
			
		||||
    unsigned int n;
 | 
			
		||||
 | 
			
		||||
    kvm_get_pit_ch2(s->pit, NULL);
 | 
			
		||||
 | 
			
		||||
    if (pit_get_mode(s->pit, 2) != 3)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
@@ -117,6 +161,8 @@ static uint32_t pcspk_ioport_read(void *opaque, uint32_t addr)
 | 
			
		||||
    PCSpkState *s = opaque;
 | 
			
		||||
    int out;
 | 
			
		||||
 | 
			
		||||
    kvm_get_pit_ch2(s->pit, NULL);
 | 
			
		||||
 | 
			
		||||
    s->dummy_refresh_clock ^= (1 << 4);
 | 
			
		||||
    out = pit_get_out(s->pit, 2, qemu_get_clock_ns(vm_clock)) << 5;
 | 
			
		||||
 | 
			
		||||
@@ -125,9 +171,12 @@ static uint32_t pcspk_ioport_read(void *opaque, uint32_t addr)
 | 
			
		||||
 | 
			
		||||
static void pcspk_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 | 
			
		||||
{
 | 
			
		||||
    struct kvm_pit_state inkernel_state;
 | 
			
		||||
    PCSpkState *s = opaque;
 | 
			
		||||
    const int gate = val & 1;
 | 
			
		||||
 | 
			
		||||
    kvm_get_pit_ch2(s->pit, &inkernel_state);
 | 
			
		||||
 | 
			
		||||
    s->data_on = (val >> 1) & 1;
 | 
			
		||||
    pit_set_gate(s->pit, 2, gate);
 | 
			
		||||
    if (s->voice) {
 | 
			
		||||
@@ -135,6 +184,8 @@ static void pcspk_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 | 
			
		||||
            s->play_pos = 0;
 | 
			
		||||
        AUD_set_active_out(s->voice, gate & s->data_on);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    kvm_set_pit_ch2(s->pit, &inkernel_state);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void pcspk_init(ISADevice *pit)
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,7 @@
 | 
			
		||||
#include "sysbus.h"
 | 
			
		||||
#include "range.h"
 | 
			
		||||
#include "xen.h"
 | 
			
		||||
#include "kvm.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * I440FX chipset data sheet.
 | 
			
		||||
@@ -238,6 +239,8 @@ static int i440fx_initfn(PCIDevice *dev)
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PIIX3State *piix3_dev;
 | 
			
		||||
 | 
			
		||||
static PCIBus *i440fx_common_init(const char *device_name,
 | 
			
		||||
                                  PCII440FXState **pi440fx_state,
 | 
			
		||||
                                  int *piix3_devfn,
 | 
			
		||||
@@ -284,6 +287,8 @@ static PCIBus *i440fx_common_init(const char *device_name,
 | 
			
		||||
        ram_size = 255;
 | 
			
		||||
    (*pi440fx_state)->dev.config[0x57]=ram_size;
 | 
			
		||||
 | 
			
		||||
    piix3_dev = piix3;
 | 
			
		||||
 | 
			
		||||
    return b;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -354,6 +359,13 @@ static void piix3_write_config(PCIDevice *dev,
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int piix_get_irq(int pin)
 | 
			
		||||
{
 | 
			
		||||
    if (piix3_dev)
 | 
			
		||||
        return piix3_dev->dev.config[0x60+pin];
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void piix3_write_config_xen(PCIDevice *dev,
 | 
			
		||||
                               uint32_t address, uint32_t val, int len)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										140
									
								
								hw/testdev.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								hw/testdev.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,140 @@
 | 
			
		||||
#include <sys/mman.h>
 | 
			
		||||
#include "hw.h"
 | 
			
		||||
#include "qdev.h"
 | 
			
		||||
#include "isa.h"
 | 
			
		||||
 | 
			
		||||
struct testdev {
 | 
			
		||||
    ISADevice dev;
 | 
			
		||||
    CharDriverState *chr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void test_device_serial_write(void *opaque, uint32_t addr, uint32_t data)
 | 
			
		||||
{
 | 
			
		||||
    struct testdev *dev = opaque;
 | 
			
		||||
    uint8_t buf[1] = { data };
 | 
			
		||||
 | 
			
		||||
    if (dev->chr) {
 | 
			
		||||
        qemu_chr_write(dev->chr, buf, 1);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void test_device_exit(void *opaque, uint32_t addr, uint32_t data)
 | 
			
		||||
{
 | 
			
		||||
    exit(data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t test_device_memsize_read(void *opaque, uint32_t addr)
 | 
			
		||||
{
 | 
			
		||||
    return ram_size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void test_device_irq_line(void *opaque, uint32_t addr, uint32_t data)
 | 
			
		||||
{
 | 
			
		||||
    qemu_set_irq(isa_get_irq(addr - 0x2000), !!data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32 test_device_ioport_data;
 | 
			
		||||
 | 
			
		||||
static void test_device_ioport_write(void *opaque, uint32_t addr, uint32_t data)
 | 
			
		||||
{
 | 
			
		||||
    test_device_ioport_data = data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t test_device_ioport_read(void *opaque, uint32_t addr)
 | 
			
		||||
{
 | 
			
		||||
    return test_device_ioport_data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void test_device_flush_page(void *opaque, uint32_t addr, uint32_t data)
 | 
			
		||||
{
 | 
			
		||||
    target_phys_addr_t len = 4096;
 | 
			
		||||
    void *a = cpu_physical_memory_map(data & ~0xffful, &len, 0);
 | 
			
		||||
 | 
			
		||||
    mprotect(a, 4096, PROT_NONE);
 | 
			
		||||
    mprotect(a, 4096, PROT_READ|PROT_WRITE);
 | 
			
		||||
    cpu_physical_memory_unmap(a, len, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *iomem_buf;
 | 
			
		||||
 | 
			
		||||
static uint32_t test_iomem_readb(void *opaque, target_phys_addr_t addr)
 | 
			
		||||
{
 | 
			
		||||
    return iomem_buf[addr];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t test_iomem_readw(void *opaque, target_phys_addr_t addr)
 | 
			
		||||
{
 | 
			
		||||
    return *(uint16_t*)(iomem_buf + addr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint32_t test_iomem_readl(void *opaque, target_phys_addr_t addr)
 | 
			
		||||
{
 | 
			
		||||
    return *(uint32_t*)(iomem_buf + addr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void test_iomem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
 | 
			
		||||
{
 | 
			
		||||
    iomem_buf[addr] = val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void test_iomem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
 | 
			
		||||
{
 | 
			
		||||
    *(uint16_t*)(iomem_buf + addr) = val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void test_iomem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
 | 
			
		||||
{
 | 
			
		||||
    *(uint32_t*)(iomem_buf + addr) = val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static CPUReadMemoryFunc * const test_iomem_read[3] = {
 | 
			
		||||
    test_iomem_readb,
 | 
			
		||||
    test_iomem_readw,
 | 
			
		||||
    test_iomem_readl,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static CPUWriteMemoryFunc * const test_iomem_write[3] = {
 | 
			
		||||
    test_iomem_writeb,
 | 
			
		||||
    test_iomem_writew,
 | 
			
		||||
    test_iomem_writel,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int init_test_device(ISADevice *isa)
 | 
			
		||||
{
 | 
			
		||||
    struct testdev *dev = DO_UPCAST(struct testdev, dev, isa);
 | 
			
		||||
    int iomem;
 | 
			
		||||
 | 
			
		||||
    register_ioport_write(0xf1, 1, 1, test_device_serial_write, dev);
 | 
			
		||||
    register_ioport_write(0xf4, 1, 4, test_device_exit, dev);
 | 
			
		||||
    register_ioport_read(0xd1, 1, 4, test_device_memsize_read, dev);
 | 
			
		||||
    register_ioport_read(0xe0, 1, 1, test_device_ioport_read, dev);
 | 
			
		||||
    register_ioport_write(0xe0, 1, 1, test_device_ioport_write, dev);
 | 
			
		||||
    register_ioport_read(0xe0, 1, 2, test_device_ioport_read, dev);
 | 
			
		||||
    register_ioport_write(0xe0, 1, 2, test_device_ioport_write, dev);
 | 
			
		||||
    register_ioport_read(0xe0, 1, 4, test_device_ioport_read, dev);
 | 
			
		||||
    register_ioport_write(0xe0, 1, 4, test_device_ioport_write, dev);
 | 
			
		||||
    register_ioport_write(0xe4, 1, 4, test_device_flush_page, dev);
 | 
			
		||||
    register_ioport_write(0x2000, 24, 1, test_device_irq_line, NULL);
 | 
			
		||||
    iomem_buf = qemu_mallocz(0x10000);
 | 
			
		||||
    iomem = cpu_register_io_memory(test_iomem_read, test_iomem_write, NULL,
 | 
			
		||||
                                   DEVICE_NATIVE_ENDIAN);
 | 
			
		||||
    cpu_register_physical_memory(0xff000000, 0x10000, iomem);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ISADeviceInfo testdev_info = {
 | 
			
		||||
    .qdev.name  = "testdev",
 | 
			
		||||
    .qdev.size  = sizeof(struct testdev),
 | 
			
		||||
    .init       = init_test_device,
 | 
			
		||||
    .qdev.props = (Property[]) {
 | 
			
		||||
        DEFINE_PROP_CHR("chardev", struct testdev, chr),
 | 
			
		||||
        DEFINE_PROP_END_OF_LIST(),
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void testdev_register_devices(void)
 | 
			
		||||
{
 | 
			
		||||
    isa_qdev_register(&testdev_info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
device_init(testdev_register_devices)
 | 
			
		||||
							
								
								
									
										3
									
								
								hw/vga.c
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								hw/vga.c
									
									
									
									
									
								
							@@ -1885,6 +1885,9 @@ static void vga_update_display(void *opaque)
 | 
			
		||||
            vga_draw_text(s, full_update);
 | 
			
		||||
            break;
 | 
			
		||||
        case GMODE_GRAPH:
 | 
			
		||||
#ifdef TARGET_IA64
 | 
			
		||||
            full_update = 1;
 | 
			
		||||
#endif
 | 
			
		||||
            vga_draw_graphic(s, full_update);
 | 
			
		||||
            break;
 | 
			
		||||
        case GMODE_BLANK:
 | 
			
		||||
 
 | 
			
		||||
@@ -33,8 +33,8 @@
 | 
			
		||||
/* bochs VBE support */
 | 
			
		||||
#define CONFIG_BOCHS_VBE
 | 
			
		||||
 | 
			
		||||
#define VBE_DISPI_MAX_XRES              1600
 | 
			
		||||
#define VBE_DISPI_MAX_YRES              1200
 | 
			
		||||
#define VBE_DISPI_MAX_XRES              2560
 | 
			
		||||
#define VBE_DISPI_MAX_YRES              1600
 | 
			
		||||
#define VBE_DISPI_MAX_BPP               32
 | 
			
		||||
 | 
			
		||||
#define VBE_DISPI_INDEX_ID              0x0
 | 
			
		||||
@@ -225,7 +225,7 @@ void vga_init_vbe(VGACommonState *s);
 | 
			
		||||
extern const uint8_t sr_mask[8];
 | 
			
		||||
extern const uint8_t gr_mask[16];
 | 
			
		||||
 | 
			
		||||
#define VGA_RAM_SIZE (8192 * 1024)
 | 
			
		||||
#define VGA_RAM_SIZE (16 * 1024 * 1024)
 | 
			
		||||
#define VGABIOS_FILENAME "vgabios.bin"
 | 
			
		||||
#define VGABIOS_CIRRUS_FILENAME "vgabios-cirrus.bin"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,9 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Virtio Block Device
 | 
			
		||||
 * Virtio Balloon Device
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright IBM, Corp. 2008
 | 
			
		||||
 * Copyright (C) 2011 Red Hat, Inc.
 | 
			
		||||
 * Copyright (C) 2011 Amit Shah <amit.shah@redhat.com>
 | 
			
		||||
 *
 | 
			
		||||
 * Authors:
 | 
			
		||||
 *  Anthony Liguori   <aliguori@us.ibm.com>
 | 
			
		||||
@@ -43,6 +45,7 @@ typedef struct VirtIOBalloon
 | 
			
		||||
    size_t stats_vq_offset;
 | 
			
		||||
    MonitorCompletion *stats_callback;
 | 
			
		||||
    void *stats_opaque_callback_data;
 | 
			
		||||
    DeviceState *qdev;
 | 
			
		||||
} VirtIOBalloon;
 | 
			
		||||
 | 
			
		||||
static VirtIOBalloon *to_virtio_balloon(VirtIODevice *vdev)
 | 
			
		||||
@@ -199,18 +202,11 @@ static uint32_t virtio_balloon_get_features(VirtIODevice *vdev, uint32_t f)
 | 
			
		||||
    return f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void virtio_balloon_to_target(void *opaque, ram_addr_t target,
 | 
			
		||||
                                     MonitorCompletion cb, void *cb_data)
 | 
			
		||||
static void virtio_balloon_stat(void *opaque, MonitorCompletion cb,
 | 
			
		||||
                                void *cb_data)
 | 
			
		||||
{
 | 
			
		||||
    VirtIOBalloon *dev = opaque;
 | 
			
		||||
 | 
			
		||||
    if (target > ram_size)
 | 
			
		||||
        target = ram_size;
 | 
			
		||||
 | 
			
		||||
    if (target) {
 | 
			
		||||
        dev->num_pages = (ram_size - target) >> VIRTIO_BALLOON_PFN_SHIFT;
 | 
			
		||||
        virtio_notify_config(&dev->vdev);
 | 
			
		||||
    } else {
 | 
			
		||||
    /* For now, only allow one request at a time.  This restriction can be
 | 
			
		||||
     * removed later by queueing callback and data pairs.
 | 
			
		||||
     */
 | 
			
		||||
@@ -219,16 +215,31 @@ static void virtio_balloon_to_target(void *opaque, ram_addr_t target,
 | 
			
		||||
    }
 | 
			
		||||
    dev->stats_callback = cb;
 | 
			
		||||
    dev->stats_opaque_callback_data = cb_data;
 | 
			
		||||
        if (ENABLE_GUEST_STATS && (dev->vdev.guest_features & (1 << VIRTIO_BALLOON_F_STATS_VQ))) {
 | 
			
		||||
 | 
			
		||||
    if (ENABLE_GUEST_STATS
 | 
			
		||||
        && (dev->vdev.guest_features & (1 << VIRTIO_BALLOON_F_STATS_VQ))) {
 | 
			
		||||
        virtqueue_push(dev->svq, &dev->stats_vq_elem, dev->stats_vq_offset);
 | 
			
		||||
        virtio_notify(&dev->vdev, dev->svq);
 | 
			
		||||
        } else {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Stats are not supported.  Clear out any stale values that might
 | 
			
		||||
     * have been set by a more featureful guest kernel.
 | 
			
		||||
     */
 | 
			
		||||
    reset_stats(dev);
 | 
			
		||||
    complete_stats_request(dev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void virtio_balloon_to_target(void *opaque, ram_addr_t target)
 | 
			
		||||
{
 | 
			
		||||
    VirtIOBalloon *dev = opaque;
 | 
			
		||||
 | 
			
		||||
    if (target > ram_size) {
 | 
			
		||||
        target = ram_size;
 | 
			
		||||
    }
 | 
			
		||||
    if (target) {
 | 
			
		||||
        dev->num_pages = (ram_size - target) >> VIRTIO_BALLOON_PFN_SHIFT;
 | 
			
		||||
        virtio_notify_config(&dev->vdev);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -259,6 +270,7 @@ static int virtio_balloon_load(QEMUFile *f, void *opaque, int version_id)
 | 
			
		||||
VirtIODevice *virtio_balloon_init(DeviceState *dev)
 | 
			
		||||
{
 | 
			
		||||
    VirtIOBalloon *s;
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    s = (VirtIOBalloon *)virtio_common_init("virtio-balloon",
 | 
			
		||||
                                            VIRTIO_ID_BALLOON,
 | 
			
		||||
@@ -268,15 +280,29 @@ VirtIODevice *virtio_balloon_init(DeviceState *dev)
 | 
			
		||||
    s->vdev.set_config = virtio_balloon_set_config;
 | 
			
		||||
    s->vdev.get_features = virtio_balloon_get_features;
 | 
			
		||||
 | 
			
		||||
    ret = qemu_add_balloon_handler(virtio_balloon_to_target,
 | 
			
		||||
                                   virtio_balloon_stat, s);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        virtio_cleanup(&s->vdev);
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    s->ivq = virtio_add_queue(&s->vdev, 128, virtio_balloon_handle_output);
 | 
			
		||||
    s->dvq = virtio_add_queue(&s->vdev, 128, virtio_balloon_handle_output);
 | 
			
		||||
    s->svq = virtio_add_queue(&s->vdev, 128, virtio_balloon_receive_stats);
 | 
			
		||||
 | 
			
		||||
    reset_stats(s);
 | 
			
		||||
    qemu_add_balloon_handler(virtio_balloon_to_target, s);
 | 
			
		||||
 | 
			
		||||
    s->qdev = dev;
 | 
			
		||||
    register_savevm(dev, "virtio-balloon", -1, 1,
 | 
			
		||||
                    virtio_balloon_save, virtio_balloon_load, s);
 | 
			
		||||
 | 
			
		||||
    return &s->vdev;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void virtio_balloon_exit(VirtIODevice *vdev)
 | 
			
		||||
{
 | 
			
		||||
    VirtIOBalloon *s = DO_UPCAST(VirtIOBalloon, vdev, vdev);
 | 
			
		||||
    unregister_savevm(s->qdev, "virtio-balloon", s);
 | 
			
		||||
    virtio_cleanup(vdev);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -545,6 +545,57 @@ static void virtio_pci_guest_notifier_read(void *opaque)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int virtio_pci_mask_vq(PCIDevice *dev, unsigned vector,
 | 
			
		||||
                              VirtQueue *vq, int masked)
 | 
			
		||||
{
 | 
			
		||||
    EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
 | 
			
		||||
    int r = kvm_set_irqfd(dev->msix_irq_entries[vector].gsi,
 | 
			
		||||
                          event_notifier_get_fd(notifier),
 | 
			
		||||
                          !masked);
 | 
			
		||||
    if (r < 0) {
 | 
			
		||||
        return (r == -ENOSYS) ? 0 : r;
 | 
			
		||||
    }
 | 
			
		||||
    if (masked) {
 | 
			
		||||
        qemu_set_fd_handler(event_notifier_get_fd(notifier),
 | 
			
		||||
                            virtio_pci_guest_notifier_read, NULL, vq);
 | 
			
		||||
    } else {
 | 
			
		||||
        qemu_set_fd_handler(event_notifier_get_fd(notifier),
 | 
			
		||||
                            NULL, NULL, NULL);
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int virtio_pci_mask_notifier(PCIDevice *dev, unsigned vector,
 | 
			
		||||
                                    int masked)
 | 
			
		||||
{
 | 
			
		||||
    VirtIOPCIProxy *proxy = container_of(dev, VirtIOPCIProxy, pci_dev);
 | 
			
		||||
    VirtIODevice *vdev = proxy->vdev;
 | 
			
		||||
    int r, n;
 | 
			
		||||
 | 
			
		||||
    for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
 | 
			
		||||
        if (!virtio_queue_get_num(vdev, n)) {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        if (virtio_queue_vector(vdev, n) != vector) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        r = virtio_pci_mask_vq(dev, vector, virtio_get_queue(vdev, n), masked);
 | 
			
		||||
        if (r < 0) {
 | 
			
		||||
            goto undo;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
undo:
 | 
			
		||||
    while (--n >= 0) {
 | 
			
		||||
        if (virtio_queue_vector(vdev, n) != vector) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        virtio_pci_mask_vq(dev, vector, virtio_get_queue(vdev, n), !masked);
 | 
			
		||||
    }
 | 
			
		||||
    return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign)
 | 
			
		||||
{
 | 
			
		||||
    VirtIOPCIProxy *proxy = opaque;
 | 
			
		||||
@@ -561,6 +612,9 @@ static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign)
 | 
			
		||||
    } else {
 | 
			
		||||
        qemu_set_fd_handler(event_notifier_get_fd(notifier),
 | 
			
		||||
                            NULL, NULL, NULL);
 | 
			
		||||
        /* Test and clear notifier before closing it,
 | 
			
		||||
         * in case poll callback didn't have time to run. */
 | 
			
		||||
        virtio_pci_guest_notifier_read(vq);
 | 
			
		||||
        event_notifier_cleanup(notifier);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -579,6 +633,13 @@ static int virtio_pci_set_guest_notifiers(void *opaque, bool assign)
 | 
			
		||||
    VirtIODevice *vdev = proxy->vdev;
 | 
			
		||||
    int r, n;
 | 
			
		||||
 | 
			
		||||
    /* Must unset mask notifier while guest notifier
 | 
			
		||||
     * is still assigned */
 | 
			
		||||
    if (!assign) {
 | 
			
		||||
	    r = msix_unset_mask_notifier(&proxy->pci_dev);
 | 
			
		||||
            assert(r >= 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
 | 
			
		||||
        if (!virtio_queue_get_num(vdev, n)) {
 | 
			
		||||
            break;
 | 
			
		||||
@@ -590,6 +651,16 @@ static int virtio_pci_set_guest_notifiers(void *opaque, bool assign)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Must set mask notifier after guest notifier
 | 
			
		||||
     * has been assigned */
 | 
			
		||||
    if (assign) {
 | 
			
		||||
        r = msix_set_mask_notifier(&proxy->pci_dev,
 | 
			
		||||
                                   virtio_pci_mask_notifier);
 | 
			
		||||
        if (r < 0) {
 | 
			
		||||
            goto assign_error;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
 | 
			
		||||
assign_error:
 | 
			
		||||
@@ -597,6 +668,11 @@ assign_error:
 | 
			
		||||
    while (--n >= 0) {
 | 
			
		||||
        virtio_pci_set_guest_notifier(opaque, n, !assign);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!assign) {
 | 
			
		||||
        msix_set_mask_notifier(&proxy->pci_dev,
 | 
			
		||||
                               virtio_pci_mask_notifier);
 | 
			
		||||
    }
 | 
			
		||||
    return r;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -788,10 +864,22 @@ static int virtio_balloon_init_pci(PCIDevice *pci_dev)
 | 
			
		||||
    VirtIODevice *vdev;
 | 
			
		||||
 | 
			
		||||
    vdev = virtio_balloon_init(&pci_dev->qdev);
 | 
			
		||||
    if (!vdev) {
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    virtio_init_pci(proxy, vdev);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int virtio_balloon_exit_pci(PCIDevice *pci_dev)
 | 
			
		||||
{
 | 
			
		||||
    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
 | 
			
		||||
 | 
			
		||||
    virtio_pci_stop_ioeventfd(proxy);
 | 
			
		||||
    virtio_balloon_exit(proxy->vdev);
 | 
			
		||||
    return virtio_exit_pci(pci_dev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PCIDeviceInfo virtio_info[] = {
 | 
			
		||||
    {
 | 
			
		||||
        .qdev.name = "virtio-blk-pci",
 | 
			
		||||
@@ -866,7 +954,7 @@ static PCIDeviceInfo virtio_info[] = {
 | 
			
		||||
        .qdev.alias = "virtio-balloon",
 | 
			
		||||
        .qdev.size = sizeof(VirtIOPCIProxy),
 | 
			
		||||
        .init      = virtio_balloon_init_pci,
 | 
			
		||||
        .exit      = virtio_exit_pci,
 | 
			
		||||
        .exit      = virtio_balloon_exit_pci,
 | 
			
		||||
        .vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET,
 | 
			
		||||
        .device_id = PCI_DEVICE_ID_VIRTIO_BALLOON,
 | 
			
		||||
        .revision  = VIRTIO_PCI_ABI_VERSION,
 | 
			
		||||
 
 | 
			
		||||
@@ -213,6 +213,7 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf);
 | 
			
		||||
void virtio_net_exit(VirtIODevice *vdev);
 | 
			
		||||
void virtio_blk_exit(VirtIODevice *vdev);
 | 
			
		||||
void virtio_serial_exit(VirtIODevice *vdev);
 | 
			
		||||
void virtio_balloon_exit(VirtIODevice *vdev);
 | 
			
		||||
 | 
			
		||||
#define DEFINE_VIRTIO_COMMON_FEATURES(_state, _field) \
 | 
			
		||||
	DEFINE_PROP_BIT("indirect_desc", _state, _field, \
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								i386.ld
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								i386.ld
									
									
									
									
									
								
							@@ -42,16 +42,16 @@ SECTIONS
 | 
			
		||||
  .rel.plt      :
 | 
			
		||||
  {
 | 
			
		||||
    *(.rel.plt)
 | 
			
		||||
    PROVIDE_HIDDEN (__rel_iplt_start = .);
 | 
			
		||||
    PROVIDE (__rel_iplt_start = .);
 | 
			
		||||
    *(.rel.iplt)
 | 
			
		||||
    PROVIDE_HIDDEN (__rel_iplt_end = .);
 | 
			
		||||
    PROVIDE (__rel_iplt_end = .);
 | 
			
		||||
  }
 | 
			
		||||
  .rela.plt       :
 | 
			
		||||
  {
 | 
			
		||||
    *(.rela.plt)
 | 
			
		||||
    PROVIDE_HIDDEN (__rela_iplt_start = .);
 | 
			
		||||
    PROVIDE (__rela_iplt_start = .);
 | 
			
		||||
    *(.rela.iplt)
 | 
			
		||||
    PROVIDE_HIDDEN (__rela_iplt_end = .);
 | 
			
		||||
    PROVIDE (__rela_iplt_end = .);
 | 
			
		||||
  }
 | 
			
		||||
  .init          : { *(.init)	} =0x47ff041f
 | 
			
		||||
  .text      :
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								ia64.ld
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								ia64.ld
									
									
									
									
									
								
							@@ -7,7 +7,7 @@ ENTRY(_start)
 | 
			
		||||
SECTIONS
 | 
			
		||||
{
 | 
			
		||||
  /* Read-only sections, merged into text segment: */
 | 
			
		||||
  PROVIDE (__executable_start = 0x60000000); . = 0x60000000 + SIZEOF_HEADERS;
 | 
			
		||||
  PROVIDE (__executable_start = 0x4000000060000000); . = 0x4000000060000000 + SIZEOF_HEADERS;
 | 
			
		||||
  .interp         : { *(.interp) }
 | 
			
		||||
  .hash           : { *(.hash) }
 | 
			
		||||
  .dynsym         : { *(.dynsym) }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										150
									
								
								ia64intrin.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								ia64intrin.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,150 @@
 | 
			
		||||
#ifndef IA64_INTRINSIC_H
 | 
			
		||||
#define IA64_INTRINSIC_H
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Compiler-dependent Intrinsics
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2002,2003 Jun Nakajima <jun.nakajima@intel.com>
 | 
			
		||||
 * Copyright (C) 2002,2003 Suresh Siddha <suresh.b.siddha@intel.com>
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
extern long ia64_cmpxchg_called_with_bad_pointer (void);
 | 
			
		||||
extern void ia64_bad_param_for_getreg (void);
 | 
			
		||||
#define ia64_cmpxchg(sem,ptr,o,n,s) ({					\
 | 
			
		||||
	uint64_t _o, _r;						\
 | 
			
		||||
	switch(s) {							\
 | 
			
		||||
		case 1: _o = (uint8_t)(long)(o); break;			\
 | 
			
		||||
		case 2: _o = (uint16_t)(long)(o); break;		\
 | 
			
		||||
		case 4: _o = (uint32_t)(long)(o); break;		\
 | 
			
		||||
		case 8: _o = (uint64_t)(long)(o); break;		\
 | 
			
		||||
		default: break;						\
 | 
			
		||||
	}								\
 | 
			
		||||
	switch(s) {							\
 | 
			
		||||
		case 1:							\
 | 
			
		||||
		_r = ia64_cmpxchg1_##sem((uint8_t*)ptr,n,_o); break;	\
 | 
			
		||||
		case 2:							\
 | 
			
		||||
		_r = ia64_cmpxchg2_##sem((uint16_t*)ptr,n,_o); break;	\
 | 
			
		||||
		case 4:							\
 | 
			
		||||
		_r = ia64_cmpxchg4_##sem((uint32_t*)ptr,n,_o); break;	\
 | 
			
		||||
		case 8:							\
 | 
			
		||||
		_r = ia64_cmpxchg8_##sem((uint64_t*)ptr,n,_o); break;	\
 | 
			
		||||
		default:						\
 | 
			
		||||
		_r = ia64_cmpxchg_called_with_bad_pointer(); break;	\
 | 
			
		||||
	}								\
 | 
			
		||||
	(__typeof__(o)) _r;						\
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
#define cmpxchg_acq(ptr,o,n) ia64_cmpxchg(acq,ptr,o,n,sizeof(*ptr))
 | 
			
		||||
#define cmpxchg_rel(ptr,o,n) ia64_cmpxchg(rel,ptr,o,n,sizeof(*ptr))
 | 
			
		||||
 | 
			
		||||
#ifdef __INTEL_COMPILER
 | 
			
		||||
void  __fc(uint64_t *addr);
 | 
			
		||||
void  __synci(void);
 | 
			
		||||
void __isrlz(void);
 | 
			
		||||
void __dsrlz(void);
 | 
			
		||||
uint64_t __getReg(const int whichReg);
 | 
			
		||||
uint64_t _InterlockedCompareExchange8_rel(volatile uint8_t *dest, uint64_t xchg, uint64_t comp);
 | 
			
		||||
uint64_t _InterlockedCompareExchange8_acq(volatile uint8_t *dest, uint64_t xchg, uint64_t comp);
 | 
			
		||||
uint64_t _InterlockedCompareExchange16_rel(volatile uint16_t *dest, uint64_t xchg, uint64_t comp);
 | 
			
		||||
uint64_t _InterlockedCompareExchange16_acq(volatile uint16_t *dest, uint64_t xchg, uint64_t comp);
 | 
			
		||||
uint64_t _InterlockedCompareExchange_rel(volatile uint32_t *dest, uint64_t xchg, uint64_t comp);
 | 
			
		||||
uint64_t _InterlockedCompareExchange_acq(volatile uint32_t *dest, uint64_t xchg, uint64_t comp);
 | 
			
		||||
uint64_t _InterlockedCompareExchange64_rel(volatile uint64_t *dest, uint64_t xchg, uint64_t comp);
 | 
			
		||||
u64_t _InterlockedCompareExchange64_acq(volatile uint64_t *dest, uint64_t xchg, uint64_t comp);
 | 
			
		||||
 | 
			
		||||
#define ia64_cmpxchg1_rel	_InterlockedCompareExchange8_rel
 | 
			
		||||
#define ia64_cmpxchg1_acq	_InterlockedCompareExchange8_acq
 | 
			
		||||
#define ia64_cmpxchg2_rel	_InterlockedCompareExchange16_rel
 | 
			
		||||
#define ia64_cmpxchg2_acq	_InterlockedCompareExchange16_acq
 | 
			
		||||
#define ia64_cmpxchg4_rel	_InterlockedCompareExchange_rel
 | 
			
		||||
#define ia64_cmpxchg4_acq	_InterlockedCompareExchange_acq
 | 
			
		||||
#define ia64_cmpxchg8_rel	_InterlockedCompareExchange64_rel
 | 
			
		||||
#define ia64_cmpxchg8_acq	_InterlockedCompareExchange64_acq
 | 
			
		||||
 | 
			
		||||
#define ia64_srlz_d		__dsrlz
 | 
			
		||||
#define ia64_srlz_i		__isrlz
 | 
			
		||||
#define __ia64_fc 		__fc
 | 
			
		||||
#define ia64_sync_i		__synci
 | 
			
		||||
#define __ia64_getreg		__getReg
 | 
			
		||||
#else /* __INTEL_COMPILER */
 | 
			
		||||
#define ia64_cmpxchg1_acq(ptr, new, old)						\
 | 
			
		||||
({											\
 | 
			
		||||
	uint64_t ia64_intri_res;							\
 | 
			
		||||
	asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));					\
 | 
			
		||||
	asm volatile ("cmpxchg1.acq %0=[%1],%2,ar.ccv":					\
 | 
			
		||||
			      "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");	\
 | 
			
		||||
	ia64_intri_res;									\
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
#define ia64_cmpxchg1_rel(ptr, new, old)						\
 | 
			
		||||
({											\
 | 
			
		||||
	uint64_t ia64_intri_res;							\
 | 
			
		||||
	asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));					\
 | 
			
		||||
	asm volatile ("cmpxchg1.rel %0=[%1],%2,ar.ccv":					\
 | 
			
		||||
			      "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");	\
 | 
			
		||||
	ia64_intri_res;									\
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
#define ia64_cmpxchg2_acq(ptr, new, old)						\
 | 
			
		||||
({											\
 | 
			
		||||
	uint64_t ia64_intri_res;							\
 | 
			
		||||
	asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));					\
 | 
			
		||||
	asm volatile ("cmpxchg2.acq %0=[%1],%2,ar.ccv":					\
 | 
			
		||||
			      "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");	\
 | 
			
		||||
	ia64_intri_res;									\
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
#define ia64_cmpxchg2_rel(ptr, new, old)						\
 | 
			
		||||
({											\
 | 
			
		||||
	uint64_t ia64_intri_res;							\
 | 
			
		||||
	asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));					\
 | 
			
		||||
											\
 | 
			
		||||
	asm volatile ("cmpxchg2.rel %0=[%1],%2,ar.ccv":					\
 | 
			
		||||
			      "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");	\
 | 
			
		||||
	ia64_intri_res;									\
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
#define ia64_cmpxchg4_acq(ptr, new, old)						\
 | 
			
		||||
({											\
 | 
			
		||||
	uint64_t ia64_intri_res;							\
 | 
			
		||||
	asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));					\
 | 
			
		||||
	asm volatile ("cmpxchg4.acq %0=[%1],%2,ar.ccv":					\
 | 
			
		||||
			      "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");	\
 | 
			
		||||
	ia64_intri_res;									\
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
#define ia64_cmpxchg4_rel(ptr, new, old)						\
 | 
			
		||||
({											\
 | 
			
		||||
	uint64_t ia64_intri_res;							\
 | 
			
		||||
	asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));					\
 | 
			
		||||
	asm volatile ("cmpxchg4.rel %0=[%1],%2,ar.ccv":					\
 | 
			
		||||
			      "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");	\
 | 
			
		||||
	ia64_intri_res;									\
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
#define ia64_cmpxchg8_acq(ptr, new, old)						\
 | 
			
		||||
({											\
 | 
			
		||||
	uint64_t ia64_intri_res;							\
 | 
			
		||||
	asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));					\
 | 
			
		||||
	asm volatile ("cmpxchg8.acq %0=[%1],%2,ar.ccv":					\
 | 
			
		||||
			      "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");	\
 | 
			
		||||
	ia64_intri_res;									\
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
#define ia64_cmpxchg8_rel(ptr, new, old)						\
 | 
			
		||||
({											\
 | 
			
		||||
	uint64_t ia64_intri_res;							\
 | 
			
		||||
	asm volatile ("mov ar.ccv=%0;;" :: "rO"(old));					\
 | 
			
		||||
											\
 | 
			
		||||
	asm volatile ("cmpxchg8.rel %0=[%1],%2,ar.ccv":					\
 | 
			
		||||
			      "=r"(ia64_intri_res) : "r"(ptr), "r"(new) : "memory");	\
 | 
			
		||||
	ia64_intri_res;									\
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
#define ia64_srlz_i()	asm volatile (";; srlz.i ;;" ::: "memory")
 | 
			
		||||
#define ia64_srlz_d()	asm volatile (";; srlz.d" ::: "memory");
 | 
			
		||||
#define __ia64_fc(addr)	asm volatile ("fc %0" :: "r"(addr) : "memory")
 | 
			
		||||
#define ia64_sync_i()	asm volatile (";; sync.i" ::: "memory")
 | 
			
		||||
 | 
			
		||||
#endif /* __INTEL_COMPILER */
 | 
			
		||||
#endif /* IA64_INTRINSIC_H */
 | 
			
		||||
							
								
								
									
										51
									
								
								kvm-all.c
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								kvm-all.c
									
									
									
									
									
								
							@@ -76,6 +76,15 @@ struct KVMState
 | 
			
		||||
    int pit_in_kernel;
 | 
			
		||||
    int xsave, xcrs;
 | 
			
		||||
    int many_ioeventfds;
 | 
			
		||||
    int pit_state2;
 | 
			
		||||
 | 
			
		||||
    int irqchip_inject_ioctl;
 | 
			
		||||
#ifdef KVM_CAP_IRQ_ROUTING
 | 
			
		||||
    struct kvm_irq_routing *irq_routes;
 | 
			
		||||
    int nr_allocated_irq_routes;
 | 
			
		||||
#endif
 | 
			
		||||
    void *used_gsi_bitmap;
 | 
			
		||||
    int max_gsi;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
KVMState *kvm_state;
 | 
			
		||||
@@ -781,6 +790,13 @@ int kvm_init(void)
 | 
			
		||||
    s->xcrs = kvm_check_extension(s, KVM_CAP_XCRS);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    s->pit_state2 = 0;
 | 
			
		||||
#ifdef KVM_CAP_PIT_STATE2
 | 
			
		||||
    s->pit_state2 = kvm_check_extension(s, KVM_CAP_PIT_STATE2);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    s->pit_in_kernel = kvm_pit;
 | 
			
		||||
 | 
			
		||||
    ret = kvm_arch_init(s);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        goto err;
 | 
			
		||||
@@ -791,6 +807,11 @@ int kvm_init(void)
 | 
			
		||||
 | 
			
		||||
    s->many_ioeventfds = kvm_check_many_ioeventfds();
 | 
			
		||||
 | 
			
		||||
    ret = kvm_create_irqchip(s);
 | 
			
		||||
    if (ret < 0) {
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    cpu_interrupt_handler = kvm_handle_interrupt;
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
@@ -1103,6 +1124,11 @@ int kvm_has_xcrs(void)
 | 
			
		||||
    return kvm_state->xcrs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int kvm_has_pit_state2(void)
 | 
			
		||||
{
 | 
			
		||||
    return kvm_state->pit_state2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int kvm_has_many_ioeventfds(void)
 | 
			
		||||
{
 | 
			
		||||
    if (!kvm_enabled()) {
 | 
			
		||||
@@ -1111,6 +1137,11 @@ int kvm_has_many_ioeventfds(void)
 | 
			
		||||
    return kvm_state->many_ioeventfds;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int kvm_allows_irq0_override(void)
 | 
			
		||||
{
 | 
			
		||||
    return !kvm_enabled() || !kvm_irqchip_in_kernel() || kvm_has_gsi_routing();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void kvm_setup_guest_memory(void *start, size_t size)
 | 
			
		||||
{
 | 
			
		||||
    if (!kvm_has_sync_mmu()) {
 | 
			
		||||
@@ -1385,6 +1416,23 @@ int kvm_set_ioeventfd_pio_word(int fd, uint16_t addr, uint16_t val, bool assign)
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int kvm_set_irqfd(int gsi, int fd, bool assigned)
 | 
			
		||||
{
 | 
			
		||||
    struct kvm_irqfd irqfd = {
 | 
			
		||||
        .fd = fd,
 | 
			
		||||
        .gsi = gsi,
 | 
			
		||||
        .flags = assigned ? 0 : KVM_IRQFD_FLAG_DEASSIGN,
 | 
			
		||||
    };
 | 
			
		||||
    int r;
 | 
			
		||||
    if (!kvm_enabled() || !kvm_irqchip_in_kernel())
 | 
			
		||||
        return -ENOSYS;
 | 
			
		||||
 | 
			
		||||
    r = kvm_vm_ioctl(kvm_state, KVM_IRQFD, &irqfd);
 | 
			
		||||
    if (r < 0)
 | 
			
		||||
        return r;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int kvm_on_sigbus_vcpu(CPUState *env, int code, void *addr)
 | 
			
		||||
{
 | 
			
		||||
    return kvm_arch_on_sigbus_vcpu(env, code, addr);
 | 
			
		||||
@@ -1394,3 +1442,6 @@ int kvm_on_sigbus(int code, void *addr)
 | 
			
		||||
{
 | 
			
		||||
    return kvm_arch_on_sigbus(code, addr);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#undef PAGE_SIZE
 | 
			
		||||
#include "qemu-kvm.c"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										51
									
								
								kvm-stub.c
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								kvm-stub.c
									
									
									
									
									
								
							@@ -78,6 +78,16 @@ int kvm_has_many_ioeventfds(void)
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int kvm_allows_irq0_override(void)
 | 
			
		||||
{
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int kvm_has_pit_state2(void)
 | 
			
		||||
{
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void kvm_setup_guest_memory(void *start, size_t size)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
@@ -120,6 +130,42 @@ int kvm_set_ioeventfd_mmio_long(int fd, uint32_t adr, uint32_t val, bool assign)
 | 
			
		||||
    return -ENOSYS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int kvm_has_gsi_routing(void)
 | 
			
		||||
{
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int kvm_get_irq_route_gsi(void)
 | 
			
		||||
{
 | 
			
		||||
    return -ENOSYS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int kvm_msi_message_add(KVMMsiMessage *msg)
 | 
			
		||||
{
 | 
			
		||||
    return -ENOSYS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int kvm_msi_message_del(KVMMsiMessage *msg)
 | 
			
		||||
{
 | 
			
		||||
    return -ENOSYS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int kvm_msi_message_update(KVMMsiMessage *old, KVMMsiMessage *new)
 | 
			
		||||
{
 | 
			
		||||
    return -ENOSYS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int kvm_commit_irq_routes(void)
 | 
			
		||||
{
 | 
			
		||||
    return -ENOSYS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int kvm_set_irq(int irq, int level, int *status)
 | 
			
		||||
{
 | 
			
		||||
    assert(0);
 | 
			
		||||
    return -ENOSYS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int kvm_on_sigbus_vcpu(CPUState *env, int code, void *addr)
 | 
			
		||||
{
 | 
			
		||||
    return 1;
 | 
			
		||||
@@ -129,3 +175,8 @@ int kvm_on_sigbus(int code, void *addr)
 | 
			
		||||
{
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int kvm_set_irqfd(int gsi, int fd, bool assigned)
 | 
			
		||||
{
 | 
			
		||||
    return -ENOSYS;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										380
									
								
								kvm-tpr-opt.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										380
									
								
								kvm-tpr-opt.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,380 @@
 | 
			
		||||
/*
 | 
			
		||||
 * tpr optimization for qemu/kvm
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2007-2008 Qumranet Technologies
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the terms of the GNU GPL version 2 or higher.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include "config-host.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "hw/hw.h"
 | 
			
		||||
#include "hw/isa.h"
 | 
			
		||||
#include "sysemu.h"
 | 
			
		||||
#include "kvm.h"
 | 
			
		||||
#include "cpu.h"
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
static uint64_t map_addr(CPUState *env, target_ulong virt, unsigned *perms)
 | 
			
		||||
{
 | 
			
		||||
    uint64_t mask = ((1ull << 48) - 1) & ~4095ull;
 | 
			
		||||
    uint64_t p, pp = 7;
 | 
			
		||||
 | 
			
		||||
    p = env->cr[3];
 | 
			
		||||
    if (env->cr[4] & 0x20) {
 | 
			
		||||
	p &= ~31ull;
 | 
			
		||||
	p = ldq_phys(p + 8 * (virt >> 30));
 | 
			
		||||
	if (!(p & 1))
 | 
			
		||||
	    return -1ull;
 | 
			
		||||
	p &= mask;
 | 
			
		||||
	p = ldq_phys(p + 8 * ((virt >> 21) & 511));
 | 
			
		||||
	if (!(p & 1))
 | 
			
		||||
	    return -1ull;
 | 
			
		||||
	pp &= p;
 | 
			
		||||
	if (p & 128) {
 | 
			
		||||
	    p += ((virt >> 12) & 511) << 12;
 | 
			
		||||
	} else {
 | 
			
		||||
	    p &= mask;
 | 
			
		||||
	    p = ldq_phys(p + 8 * ((virt >> 12) & 511));
 | 
			
		||||
	    if (!(p & 1))
 | 
			
		||||
		return -1ull;
 | 
			
		||||
	    pp &= p;
 | 
			
		||||
	}
 | 
			
		||||
    } else {
 | 
			
		||||
	p &= mask;
 | 
			
		||||
	p = ldl_phys(p + 4 * ((virt >> 22) & 1023));
 | 
			
		||||
	if (!(p & 1))
 | 
			
		||||
	    return -1ull;
 | 
			
		||||
	pp &= p;
 | 
			
		||||
	if (p & 128) {
 | 
			
		||||
	    p += ((virt >> 12) & 1023) << 12;
 | 
			
		||||
	} else {
 | 
			
		||||
	    p &= mask;
 | 
			
		||||
	    p = ldl_phys(p + 4 * ((virt >> 12) & 1023));
 | 
			
		||||
	    pp &= p;
 | 
			
		||||
	    if (!(p & 1))
 | 
			
		||||
		return -1ull;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
    if (perms)
 | 
			
		||||
	*perms = pp >> 1;
 | 
			
		||||
    p &= mask;
 | 
			
		||||
    return p + (virt & 4095);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint8_t read_byte_virt(CPUState *env, target_ulong virt)
 | 
			
		||||
{
 | 
			
		||||
    return ldub_phys(map_addr(env, virt, NULL));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void write_byte_virt(CPUState *env, target_ulong virt, uint8_t b)
 | 
			
		||||
{
 | 
			
		||||
    cpu_physical_memory_write_rom(map_addr(env, virt, NULL), &b, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct vapic_bios {
 | 
			
		||||
    char signature[8];
 | 
			
		||||
    uint32_t virt_base;
 | 
			
		||||
    uint32_t fixup_start;
 | 
			
		||||
    uint32_t fixup_end;
 | 
			
		||||
    uint32_t vapic;
 | 
			
		||||
    uint32_t vapic_size;
 | 
			
		||||
    uint32_t vcpu_shift;
 | 
			
		||||
    uint32_t real_tpr;
 | 
			
		||||
    struct vapic_patches {
 | 
			
		||||
	uint32_t set_tpr;
 | 
			
		||||
	uint32_t set_tpr_eax;
 | 
			
		||||
	uint32_t get_tpr[8];
 | 
			
		||||
        uint32_t get_tpr_stack;
 | 
			
		||||
    } __attribute__((packed)) up, mp;
 | 
			
		||||
} __attribute__((packed));
 | 
			
		||||
 | 
			
		||||
static struct vapic_bios vapic_bios;
 | 
			
		||||
 | 
			
		||||
static uint32_t real_tpr;
 | 
			
		||||
static uint32_t bios_addr;
 | 
			
		||||
static uint32_t vapic_phys;
 | 
			
		||||
static uint32_t bios_enabled;
 | 
			
		||||
static uint32_t vbios_desc_phys;
 | 
			
		||||
static uint32_t vapic_bios_addr;
 | 
			
		||||
 | 
			
		||||
static void update_vbios_real_tpr(void)
 | 
			
		||||
{
 | 
			
		||||
    cpu_physical_memory_rw(vbios_desc_phys, (void *)&vapic_bios, sizeof vapic_bios, 0);
 | 
			
		||||
    vapic_bios.real_tpr = real_tpr;
 | 
			
		||||
    vapic_bios.vcpu_shift = 7;
 | 
			
		||||
    cpu_physical_memory_write_rom(vbios_desc_phys, (void *)&vapic_bios, sizeof vapic_bios);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned modrm_reg(uint8_t modrm)
 | 
			
		||||
{
 | 
			
		||||
    return (modrm >> 3) & 7;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int is_abs_modrm(uint8_t modrm)
 | 
			
		||||
{
 | 
			
		||||
    return (modrm & 0xc7) == 0x05;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int instruction_is_ok(CPUState *env, uint64_t rip, int is_write)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t b1, b2;
 | 
			
		||||
    unsigned addr_offset;
 | 
			
		||||
    uint32_t addr;
 | 
			
		||||
    uint64_t p;
 | 
			
		||||
 | 
			
		||||
    if ((rip & 0xf0000000) != 0x80000000 && (rip & 0xf0000000) != 0xe0000000)
 | 
			
		||||
	return 0;
 | 
			
		||||
    if (env->regs[R_ESP] == 0)
 | 
			
		||||
        return 0;
 | 
			
		||||
    b1 = read_byte_virt(env, rip);
 | 
			
		||||
    b2 = read_byte_virt(env, rip + 1);
 | 
			
		||||
    switch (b1) {
 | 
			
		||||
    case 0xc7: /* mov imm32, r/m32 (c7/0) */
 | 
			
		||||
	if (modrm_reg(b2) != 0)
 | 
			
		||||
	    return 0;
 | 
			
		||||
	/* fall through */
 | 
			
		||||
    case 0x89: /* mov r32 to r/m32 */
 | 
			
		||||
    case 0x8b: /* mov r/m32 to r32 */
 | 
			
		||||
	if (!is_abs_modrm(b2))
 | 
			
		||||
	    return 0;
 | 
			
		||||
	addr_offset = 2;
 | 
			
		||||
	break;
 | 
			
		||||
    case 0xa1: /* mov abs to eax */
 | 
			
		||||
    case 0xa3: /* mov eax to abs */
 | 
			
		||||
	addr_offset = 1;
 | 
			
		||||
	break;
 | 
			
		||||
    case 0xff: /* push r/m32 */
 | 
			
		||||
        if (modrm_reg(b2) != 6 || !is_abs_modrm(b2))
 | 
			
		||||
            return 0;
 | 
			
		||||
        addr_offset = 2;
 | 
			
		||||
    default:
 | 
			
		||||
	return 0;
 | 
			
		||||
    }
 | 
			
		||||
    p = rip + addr_offset;
 | 
			
		||||
    addr = read_byte_virt(env, p++);
 | 
			
		||||
    addr |= read_byte_virt(env, p++) << 8;
 | 
			
		||||
    addr |= read_byte_virt(env, p++) << 16;
 | 
			
		||||
    addr |= read_byte_virt(env, p++) << 24;
 | 
			
		||||
    if ((addr & 0xfff) != 0x80)
 | 
			
		||||
	return 0;
 | 
			
		||||
    real_tpr = addr;
 | 
			
		||||
    update_vbios_real_tpr();
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int bios_is_mapped(CPUState *env, uint64_t rip)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t probe;
 | 
			
		||||
    uint64_t phys;
 | 
			
		||||
    unsigned perms;
 | 
			
		||||
    uint32_t i;
 | 
			
		||||
    uint32_t offset, fixup, start = vapic_bios_addr ? : 0xe0000;
 | 
			
		||||
    uint32_t patch;
 | 
			
		||||
 | 
			
		||||
    if (bios_enabled)
 | 
			
		||||
	return 1;
 | 
			
		||||
 | 
			
		||||
    probe = (rip & 0xf0000000) + start;
 | 
			
		||||
    phys = map_addr(env, probe, &perms);
 | 
			
		||||
    if (phys != start)
 | 
			
		||||
	return 0;
 | 
			
		||||
    bios_addr = probe;
 | 
			
		||||
    for (i = 0; i < 64; ++i) {
 | 
			
		||||
	cpu_physical_memory_read(phys, (void *)&vapic_bios, sizeof(vapic_bios));
 | 
			
		||||
	if (memcmp(vapic_bios.signature, "kvm aPiC", 8) == 0)
 | 
			
		||||
	    break;
 | 
			
		||||
	phys += 1024;
 | 
			
		||||
	bios_addr += 1024;
 | 
			
		||||
    }
 | 
			
		||||
    if (i == 64)
 | 
			
		||||
	return 0;
 | 
			
		||||
    if (bios_addr == vapic_bios.virt_base)
 | 
			
		||||
	return 1;
 | 
			
		||||
    vbios_desc_phys = phys;
 | 
			
		||||
    for (i = vapic_bios.fixup_start; i < vapic_bios.fixup_end; i += 4) {
 | 
			
		||||
	offset = ldl_phys(phys + i - vapic_bios.virt_base);
 | 
			
		||||
	fixup = phys + offset;
 | 
			
		||||
        patch = ldl_phys(fixup) + bios_addr - vapic_bios.virt_base;
 | 
			
		||||
        cpu_physical_memory_write_rom(fixup, (uint8_t *)&patch, 4);
 | 
			
		||||
    }
 | 
			
		||||
    vapic_phys = vapic_bios.vapic - vapic_bios.virt_base + phys;
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int get_pcr_cpu(CPUState *env)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t b;
 | 
			
		||||
 | 
			
		||||
    cpu_synchronize_state(env);
 | 
			
		||||
 | 
			
		||||
    if (cpu_memory_rw_debug(env, env->segs[R_FS].base + 0x51, &b, 1, 0) < 0)
 | 
			
		||||
	    return -1;
 | 
			
		||||
 | 
			
		||||
    return (int)b;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int kvm_tpr_enable_vapic(CPUState *env)
 | 
			
		||||
{
 | 
			
		||||
    static uint8_t one = 1;
 | 
			
		||||
    int pcr_cpu = get_pcr_cpu(env);
 | 
			
		||||
 | 
			
		||||
    if (pcr_cpu < 0)
 | 
			
		||||
	    return 0;
 | 
			
		||||
 | 
			
		||||
    kvm_enable_vapic(env, vapic_phys + (pcr_cpu << 7));
 | 
			
		||||
    cpu_physical_memory_write_rom(vapic_phys + (pcr_cpu << 7) + 4, &one, 1);
 | 
			
		||||
    env->kvm_vcpu_update_vapic = 0;
 | 
			
		||||
    bios_enabled = 1;
 | 
			
		||||
    return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void patch_call(CPUState *env, uint64_t rip, uint32_t target)
 | 
			
		||||
{
 | 
			
		||||
    uint32_t offset;
 | 
			
		||||
 | 
			
		||||
    offset = target - vapic_bios.virt_base + bios_addr - rip - 5;
 | 
			
		||||
    write_byte_virt(env, rip, 0xe8); /* call near */
 | 
			
		||||
    write_byte_virt(env, rip + 1, offset);
 | 
			
		||||
    write_byte_virt(env, rip + 2, offset >> 8);
 | 
			
		||||
    write_byte_virt(env, rip + 3, offset >> 16);
 | 
			
		||||
    write_byte_virt(env, rip + 4, offset >> 24);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void patch_instruction(CPUState *env, uint64_t rip)
 | 
			
		||||
{
 | 
			
		||||
    uint8_t b1, b2;
 | 
			
		||||
    struct vapic_patches *vp;
 | 
			
		||||
 | 
			
		||||
    vp = smp_cpus == 1 ? &vapic_bios.up : &vapic_bios.mp;
 | 
			
		||||
    b1 = read_byte_virt(env, rip);
 | 
			
		||||
    b2 = read_byte_virt(env, rip + 1);
 | 
			
		||||
    switch (b1) {
 | 
			
		||||
    case 0x89: /* mov r32 to r/m32 */
 | 
			
		||||
	write_byte_virt(env, rip, 0x50 + modrm_reg(b2));  /* push reg */
 | 
			
		||||
	patch_call(env, rip + 1, vp->set_tpr);
 | 
			
		||||
	break;
 | 
			
		||||
    case 0x8b: /* mov r/m32 to r32 */
 | 
			
		||||
	write_byte_virt(env, rip, 0x90);
 | 
			
		||||
	patch_call(env, rip + 1, vp->get_tpr[modrm_reg(b2)]);
 | 
			
		||||
	break;
 | 
			
		||||
    case 0xa1: /* mov abs to eax */
 | 
			
		||||
	patch_call(env, rip, vp->get_tpr[0]);
 | 
			
		||||
	break;
 | 
			
		||||
    case 0xa3: /* mov eax to abs */
 | 
			
		||||
	patch_call(env, rip, vp->set_tpr_eax);
 | 
			
		||||
	break;
 | 
			
		||||
    case 0xc7: /* mov imm32, r/m32 (c7/0) */
 | 
			
		||||
	write_byte_virt(env, rip, 0x68);  /* push imm32 */
 | 
			
		||||
	write_byte_virt(env, rip + 1, read_byte_virt(env, rip+6));
 | 
			
		||||
	write_byte_virt(env, rip + 2, read_byte_virt(env, rip+7));
 | 
			
		||||
	write_byte_virt(env, rip + 3, read_byte_virt(env, rip+8));
 | 
			
		||||
	write_byte_virt(env, rip + 4, read_byte_virt(env, rip+9));
 | 
			
		||||
	patch_call(env, rip + 5, vp->set_tpr);
 | 
			
		||||
	break;
 | 
			
		||||
    case 0xff: /* push r/m32 */
 | 
			
		||||
        printf("patching push\n");
 | 
			
		||||
        write_byte_virt(env, rip, 0x50); /* push eax */
 | 
			
		||||
        patch_call(env, rip + 1, vp->get_tpr_stack);
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
	printf("funny insn %02x %02x\n", b1, b2);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void kvm_tpr_access_report(CPUState *env, uint64_t rip, int is_write)
 | 
			
		||||
{
 | 
			
		||||
    cpu_synchronize_state(env);
 | 
			
		||||
    if (!instruction_is_ok(env, rip, is_write))
 | 
			
		||||
	return;
 | 
			
		||||
    if (!bios_is_mapped(env, rip))
 | 
			
		||||
	return;
 | 
			
		||||
    if (!kvm_tpr_enable_vapic(env))
 | 
			
		||||
	return;
 | 
			
		||||
    patch_instruction(env, rip);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void tpr_save(QEMUFile *f, void *s)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < (sizeof vapic_bios) / 4; ++i)
 | 
			
		||||
	qemu_put_be32s(f, &((uint32_t *)&vapic_bios)[i]);
 | 
			
		||||
    qemu_put_be32s(f, &bios_enabled);
 | 
			
		||||
    qemu_put_be32s(f, &real_tpr);
 | 
			
		||||
    qemu_put_be32s(f, &bios_addr);
 | 
			
		||||
    qemu_put_be32s(f, &vapic_phys);
 | 
			
		||||
    qemu_put_be32s(f, &vbios_desc_phys);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int tpr_load(QEMUFile *f, void *s, int version_id)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    if (version_id != 1)
 | 
			
		||||
	return -EINVAL;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < (sizeof vapic_bios) / 4; ++i)
 | 
			
		||||
	qemu_get_be32s(f, &((uint32_t *)&vapic_bios)[i]);
 | 
			
		||||
    qemu_get_be32s(f, &bios_enabled);
 | 
			
		||||
    qemu_get_be32s(f, &real_tpr);
 | 
			
		||||
    qemu_get_be32s(f, &bios_addr);
 | 
			
		||||
    qemu_get_be32s(f, &vapic_phys);
 | 
			
		||||
    qemu_get_be32s(f, &vbios_desc_phys);
 | 
			
		||||
  
 | 
			
		||||
    if (bios_enabled) {
 | 
			
		||||
        CPUState *env = first_cpu->next_cpu;
 | 
			
		||||
 | 
			
		||||
        for (env = first_cpu; env != NULL; env = env->next_cpu)
 | 
			
		||||
            env->kvm_vcpu_update_vapic = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void vtpr_ioport_write16(void *opaque, uint32_t addr, uint32_t val)
 | 
			
		||||
{
 | 
			
		||||
    CPUState *env = cpu_single_env;
 | 
			
		||||
 | 
			
		||||
    cpu_synchronize_state(env);
 | 
			
		||||
 | 
			
		||||
    vapic_bios_addr = ((env->segs[R_CS].base + env->eip) & ~(512 - 1)) + val;
 | 
			
		||||
    bios_enabled = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void vtpr_ioport_write(void *opaque, uint32_t addr, uint32_t val)
 | 
			
		||||
{
 | 
			
		||||
    CPUState *env = cpu_single_env;
 | 
			
		||||
    uint32_t rip;
 | 
			
		||||
 | 
			
		||||
    cpu_synchronize_state(env);
 | 
			
		||||
 | 
			
		||||
    rip = env->eip - 2;
 | 
			
		||||
    write_byte_virt(env, rip, 0x66);
 | 
			
		||||
    write_byte_virt(env, rip + 1, 0x90);
 | 
			
		||||
    if (bios_enabled)
 | 
			
		||||
	return;
 | 
			
		||||
    if (!bios_is_mapped(env, rip))
 | 
			
		||||
	printf("bios not mapped?\n");
 | 
			
		||||
    for (addr = 0xfffff000u; addr >= 0x80000000u; addr -= 4096)
 | 
			
		||||
	if (map_addr(env, addr, NULL) == 0xfee00000u) {
 | 
			
		||||
	    real_tpr = addr + 0x80;
 | 
			
		||||
	    break;
 | 
			
		||||
	}
 | 
			
		||||
    bios_enabled = 1;
 | 
			
		||||
    update_vbios_real_tpr();
 | 
			
		||||
    kvm_tpr_enable_vapic(env);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void kvm_tpr_opt_setup(void)
 | 
			
		||||
{
 | 
			
		||||
    register_savevm(NULL, "kvm-tpr-opt", 0, 1, tpr_save, tpr_load, NULL);
 | 
			
		||||
    register_ioport_write(0x7e, 1, 1, vtpr_ioport_write, NULL);
 | 
			
		||||
    register_ioport_write(0x7e, 2, 2, vtpr_ioport_write16, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
device_init(kvm_tpr_opt_setup);
 | 
			
		||||
							
								
								
									
										33
									
								
								kvm.h
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								kvm.h
									
									
									
									
									
								
							@@ -51,6 +51,7 @@ int kvm_has_debugregs(void);
 | 
			
		||||
int kvm_has_xsave(void);
 | 
			
		||||
int kvm_has_xcrs(void);
 | 
			
		||||
int kvm_has_many_ioeventfds(void);
 | 
			
		||||
int kvm_has_pit_state2(void);
 | 
			
		||||
 | 
			
		||||
#ifdef NEED_CPU_H
 | 
			
		||||
int kvm_init_vcpu(CPUState *env);
 | 
			
		||||
@@ -76,10 +77,10 @@ int kvm_set_signal_mask(CPUState *env, const sigset_t *sigset);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
int kvm_pit_in_kernel(void);
 | 
			
		||||
int kvm_irqchip_in_kernel(void);
 | 
			
		||||
 | 
			
		||||
int kvm_on_sigbus_vcpu(CPUState *env, int code, void *addr);
 | 
			
		||||
int kvm_on_sigbus(int code, void *addr);
 | 
			
		||||
#endif /* NEED_CPU_H */
 | 
			
		||||
 | 
			
		||||
/* internal API */
 | 
			
		||||
 | 
			
		||||
@@ -91,6 +92,7 @@ int kvm_ioctl(KVMState *s, int type, ...);
 | 
			
		||||
 | 
			
		||||
int kvm_vm_ioctl(KVMState *s, int type, ...);
 | 
			
		||||
 | 
			
		||||
#ifdef NEED_CPU_H
 | 
			
		||||
int kvm_vcpu_ioctl(CPUState *env, int type, ...);
 | 
			
		||||
 | 
			
		||||
/* Arch specific hooks */
 | 
			
		||||
@@ -186,7 +188,6 @@ static inline void cpu_synchronize_post_init(CPUState *env)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if !defined(CONFIG_USER_ONLY)
 | 
			
		||||
int kvm_physical_memory_addr_from_ram(KVMState *s, ram_addr_t ram_addr,
 | 
			
		||||
                                      target_phys_addr_t *phys_addr);
 | 
			
		||||
@@ -195,5 +196,33 @@ int kvm_physical_memory_addr_from_ram(KVMState *s, ram_addr_t ram_addr,
 | 
			
		||||
#endif
 | 
			
		||||
int kvm_set_ioeventfd_mmio_long(int fd, uint32_t adr, uint32_t val, bool assign);
 | 
			
		||||
 | 
			
		||||
int kvm_set_irqfd(int gsi, int fd, bool assigned);
 | 
			
		||||
 | 
			
		||||
int kvm_set_ioeventfd_pio_word(int fd, uint16_t adr, uint16_t val, bool assign);
 | 
			
		||||
 | 
			
		||||
typedef struct KVMMsiMessage {
 | 
			
		||||
    uint32_t gsi;
 | 
			
		||||
    uint32_t addr_lo;
 | 
			
		||||
    uint32_t addr_hi;
 | 
			
		||||
    uint32_t data;
 | 
			
		||||
} KVMMsiMessage;
 | 
			
		||||
 | 
			
		||||
int kvm_has_gsi_routing(void);
 | 
			
		||||
int kvm_allows_irq0_override(void);
 | 
			
		||||
int kvm_get_irq_route_gsi(void);
 | 
			
		||||
 | 
			
		||||
int kvm_msi_message_add(KVMMsiMessage *msg);
 | 
			
		||||
int kvm_msi_message_del(KVMMsiMessage *msg);
 | 
			
		||||
int kvm_msi_message_update(KVMMsiMessage *old, KVMMsiMessage *new);
 | 
			
		||||
 | 
			
		||||
int kvm_commit_irq_routes(void);
 | 
			
		||||
 | 
			
		||||
int kvm_irqchip_in_kernel(void);
 | 
			
		||||
 | 
			
		||||
int kvm_set_irq(int irq, int level, int *status);
 | 
			
		||||
 | 
			
		||||
#ifdef NEED_CPU_H
 | 
			
		||||
#include "qemu-kvm.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										66
									
								
								kvm/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								kvm/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,66 @@
 | 
			
		||||
*.o
 | 
			
		||||
*.d
 | 
			
		||||
*~
 | 
			
		||||
*.flat
 | 
			
		||||
*.a
 | 
			
		||||
config.mak
 | 
			
		||||
.*.cmd
 | 
			
		||||
qemu/config-host.h
 | 
			
		||||
qemu/config-host.mak
 | 
			
		||||
user/test/bootstrap
 | 
			
		||||
user/kvmctl
 | 
			
		||||
qemu/dyngen
 | 
			
		||||
qemu/x86_64-softmmu
 | 
			
		||||
qemu/qemu-img
 | 
			
		||||
qemu/qemu-nbd
 | 
			
		||||
*.ko
 | 
			
		||||
*.mod.c
 | 
			
		||||
bios/*.bin
 | 
			
		||||
bios/*.sym
 | 
			
		||||
bios/*.txt
 | 
			
		||||
bios/acpi-dsdt.aml
 | 
			
		||||
vgabios/*.bin
 | 
			
		||||
vgabios/*.txt
 | 
			
		||||
extboot/extboot.bin
 | 
			
		||||
extboot/extboot.img
 | 
			
		||||
extboot/signrom
 | 
			
		||||
kernel/config.kbuild
 | 
			
		||||
kernel/modules.order
 | 
			
		||||
kernel/Module.symvers
 | 
			
		||||
kernel/Modules.symvers
 | 
			
		||||
kernel/Module.markers
 | 
			
		||||
kernel/.tmp_versions
 | 
			
		||||
kernel/include-compat/asm
 | 
			
		||||
kernel/include-compat/asm-x86/asm-x86
 | 
			
		||||
kernel/include
 | 
			
		||||
kernel/x86/modules.order
 | 
			
		||||
kernel/x86/i825[49].[ch]
 | 
			
		||||
kernel/x86/kvm_main.c
 | 
			
		||||
kernel/x86/kvm_svm.h
 | 
			
		||||
kernel/x86/vmx.[ch]
 | 
			
		||||
kernel/x86/svm.[ch]
 | 
			
		||||
kernel/x86/mmu.[ch]
 | 
			
		||||
kernel/x86/paging_tmpl.h
 | 
			
		||||
kernel/x86/x86_emulate.[ch]
 | 
			
		||||
kernel/x86/ioapic.[ch]
 | 
			
		||||
kernel/x86/iodev.h
 | 
			
		||||
kernel/x86/irq.[ch]
 | 
			
		||||
kernel/x86/kvm_trace.c
 | 
			
		||||
kernel/x86/lapic.[ch]
 | 
			
		||||
kernel/x86/tss.h
 | 
			
		||||
kernel/x86/x86.[ch]
 | 
			
		||||
kernel/x86/coalesced_mmio.[ch]
 | 
			
		||||
kernel/x86/kvm_cache_regs.h
 | 
			
		||||
kernel/x86/vtd.c
 | 
			
		||||
kernel/x86/irq_comm.c
 | 
			
		||||
kernel/x86/timer.c
 | 
			
		||||
kernel/x86/kvm_timer.h
 | 
			
		||||
kernel/x86/iommu.c
 | 
			
		||||
qemu/pc-bios/extboot.bin
 | 
			
		||||
qemu/qemu-doc.html
 | 
			
		||||
qemu/*.[18]
 | 
			
		||||
qemu/*.pod
 | 
			
		||||
qemu/qemu-tech.html
 | 
			
		||||
qemu/qemu-options.texi
 | 
			
		||||
user/kvmtrace
 | 
			
		||||
user/test/x86/bootstrap
 | 
			
		||||
							
								
								
									
										125
									
								
								kvm/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								kvm/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,125 @@
 | 
			
		||||
 | 
			
		||||
include config.mak
 | 
			
		||||
 | 
			
		||||
DESTDIR=
 | 
			
		||||
 | 
			
		||||
rpmrelease = devel
 | 
			
		||||
 | 
			
		||||
sane-arch = $(subst i386,x86,$(subst x86_64,x86,$(subst s390x,s390,$(ARCH))))
 | 
			
		||||
 | 
			
		||||
.PHONY: kernel user libkvm qemu bios vgabios extboot clean libfdt cscope
 | 
			
		||||
 | 
			
		||||
all: libkvm qemu
 | 
			
		||||
ifneq '$(filter $(ARCH), x86_64 i386 ia64)' ''
 | 
			
		||||
    all: $(if $(WANT_MODULE), kernel) user
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
kcmd = $(if $(WANT_MODULE),,@\#)
 | 
			
		||||
 | 
			
		||||
qemu kernel user libkvm:
 | 
			
		||||
	$(MAKE) -C $@
 | 
			
		||||
 | 
			
		||||
qemu: libkvm
 | 
			
		||||
ifneq '$(filter $(ARCH), i386 x86_64)' ''
 | 
			
		||||
    qemu: extboot
 | 
			
		||||
endif
 | 
			
		||||
ifneq '$(filter $(ARCH), powerpc ia64)' ''
 | 
			
		||||
    qemu: libfdt
 | 
			
		||||
endif
 | 
			
		||||
user: libkvm
 | 
			
		||||
 | 
			
		||||
# sync if kernel/Makefile exists and if using --with-patched-kernel
 | 
			
		||||
user libkvm qemu: header-sync-$(if $(wildcard kernel/Makefile),$(if $(WANT_MODULE),n,y),n)
 | 
			
		||||
 | 
			
		||||
header-sync-n:
 | 
			
		||||
 | 
			
		||||
header-sync-y:
 | 
			
		||||
	make -C kernel \
 | 
			
		||||
	LINUX=$(if $(KERNELSOURCEDIR),$(KERNELSOURCEDIR),$(KERNELDIR)) \
 | 
			
		||||
	header-sync
 | 
			
		||||
	rm -f kernel/include/asm
 | 
			
		||||
	ln -sf asm-$(sane-arch) kernel/include/asm
 | 
			
		||||
 | 
			
		||||
bios:
 | 
			
		||||
	$(MAKE) -C $@
 | 
			
		||||
	cp bios/BIOS-bochs-latest qemu/pc-bios/bios.bin
 | 
			
		||||
 | 
			
		||||
vgabios:
 | 
			
		||||
	$(MAKE) -C $@
 | 
			
		||||
	cp vgabios/VGABIOS-lgpl-latest.bin qemu/pc-bios/vgabios.bin
 | 
			
		||||
	cp vgabios/VGABIOS-lgpl-latest.cirrus.bin qemu/pc-bios/vgabios-cirrus.bin
 | 
			
		||||
 | 
			
		||||
extboot:
 | 
			
		||||
	$(MAKE) -C $@
 | 
			
		||||
	if ! [ -f qemu/pc-bios/extboot.bin ] \
 | 
			
		||||
           || ! cmp -s qemu/pc-bios/extboot.bin extboot/extboot.bin; then \
 | 
			
		||||
		cp extboot/extboot.bin qemu/pc-bios/extboot.bin; \
 | 
			
		||||
	fi
 | 
			
		||||
libfdt:
 | 
			
		||||
	$(MAKE) -C $@
 | 
			
		||||
 | 
			
		||||
LINUX=linux-2.6
 | 
			
		||||
 | 
			
		||||
sync:
 | 
			
		||||
	make -C kernel sync LINUX=$(shell readlink -f "$(LINUX)")
 | 
			
		||||
 | 
			
		||||
bindir = /usr/bin
 | 
			
		||||
bin = $(bindir)/kvm
 | 
			
		||||
initdir = /etc/init.d
 | 
			
		||||
confdir = /etc/kvm
 | 
			
		||||
utilsdir = /etc/kvm/utils
 | 
			
		||||
 | 
			
		||||
install-rpm:
 | 
			
		||||
	mkdir -p $(DESTDIR)/$(bindir)
 | 
			
		||||
	mkdir -p $(DESTDIR)/$(confdir)
 | 
			
		||||
	mkdir -p $(DESTDIR)/$(initdir)
 | 
			
		||||
	mkdir -p $(DESTDIR)/$(utilsdir)
 | 
			
		||||
	mkdir -p $(DESTDIR)/etc/udev/rules.d
 | 
			
		||||
	make -C qemu DESTDIR=$(DESTDIR)/ install
 | 
			
		||||
	ln -sf /usr/kvm/bin/qemu-system-x86_64 $(DESTDIR)/$(bin)
 | 
			
		||||
	install -m 755 kvm_stat $(DESTDIR)/$(bindir)/kvm_stat
 | 
			
		||||
	cp scripts/kvm $(DESTDIR)/$(initdir)/kvm
 | 
			
		||||
	cp scripts/qemu-ifup $(DESTDIR)/$(confdir)/qemu-ifup
 | 
			
		||||
	install -t $(DESTDIR)/etc/udev/rules.d scripts/*kvm*.rules
 | 
			
		||||
 | 
			
		||||
install:
 | 
			
		||||
	$(kcmd)make -C kernel DESTDIR="$(DESTDIR)" install
 | 
			
		||||
	make -C libkvm DESTDIR="$(DESTDIR)" install
 | 
			
		||||
	make -C qemu DESTDIR="$(DESTDIR)" install
 | 
			
		||||
 | 
			
		||||
tmpspec = .tmp.kvm.spec
 | 
			
		||||
RPMTOPDIR = $$(pwd)/rpmtop
 | 
			
		||||
 | 
			
		||||
rpm:	srpm
 | 
			
		||||
	rm -rf $(RPMTOPDIR)/BUILD
 | 
			
		||||
	mkdir -p $(RPMTOPDIR)/{BUILD,RPMS/$$(uname -i)}
 | 
			
		||||
	rpmbuild --rebuild \
 | 
			
		||||
		 --define="_topdir $(RPMTOPDIR)" \
 | 
			
		||||
		$(RPMTOPDIR)/SRPMS/kvm-0.0-$(rpmrelease).src.rpm
 | 
			
		||||
 | 
			
		||||
srpm:
 | 
			
		||||
	mkdir -p $(RPMTOPDIR)/{SOURCES,SRPMS}
 | 
			
		||||
	sed 's/^Release:.*/Release: $(rpmrelease)/' kvm.spec > $(tmpspec)
 | 
			
		||||
	tar czf $(RPMTOPDIR)/SOURCES/kvm.tar.gz qemu
 | 
			
		||||
	tar czf $(RPMTOPDIR)/SOURCES/user.tar.gz user
 | 
			
		||||
	tar czf $(RPMTOPDIR)/SOURCES/libkvm.tar.gz libkvm
 | 
			
		||||
	tar czf $(RPMTOPDIR)/SOURCES/kernel.tar.gz kernel
 | 
			
		||||
	tar czf $(RPMTOPDIR)/SOURCES/scripts.tar.gz scripts
 | 
			
		||||
	tar czf $(RPMTOPDIR)/SOURCES/extboot.tar.gz extboot
 | 
			
		||||
	cp Makefile configure kvm_stat $(RPMTOPDIR)/SOURCES
 | 
			
		||||
	rpmbuild  --define="_topdir $(RPMTOPDIR)" -bs $(tmpspec)
 | 
			
		||||
	$(RM) $(tmpspec)
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	for i in $(if $(WANT_MODULE), kernel) user libkvm qemu libfdt; do \
 | 
			
		||||
		make -C $$i clean; \
 | 
			
		||||
	done
 | 
			
		||||
	rm -f ./cscope.*
 | 
			
		||||
 | 
			
		||||
distclean: clean
 | 
			
		||||
	rm -f config.mak user/config.mak
 | 
			
		||||
 | 
			
		||||
cscope:
 | 
			
		||||
	rm -f ./cscope.*
 | 
			
		||||
	find . -wholename './kernel' -prune -o -name "*.[ch]" -print > ./cscope.files
 | 
			
		||||
	cscope -b
 | 
			
		||||
							
								
								
									
										142
									
								
								kvm/configure
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										142
									
								
								kvm/configure
									
									
									
									
										vendored
									
									
										Executable file
									
								
							@@ -0,0 +1,142 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
prefix=/usr/local
 | 
			
		||||
kerneldir=/lib/modules/$(uname -r)/build
 | 
			
		||||
cc=gcc
 | 
			
		||||
ld=ld
 | 
			
		||||
objcopy=objcopy
 | 
			
		||||
ar=ar
 | 
			
		||||
want_module=1
 | 
			
		||||
qemu_cflags=
 | 
			
		||||
qemu_ldflags=
 | 
			
		||||
kvm_trace=
 | 
			
		||||
qemu_opts=()
 | 
			
		||||
cross_prefix=
 | 
			
		||||
arch=`uname -m`
 | 
			
		||||
target_exec=
 | 
			
		||||
# don't use uname if kerneldir is set
 | 
			
		||||
no_uname=
 | 
			
		||||
if [ -z "TMPDIR" ] ; then
 | 
			
		||||
    TMPDIR=.
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
if [ ! -e kernel/Makefile ]; then
 | 
			
		||||
    want_module=
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
usage() {
 | 
			
		||||
    cat <<-EOF
 | 
			
		||||
	Usage: $0 [options]
 | 
			
		||||
 | 
			
		||||
	Options include:
 | 
			
		||||
	    --arch=ARCH            architecture to compile for ($arch)
 | 
			
		||||
	    --cross-prefix=PREFIX  prefix for cross compile
 | 
			
		||||
	    --prefix=PREFIX        where to install things ($prefix)
 | 
			
		||||
	    --with-patched-kernel  don't use external module
 | 
			
		||||
	    --with-kvm-trace       Enable kvm_trace
 | 
			
		||||
	    --kerneldir=DIR        kernel build directory ($kerneldir)
 | 
			
		||||
	    --qemu-cflags=CFLAGS   CFLAGS to add to qemu configuration
 | 
			
		||||
	    --qemu-ldflags=LDFLAGS LDFLAGS to add to qemu configuration
 | 
			
		||||
 | 
			
		||||
EOF
 | 
			
		||||
    exit 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
while [[ "$1" = -* ]]; do
 | 
			
		||||
    opt="$1"; shift
 | 
			
		||||
    arg=
 | 
			
		||||
    hasarg=
 | 
			
		||||
    if [[ "$opt" = *=* ]]; then
 | 
			
		||||
	arg="${opt#*=}"
 | 
			
		||||
	opt="${opt%%=*}"
 | 
			
		||||
	hasarg=1
 | 
			
		||||
    fi
 | 
			
		||||
    case "$opt" in
 | 
			
		||||
	--prefix)
 | 
			
		||||
	    prefix="$arg"
 | 
			
		||||
	    ;;
 | 
			
		||||
	--kerneldir)
 | 
			
		||||
	    kerneldir="$arg"
 | 
			
		||||
            no_uname=1
 | 
			
		||||
	    ;;
 | 
			
		||||
	--with-patched-kernel)
 | 
			
		||||
	    want_module=
 | 
			
		||||
	    ;;
 | 
			
		||||
	--with-kvm-trace)
 | 
			
		||||
	    kvm_trace=y
 | 
			
		||||
	    ;;
 | 
			
		||||
	--qemu-cflags)
 | 
			
		||||
	    qemu_cflags="$arg"
 | 
			
		||||
	    ;;
 | 
			
		||||
	--qemu-ldflags)
 | 
			
		||||
	    qemu_ldflags="$arg"
 | 
			
		||||
	    ;;
 | 
			
		||||
	--arch)
 | 
			
		||||
	    arch="$arg"
 | 
			
		||||
	    ;;
 | 
			
		||||
	--cross-prefix)
 | 
			
		||||
	    cross_prefix="$arg"
 | 
			
		||||
            ;;
 | 
			
		||||
	--help)
 | 
			
		||||
	    usage
 | 
			
		||||
	    ;;
 | 
			
		||||
	*)
 | 
			
		||||
	    qemu_opts=("${qemu_opts[@]}" "$opt${hasarg:+=$arg}")
 | 
			
		||||
	    ;;
 | 
			
		||||
    esac
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#set kenel directory
 | 
			
		||||
libkvm_kerneldir=$(readlink -f kernel)
 | 
			
		||||
 | 
			
		||||
case $arch in
 | 
			
		||||
    i?86*|x86_64*)
 | 
			
		||||
        arch=${arch/#i?86/i386}
 | 
			
		||||
        target_exec="x86_64-softmmu"
 | 
			
		||||
        qemu_cflags="$qemu_cflags -DCONFIG_X86"
 | 
			
		||||
        ;;
 | 
			
		||||
    ia64*)
 | 
			
		||||
        target_exec="ia64-softmmu"
 | 
			
		||||
        ;;
 | 
			
		||||
    powerpc*)
 | 
			
		||||
        target_exec="ppcemb-softmmu"
 | 
			
		||||
        qemu_cflags="$qemu_cflags -I $PWD/libfdt"
 | 
			
		||||
        qemu_ldflags="$qemu_ldflags -L $PWD/libfdt"
 | 
			
		||||
        ;;
 | 
			
		||||
esac
 | 
			
		||||
 | 
			
		||||
processor=${arch#*-}
 | 
			
		||||
arch=${arch%%-*}
 | 
			
		||||
 | 
			
		||||
#configure kernel module
 | 
			
		||||
[ -e kernel/Makefile ] && (cd kernel;
 | 
			
		||||
    ./configure \
 | 
			
		||||
	--kerneldir="$kerneldir" \
 | 
			
		||||
	--arch="$arch" \
 | 
			
		||||
	$([ -z ${want_module} ] && echo "--with-patched-kernel") \
 | 
			
		||||
	${cross_prefix:+"--cross-prefix=$cross_prefix"} \
 | 
			
		||||
	${kvm_trace:+"--with-kvm-trace"}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
#configure user dir
 | 
			
		||||
(cd user; ./configure --prefix="$prefix" --kerneldir="$libkvm_kerneldir" \
 | 
			
		||||
          --arch="$arch" --processor="$processor" \
 | 
			
		||||
          ${cross_prefix:+"--cross-prefix=$cross_prefix"})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
cat <<EOF > config.mak
 | 
			
		||||
ARCH=$arch
 | 
			
		||||
PROCESSOR=$processor
 | 
			
		||||
PREFIX=$prefix
 | 
			
		||||
KERNELDIR=$kerneldir
 | 
			
		||||
KERNELSOURCEDIR=$kernelsourcedir
 | 
			
		||||
LIBKVM_KERNELDIR=$libkvm_kerneldir
 | 
			
		||||
WANT_MODULE=$want_module
 | 
			
		||||
CROSS_COMPILE=$cross_prefix
 | 
			
		||||
CC=$cross_prefix$cc
 | 
			
		||||
LD=$cross_prefix$ld
 | 
			
		||||
OBJCOPY=$cross_prefix$objcopy
 | 
			
		||||
AR=$cross_prefix$ar
 | 
			
		||||
EOF
 | 
			
		||||
							
								
								
									
										41
									
								
								kvm/extboot/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								kvm/extboot/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
OBJCOPY=objcopy
 | 
			
		||||
 | 
			
		||||
# from kernel sources - scripts/Kbuild.include
 | 
			
		||||
# try-run
 | 
			
		||||
# Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise)
 | 
			
		||||
# Exit code chooses option. "$$TMP" is can be used as temporary file and
 | 
			
		||||
# is automatically cleaned up.
 | 
			
		||||
try-run = $(shell set -e;		\
 | 
			
		||||
	TMP="$(TMPOUT).$$$$.tmp";	\
 | 
			
		||||
	if ($(1)) >/dev/null 2>&1;	\
 | 
			
		||||
	then echo "$(2)";		\
 | 
			
		||||
	else echo "$(3)";		\
 | 
			
		||||
	fi;				\
 | 
			
		||||
	rm -f "$$TMP")
 | 
			
		||||
 | 
			
		||||
# cc-option-yn
 | 
			
		||||
# Usage: flag := $(call cc-option-yn,-march=winchip-c6)
 | 
			
		||||
cc-option-yn = $(call try-run,\
 | 
			
		||||
	$(CC) $(KBUILD_CFLAGS) $(1) -S -xc /dev/null -o "$$TMP",y,n)
 | 
			
		||||
 | 
			
		||||
CFLAGS = -Wall -Wstrict-prototypes -Werror -fomit-frame-pointer -fno-builtin
 | 
			
		||||
ifeq ($(call cc-option-yn,-fno-stack-protector),y)
 | 
			
		||||
CFLAGS += -fno-stack-protector
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
all: extboot.bin
 | 
			
		||||
 | 
			
		||||
%.o: %.S
 | 
			
		||||
	$(CC) $(CFLAGS) -o $@ -c $<
 | 
			
		||||
 | 
			
		||||
extboot.img: extboot.o
 | 
			
		||||
	$(LD) --oformat binary -Ttext 0 -o $@ $<
 | 
			
		||||
 | 
			
		||||
extboot.bin: extboot.img signrom
 | 
			
		||||
	./signrom extboot.img extboot.bin
 | 
			
		||||
 | 
			
		||||
signrom: signrom.c
 | 
			
		||||
	$(CC) -o $@ -g -Wall $^
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	$(RM) *.o *.img *.bin signrom *~
 | 
			
		||||
							
								
								
									
										6
									
								
								kvm/extboot/STATUS
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								kvm/extboot/STATUS
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
Working
 | 
			
		||||
-------
 | 
			
		||||
 | 
			
		||||
Ubuntu Server 7.04 (i386)
 | 
			
		||||
Windows 2000 Professional (i386)
 | 
			
		||||
Windows XP SP2 (i386)
 | 
			
		||||
							
								
								
									
										79
									
								
								kvm/extboot/signrom.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								kvm/extboot/signrom.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,79 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Extended Boot Option ROM
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 | 
			
		||||
 * GNU 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright IBM Corporation, 2007
 | 
			
		||||
 *   Authors: Anthony Liguori <aliguori@us.ibm.com>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
int main(int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
	FILE *fin, *fout;
 | 
			
		||||
	char buffer[512], oldbuffer[512];
 | 
			
		||||
	int i, size, lag = 0;
 | 
			
		||||
	uint8_t sum = 0;
 | 
			
		||||
 | 
			
		||||
	if (argc != 3) {
 | 
			
		||||
		printf("Usage: %s ROM OUTPUT\n", argv[0]);
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fin = fopen(argv[1], "rb");
 | 
			
		||||
	fout = fopen(argv[2], "wb");
 | 
			
		||||
 | 
			
		||||
	if (fin == NULL || fout == NULL) {
 | 
			
		||||
		fprintf(stderr, "Could not open input/output files\n");
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		size = fread(buffer, 512, 1, fin);
 | 
			
		||||
		if (size == 1) {
 | 
			
		||||
			for (i = 0; i < 512; i++)
 | 
			
		||||
				sum += buffer[i];
 | 
			
		||||
 | 
			
		||||
			if (lag) {
 | 
			
		||||
				if (fwrite(oldbuffer, 512, 1, fout) != 1) {
 | 
			
		||||
					fprintf(stderr, "Write failed\n");
 | 
			
		||||
					return 1;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			lag = 1;
 | 
			
		||||
			memcpy(oldbuffer, buffer, 512);
 | 
			
		||||
		}
 | 
			
		||||
	} while (size == 1);
 | 
			
		||||
 | 
			
		||||
	if (size != 0) {
 | 
			
		||||
		fprintf(stderr, "Failed to read from input file\n");
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	oldbuffer[511] = -sum;
 | 
			
		||||
 | 
			
		||||
	if (fwrite(oldbuffer, 512, 1, fout) != 1) {
 | 
			
		||||
		fprintf(stderr, "Failed to write to output file\n");
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fclose(fin);
 | 
			
		||||
	fclose(fout);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										264
									
								
								kvm/include/ia64/asm/kvm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										264
									
								
								kvm/include/ia64/asm/kvm.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,264 @@
 | 
			
		||||
#ifndef __ASM_IA64_KVM_H
 | 
			
		||||
#define __ASM_IA64_KVM_H
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * kvm structure definitions  for ia64
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (C) 2007 Xiantao Zhang <xiantao.zhang@intel.com>
 | 
			
		||||
 *
 | 
			
		||||
 * 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 <linux/types.h>
 | 
			
		||||
#include <linux/ioctl.h>
 | 
			
		||||
 | 
			
		||||
/* Select x86 specific features in <linux/kvm.h> */
 | 
			
		||||
#define __KVM_HAVE_IOAPIC
 | 
			
		||||
#define __KVM_HAVE_DEVICE_ASSIGNMENT
 | 
			
		||||
 | 
			
		||||
/* Architectural interrupt line count. */
 | 
			
		||||
#define KVM_NR_INTERRUPTS 256
 | 
			
		||||
 | 
			
		||||
#define KVM_IOAPIC_NUM_PINS  48
 | 
			
		||||
 | 
			
		||||
struct kvm_ioapic_state {
 | 
			
		||||
	__u64 base_address;
 | 
			
		||||
	__u32 ioregsel;
 | 
			
		||||
	__u32 id;
 | 
			
		||||
	__u32 irr;
 | 
			
		||||
	__u32 pad;
 | 
			
		||||
	union {
 | 
			
		||||
		__u64 bits;
 | 
			
		||||
		struct {
 | 
			
		||||
			__u8 vector;
 | 
			
		||||
			__u8 delivery_mode:3;
 | 
			
		||||
			__u8 dest_mode:1;
 | 
			
		||||
			__u8 delivery_status:1;
 | 
			
		||||
			__u8 polarity:1;
 | 
			
		||||
			__u8 remote_irr:1;
 | 
			
		||||
			__u8 trig_mode:1;
 | 
			
		||||
			__u8 mask:1;
 | 
			
		||||
			__u8 reserve:7;
 | 
			
		||||
			__u8 reserved[4];
 | 
			
		||||
			__u8 dest_id;
 | 
			
		||||
		} fields;
 | 
			
		||||
	} redirtbl[KVM_IOAPIC_NUM_PINS];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define KVM_IRQCHIP_PIC_MASTER   0
 | 
			
		||||
#define KVM_IRQCHIP_PIC_SLAVE    1
 | 
			
		||||
#define KVM_IRQCHIP_IOAPIC       2
 | 
			
		||||
#define KVM_NR_IRQCHIPS          3
 | 
			
		||||
 | 
			
		||||
#define KVM_CONTEXT_SIZE	8*1024
 | 
			
		||||
 | 
			
		||||
struct kvm_fpreg {
 | 
			
		||||
	union {
 | 
			
		||||
		unsigned long bits[2];
 | 
			
		||||
		long double __dummy;	/* force 16-byte alignment */
 | 
			
		||||
	} u;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
union context {
 | 
			
		||||
	/* 8K size */
 | 
			
		||||
	char	dummy[KVM_CONTEXT_SIZE];
 | 
			
		||||
	struct {
 | 
			
		||||
		unsigned long       psr;
 | 
			
		||||
		unsigned long       pr;
 | 
			
		||||
		unsigned long       caller_unat;
 | 
			
		||||
		unsigned long       pad;
 | 
			
		||||
		unsigned long       gr[32];
 | 
			
		||||
		unsigned long       ar[128];
 | 
			
		||||
		unsigned long       br[8];
 | 
			
		||||
		unsigned long       cr[128];
 | 
			
		||||
		unsigned long       rr[8];
 | 
			
		||||
		unsigned long       ibr[8];
 | 
			
		||||
		unsigned long       dbr[8];
 | 
			
		||||
		unsigned long       pkr[8];
 | 
			
		||||
		struct kvm_fpreg   fr[128];
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct thash_data {
 | 
			
		||||
	union {
 | 
			
		||||
		struct {
 | 
			
		||||
			unsigned long p    :  1; /* 0 */
 | 
			
		||||
			unsigned long rv1  :  1; /* 1 */
 | 
			
		||||
			unsigned long ma   :  3; /* 2-4 */
 | 
			
		||||
			unsigned long a    :  1; /* 5 */
 | 
			
		||||
			unsigned long d    :  1; /* 6 */
 | 
			
		||||
			unsigned long pl   :  2; /* 7-8 */
 | 
			
		||||
			unsigned long ar   :  3; /* 9-11 */
 | 
			
		||||
			unsigned long ppn  : 38; /* 12-49 */
 | 
			
		||||
			unsigned long rv2  :  2; /* 50-51 */
 | 
			
		||||
			unsigned long ed   :  1; /* 52 */
 | 
			
		||||
			unsigned long ig1  : 11; /* 53-63 */
 | 
			
		||||
		};
 | 
			
		||||
		struct {
 | 
			
		||||
			unsigned long __rv1 : 53;     /* 0-52 */
 | 
			
		||||
			unsigned long contiguous : 1; /*53 */
 | 
			
		||||
			unsigned long tc : 1;         /* 54 TR or TC */
 | 
			
		||||
			unsigned long cl : 1;
 | 
			
		||||
			/* 55 I side or D side cache line */
 | 
			
		||||
			unsigned long len  :  4;      /* 56-59 */
 | 
			
		||||
			unsigned long io  : 1;	/* 60 entry is for io or not */
 | 
			
		||||
			unsigned long nomap : 1;
 | 
			
		||||
			/* 61 entry cann't be inserted into machine TLB.*/
 | 
			
		||||
			unsigned long checked : 1;
 | 
			
		||||
			/* 62 for VTLB/VHPT sanity check */
 | 
			
		||||
			unsigned long invalid : 1;
 | 
			
		||||
			/* 63 invalid entry */
 | 
			
		||||
		};
 | 
			
		||||
		unsigned long page_flags;
 | 
			
		||||
	};                  /* same for VHPT and TLB */
 | 
			
		||||
 | 
			
		||||
	union {
 | 
			
		||||
		struct {
 | 
			
		||||
			unsigned long rv3  :  2;
 | 
			
		||||
			unsigned long ps   :  6;
 | 
			
		||||
			unsigned long key  : 24;
 | 
			
		||||
			unsigned long rv4  : 32;
 | 
			
		||||
		};
 | 
			
		||||
		unsigned long itir;
 | 
			
		||||
	};
 | 
			
		||||
	union {
 | 
			
		||||
		struct {
 | 
			
		||||
			unsigned long ig2  :  12;
 | 
			
		||||
			unsigned long vpn  :  49;
 | 
			
		||||
			unsigned long vrn  :   3;
 | 
			
		||||
		};
 | 
			
		||||
		unsigned long ifa;
 | 
			
		||||
		unsigned long vadr;
 | 
			
		||||
		struct {
 | 
			
		||||
			unsigned long tag  :  63;
 | 
			
		||||
			unsigned long ti   :  1;
 | 
			
		||||
		};
 | 
			
		||||
		unsigned long etag;
 | 
			
		||||
	};
 | 
			
		||||
	union {
 | 
			
		||||
		struct thash_data *next;
 | 
			
		||||
		unsigned long rid;
 | 
			
		||||
		unsigned long gpaddr;
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define	NITRS	8
 | 
			
		||||
#define NDTRS	8
 | 
			
		||||
 | 
			
		||||
struct saved_vpd {
 | 
			
		||||
	unsigned long  vhpi;
 | 
			
		||||
	unsigned long  vgr[16];
 | 
			
		||||
	unsigned long  vbgr[16];
 | 
			
		||||
	unsigned long  vnat;
 | 
			
		||||
	unsigned long  vbnat;
 | 
			
		||||
	unsigned long  vcpuid[5];
 | 
			
		||||
	unsigned long  vpsr;
 | 
			
		||||
	unsigned long  vpr;
 | 
			
		||||
	union {
 | 
			
		||||
		unsigned long  vcr[128];
 | 
			
		||||
		struct {
 | 
			
		||||
			unsigned long dcr;
 | 
			
		||||
			unsigned long itm;
 | 
			
		||||
			unsigned long iva;
 | 
			
		||||
			unsigned long rsv1[5];
 | 
			
		||||
			unsigned long pta;
 | 
			
		||||
			unsigned long rsv2[7];
 | 
			
		||||
			unsigned long ipsr;
 | 
			
		||||
			unsigned long isr;
 | 
			
		||||
			unsigned long rsv3;
 | 
			
		||||
			unsigned long iip;
 | 
			
		||||
			unsigned long ifa;
 | 
			
		||||
			unsigned long itir;
 | 
			
		||||
			unsigned long iipa;
 | 
			
		||||
			unsigned long ifs;
 | 
			
		||||
			unsigned long iim;
 | 
			
		||||
			unsigned long iha;
 | 
			
		||||
			unsigned long rsv4[38];
 | 
			
		||||
			unsigned long lid;
 | 
			
		||||
			unsigned long ivr;
 | 
			
		||||
			unsigned long tpr;
 | 
			
		||||
			unsigned long eoi;
 | 
			
		||||
			unsigned long irr[4];
 | 
			
		||||
			unsigned long itv;
 | 
			
		||||
			unsigned long pmv;
 | 
			
		||||
			unsigned long cmcv;
 | 
			
		||||
			unsigned long rsv5[5];
 | 
			
		||||
			unsigned long lrr0;
 | 
			
		||||
			unsigned long lrr1;
 | 
			
		||||
			unsigned long rsv6[46];
 | 
			
		||||
		};
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct kvm_regs {
 | 
			
		||||
	struct saved_vpd vpd;
 | 
			
		||||
	/*Arch-regs*/
 | 
			
		||||
	int mp_state;
 | 
			
		||||
	unsigned long vmm_rr;
 | 
			
		||||
	/* TR and TC.  */
 | 
			
		||||
	struct thash_data itrs[NITRS];
 | 
			
		||||
	struct thash_data dtrs[NDTRS];
 | 
			
		||||
	/* Bit is set if there is a tr/tc for the region.  */
 | 
			
		||||
	unsigned char itr_regions;
 | 
			
		||||
	unsigned char dtr_regions;
 | 
			
		||||
	unsigned char tc_regions;
 | 
			
		||||
 | 
			
		||||
	char irq_check;
 | 
			
		||||
	unsigned long saved_itc;
 | 
			
		||||
	unsigned long itc_check;
 | 
			
		||||
	unsigned long timer_check;
 | 
			
		||||
	unsigned long timer_pending;
 | 
			
		||||
	unsigned long last_itc;
 | 
			
		||||
 | 
			
		||||
	unsigned long vrr[8];
 | 
			
		||||
	unsigned long ibr[8];
 | 
			
		||||
	unsigned long dbr[8];
 | 
			
		||||
	unsigned long insvc[4];		/* Interrupt in service.  */
 | 
			
		||||
	unsigned long xtp;
 | 
			
		||||
 | 
			
		||||
	unsigned long metaphysical_rr0; /* from kvm_arch (so is pinned) */
 | 
			
		||||
	unsigned long metaphysical_rr4;	/* from kvm_arch (so is pinned) */
 | 
			
		||||
	unsigned long metaphysical_saved_rr0; /* from kvm_arch          */
 | 
			
		||||
	unsigned long metaphysical_saved_rr4; /* from kvm_arch          */
 | 
			
		||||
	unsigned long fp_psr;       /*used for lazy float register */
 | 
			
		||||
	unsigned long saved_gp;
 | 
			
		||||
	/*for phycial  emulation */
 | 
			
		||||
 | 
			
		||||
	union context saved_guest;
 | 
			
		||||
 | 
			
		||||
	unsigned long reserved[64];	/* for future use */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct kvm_sregs {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct kvm_fpu {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define KVM_IA64_VCPU_STACK_SHIFT	16
 | 
			
		||||
#define KVM_IA64_VCPU_STACK_SIZE	(1UL << KVM_IA64_VCPU_STACK_SHIFT)
 | 
			
		||||
 | 
			
		||||
struct kvm_ia64_vcpu_stack {
 | 
			
		||||
	unsigned char stack[KVM_IA64_VCPU_STACK_SIZE];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct kvm_debug_exit_arch {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* for KVM_SET_GUEST_DEBUG */
 | 
			
		||||
struct kvm_guest_debug_arch {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										31
									
								
								kvm/include/ia64/asm/kvm_para.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								kvm/include/ia64/asm/kvm_para.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
#ifndef __IA64_KVM_PARA_H
 | 
			
		||||
#define __IA64_KVM_PARA_H
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2007 Xiantao Zhang <xiantao.zhang@intel.com>
 | 
			
		||||
 *
 | 
			
		||||
 * 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.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifdef __KERNEL__
 | 
			
		||||
 | 
			
		||||
static inline unsigned int kvm_arch_para_features(void)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										2
									
								
								kvm/include/linux/compiler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								kvm/include/linux/compiler.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
/* dummy file */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										43
									
								
								kvm/include/linux/config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								kvm/include/linux/config.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
#ifndef KVM_UNIFDEF_H
 | 
			
		||||
#define KVM_UNIFDEF_H
 | 
			
		||||
 | 
			
		||||
#ifdef __i386__
 | 
			
		||||
#ifndef CONFIG_X86_32
 | 
			
		||||
#define CONFIG_X86_32 1
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __x86_64__
 | 
			
		||||
#ifndef CONFIG_X86_64
 | 
			
		||||
#define CONFIG_X86_64 1
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__i386__) || defined (__x86_64__)
 | 
			
		||||
#ifndef CONFIG_X86
 | 
			
		||||
#define CONFIG_X86 1
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __ia64__
 | 
			
		||||
#ifndef CONFIG_IA64
 | 
			
		||||
#define CONFIG_IA64 1
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __PPC__
 | 
			
		||||
#ifndef CONFIG_PPC
 | 
			
		||||
#define CONFIG_PPC 1
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __s390__
 | 
			
		||||
#ifndef CONFIG_S390
 | 
			
		||||
#define CONFIG_S390 1
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define __user
 | 
			
		||||
							
								
								
									
										784
									
								
								kvm/include/linux/kvm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										784
									
								
								kvm/include/linux/kvm.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,784 @@
 | 
			
		||||
#ifndef __LINUX_KVM_H
 | 
			
		||||
#define __LINUX_KVM_H
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Userspace interface for /dev/kvm - kernel based virtual machine
 | 
			
		||||
 *
 | 
			
		||||
 * Note: you must update KVM_API_VERSION if you change this interface.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/compiler.h>
 | 
			
		||||
#include <linux/ioctl.h>
 | 
			
		||||
#include <asm/kvm.h>
 | 
			
		||||
 | 
			
		||||
#define KVM_API_VERSION 12
 | 
			
		||||
 | 
			
		||||
/* *** Deprecated interfaces *** */
 | 
			
		||||
 | 
			
		||||
#define KVM_TRC_SHIFT           16
 | 
			
		||||
 | 
			
		||||
#define KVM_TRC_ENTRYEXIT       (1 << KVM_TRC_SHIFT)
 | 
			
		||||
#define KVM_TRC_HANDLER         (1 << (KVM_TRC_SHIFT + 1))
 | 
			
		||||
 | 
			
		||||
#define KVM_TRC_VMENTRY         (KVM_TRC_ENTRYEXIT + 0x01)
 | 
			
		||||
#define KVM_TRC_VMEXIT          (KVM_TRC_ENTRYEXIT + 0x02)
 | 
			
		||||
#define KVM_TRC_PAGE_FAULT      (KVM_TRC_HANDLER + 0x01)
 | 
			
		||||
 | 
			
		||||
#define KVM_TRC_HEAD_SIZE       12
 | 
			
		||||
#define KVM_TRC_CYCLE_SIZE      8
 | 
			
		||||
#define KVM_TRC_EXTRA_MAX       7
 | 
			
		||||
 | 
			
		||||
#define KVM_TRC_INJ_VIRQ         (KVM_TRC_HANDLER + 0x02)
 | 
			
		||||
#define KVM_TRC_REDELIVER_EVT    (KVM_TRC_HANDLER + 0x03)
 | 
			
		||||
#define KVM_TRC_PEND_INTR        (KVM_TRC_HANDLER + 0x04)
 | 
			
		||||
#define KVM_TRC_IO_READ          (KVM_TRC_HANDLER + 0x05)
 | 
			
		||||
#define KVM_TRC_IO_WRITE         (KVM_TRC_HANDLER + 0x06)
 | 
			
		||||
#define KVM_TRC_CR_READ          (KVM_TRC_HANDLER + 0x07)
 | 
			
		||||
#define KVM_TRC_CR_WRITE         (KVM_TRC_HANDLER + 0x08)
 | 
			
		||||
#define KVM_TRC_DR_READ          (KVM_TRC_HANDLER + 0x09)
 | 
			
		||||
#define KVM_TRC_DR_WRITE         (KVM_TRC_HANDLER + 0x0A)
 | 
			
		||||
#define KVM_TRC_MSR_READ         (KVM_TRC_HANDLER + 0x0B)
 | 
			
		||||
#define KVM_TRC_MSR_WRITE        (KVM_TRC_HANDLER + 0x0C)
 | 
			
		||||
#define KVM_TRC_CPUID            (KVM_TRC_HANDLER + 0x0D)
 | 
			
		||||
#define KVM_TRC_INTR             (KVM_TRC_HANDLER + 0x0E)
 | 
			
		||||
#define KVM_TRC_NMI              (KVM_TRC_HANDLER + 0x0F)
 | 
			
		||||
#define KVM_TRC_VMMCALL          (KVM_TRC_HANDLER + 0x10)
 | 
			
		||||
#define KVM_TRC_HLT              (KVM_TRC_HANDLER + 0x11)
 | 
			
		||||
#define KVM_TRC_CLTS             (KVM_TRC_HANDLER + 0x12)
 | 
			
		||||
#define KVM_TRC_LMSW             (KVM_TRC_HANDLER + 0x13)
 | 
			
		||||
#define KVM_TRC_APIC_ACCESS      (KVM_TRC_HANDLER + 0x14)
 | 
			
		||||
#define KVM_TRC_TDP_FAULT        (KVM_TRC_HANDLER + 0x15)
 | 
			
		||||
#define KVM_TRC_GTLB_WRITE       (KVM_TRC_HANDLER + 0x16)
 | 
			
		||||
#define KVM_TRC_STLB_WRITE       (KVM_TRC_HANDLER + 0x17)
 | 
			
		||||
#define KVM_TRC_STLB_INVAL       (KVM_TRC_HANDLER + 0x18)
 | 
			
		||||
#define KVM_TRC_PPC_INSTR        (KVM_TRC_HANDLER + 0x19)
 | 
			
		||||
 | 
			
		||||
struct kvm_user_trace_setup {
 | 
			
		||||
	__u32 buf_size;
 | 
			
		||||
	__u32 buf_nr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define __KVM_DEPRECATED_MAIN_W_0x06 \
 | 
			
		||||
	_IOW(KVMIO, 0x06, struct kvm_user_trace_setup)
 | 
			
		||||
#define __KVM_DEPRECATED_MAIN_0x07 _IO(KVMIO, 0x07)
 | 
			
		||||
#define __KVM_DEPRECATED_MAIN_0x08 _IO(KVMIO, 0x08)
 | 
			
		||||
 | 
			
		||||
#define __KVM_DEPRECATED_VM_R_0x70 _IOR(KVMIO, 0x70, struct kvm_assigned_irq)
 | 
			
		||||
 | 
			
		||||
struct kvm_breakpoint {
 | 
			
		||||
	__u32 enabled;
 | 
			
		||||
	__u32 padding;
 | 
			
		||||
	__u64 address;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct kvm_debug_guest {
 | 
			
		||||
	__u32 enabled;
 | 
			
		||||
	__u32 pad;
 | 
			
		||||
	struct kvm_breakpoint breakpoints[4];
 | 
			
		||||
	__u32 singlestep;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define __KVM_DEPRECATED_VCPU_W_0x87 _IOW(KVMIO, 0x87, struct kvm_debug_guest)
 | 
			
		||||
 | 
			
		||||
/* *** End of deprecated interfaces *** */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* for KVM_CREATE_MEMORY_REGION */
 | 
			
		||||
struct kvm_memory_region {
 | 
			
		||||
	__u32 slot;
 | 
			
		||||
	__u32 flags;
 | 
			
		||||
	__u64 guest_phys_addr;
 | 
			
		||||
	__u64 memory_size; /* bytes */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* for KVM_SET_USER_MEMORY_REGION */
 | 
			
		||||
struct kvm_userspace_memory_region {
 | 
			
		||||
	__u32 slot;
 | 
			
		||||
	__u32 flags;
 | 
			
		||||
	__u64 guest_phys_addr;
 | 
			
		||||
	__u64 memory_size; /* bytes */
 | 
			
		||||
	__u64 userspace_addr; /* start of the userspace allocated memory */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* for kvm_memory_region::flags */
 | 
			
		||||
#define KVM_MEM_LOG_DIRTY_PAGES  1UL
 | 
			
		||||
#define KVM_MEMSLOT_INVALID      (1UL << 1)
 | 
			
		||||
 | 
			
		||||
/* for KVM_IRQ_LINE */
 | 
			
		||||
struct kvm_irq_level {
 | 
			
		||||
	/*
 | 
			
		||||
	 * ACPI gsi notion of irq.
 | 
			
		||||
	 * For IA-64 (APIC model) IOAPIC0: irq 0-23; IOAPIC1: irq 24-47..
 | 
			
		||||
	 * For X86 (standard AT mode) PIC0/1: irq 0-15. IOAPIC0: 0-23..
 | 
			
		||||
	 */
 | 
			
		||||
	union {
 | 
			
		||||
		__u32 irq;
 | 
			
		||||
		__s32 status;
 | 
			
		||||
	};
 | 
			
		||||
	__u32 level;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct kvm_irqchip {
 | 
			
		||||
	__u32 chip_id;
 | 
			
		||||
	__u32 pad;
 | 
			
		||||
        union {
 | 
			
		||||
		char dummy[512];  /* reserving space */
 | 
			
		||||
#ifdef __KVM_HAVE_PIT
 | 
			
		||||
		struct kvm_pic_state pic;
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef __KVM_HAVE_IOAPIC
 | 
			
		||||
		struct kvm_ioapic_state ioapic;
 | 
			
		||||
#endif
 | 
			
		||||
	} chip;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* for KVM_CREATE_PIT2 */
 | 
			
		||||
struct kvm_pit_config {
 | 
			
		||||
	__u32 flags;
 | 
			
		||||
	__u32 pad[15];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define KVM_PIT_SPEAKER_DUMMY     1
 | 
			
		||||
 | 
			
		||||
#define KVM_EXIT_UNKNOWN          0
 | 
			
		||||
#define KVM_EXIT_EXCEPTION        1
 | 
			
		||||
#define KVM_EXIT_IO               2
 | 
			
		||||
#define KVM_EXIT_HYPERCALL        3
 | 
			
		||||
#define KVM_EXIT_DEBUG            4
 | 
			
		||||
#define KVM_EXIT_HLT              5
 | 
			
		||||
#define KVM_EXIT_MMIO             6
 | 
			
		||||
#define KVM_EXIT_IRQ_WINDOW_OPEN  7
 | 
			
		||||
#define KVM_EXIT_SHUTDOWN         8
 | 
			
		||||
#define KVM_EXIT_FAIL_ENTRY       9
 | 
			
		||||
#define KVM_EXIT_INTR             10
 | 
			
		||||
#define KVM_EXIT_SET_TPR          11
 | 
			
		||||
#define KVM_EXIT_TPR_ACCESS       12
 | 
			
		||||
#define KVM_EXIT_S390_SIEIC       13
 | 
			
		||||
#define KVM_EXIT_S390_RESET       14
 | 
			
		||||
#define KVM_EXIT_DCR              15
 | 
			
		||||
#define KVM_EXIT_NMI              16
 | 
			
		||||
#define KVM_EXIT_INTERNAL_ERROR   17
 | 
			
		||||
#define KVM_EXIT_OSI              18
 | 
			
		||||
 | 
			
		||||
/* For KVM_EXIT_INTERNAL_ERROR */
 | 
			
		||||
#define KVM_INTERNAL_ERROR_EMULATION 1
 | 
			
		||||
#define KVM_INTERNAL_ERROR_SIMUL_EX 2
 | 
			
		||||
 | 
			
		||||
/* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */
 | 
			
		||||
struct kvm_run {
 | 
			
		||||
	/* in */
 | 
			
		||||
	__u8 request_interrupt_window;
 | 
			
		||||
	__u8 padding1[7];
 | 
			
		||||
 | 
			
		||||
	/* out */
 | 
			
		||||
	__u32 exit_reason;
 | 
			
		||||
	__u8 ready_for_interrupt_injection;
 | 
			
		||||
	__u8 if_flag;
 | 
			
		||||
	__u8 padding2[2];
 | 
			
		||||
 | 
			
		||||
	/* in (pre_kvm_run), out (post_kvm_run) */
 | 
			
		||||
	__u64 cr8;
 | 
			
		||||
	__u64 apic_base;
 | 
			
		||||
 | 
			
		||||
#ifdef __KVM_S390
 | 
			
		||||
	/* the processor status word for s390 */
 | 
			
		||||
	__u64 psw_mask; /* psw upper half */
 | 
			
		||||
	__u64 psw_addr; /* psw lower half */
 | 
			
		||||
#endif
 | 
			
		||||
	union {
 | 
			
		||||
		/* KVM_EXIT_UNKNOWN */
 | 
			
		||||
		struct {
 | 
			
		||||
			__u64 hardware_exit_reason;
 | 
			
		||||
		} hw;
 | 
			
		||||
		/* KVM_EXIT_FAIL_ENTRY */
 | 
			
		||||
		struct {
 | 
			
		||||
			__u64 hardware_entry_failure_reason;
 | 
			
		||||
		} fail_entry;
 | 
			
		||||
		/* KVM_EXIT_EXCEPTION */
 | 
			
		||||
		struct {
 | 
			
		||||
			__u32 exception;
 | 
			
		||||
			__u32 error_code;
 | 
			
		||||
		} ex;
 | 
			
		||||
		/* KVM_EXIT_IO */
 | 
			
		||||
		struct {
 | 
			
		||||
#define KVM_EXIT_IO_IN  0
 | 
			
		||||
#define KVM_EXIT_IO_OUT 1
 | 
			
		||||
			__u8 direction;
 | 
			
		||||
			__u8 size; /* bytes */
 | 
			
		||||
			__u16 port;
 | 
			
		||||
			__u32 count;
 | 
			
		||||
			__u64 data_offset; /* relative to kvm_run start */
 | 
			
		||||
		} io;
 | 
			
		||||
		struct {
 | 
			
		||||
			struct kvm_debug_exit_arch arch;
 | 
			
		||||
		} debug;
 | 
			
		||||
		/* KVM_EXIT_MMIO */
 | 
			
		||||
		struct {
 | 
			
		||||
			__u64 phys_addr;
 | 
			
		||||
			__u8  data[8];
 | 
			
		||||
			__u32 len;
 | 
			
		||||
			__u8  is_write;
 | 
			
		||||
		} mmio;
 | 
			
		||||
		/* KVM_EXIT_HYPERCALL */
 | 
			
		||||
		struct {
 | 
			
		||||
			__u64 nr;
 | 
			
		||||
			__u64 args[6];
 | 
			
		||||
			__u64 ret;
 | 
			
		||||
			__u32 longmode;
 | 
			
		||||
			__u32 pad;
 | 
			
		||||
		} hypercall;
 | 
			
		||||
		/* KVM_EXIT_TPR_ACCESS */
 | 
			
		||||
		struct {
 | 
			
		||||
			__u64 rip;
 | 
			
		||||
			__u32 is_write;
 | 
			
		||||
			__u32 pad;
 | 
			
		||||
		} tpr_access;
 | 
			
		||||
		/* KVM_EXIT_S390_SIEIC */
 | 
			
		||||
		struct {
 | 
			
		||||
			__u8 icptcode;
 | 
			
		||||
			__u16 ipa;
 | 
			
		||||
			__u32 ipb;
 | 
			
		||||
		} s390_sieic;
 | 
			
		||||
		/* KVM_EXIT_S390_RESET */
 | 
			
		||||
#define KVM_S390_RESET_POR       1
 | 
			
		||||
#define KVM_S390_RESET_CLEAR     2
 | 
			
		||||
#define KVM_S390_RESET_SUBSYSTEM 4
 | 
			
		||||
#define KVM_S390_RESET_CPU_INIT  8
 | 
			
		||||
#define KVM_S390_RESET_IPL       16
 | 
			
		||||
		__u64 s390_reset_flags;
 | 
			
		||||
		/* KVM_EXIT_DCR */
 | 
			
		||||
		struct {
 | 
			
		||||
			__u32 dcrn;
 | 
			
		||||
			__u32 data;
 | 
			
		||||
			__u8  is_write;
 | 
			
		||||
		} dcr;
 | 
			
		||||
		struct {
 | 
			
		||||
			__u32 suberror;
 | 
			
		||||
			/* Available with KVM_CAP_INTERNAL_ERROR_DATA: */
 | 
			
		||||
			__u32 ndata;
 | 
			
		||||
			__u64 data[16];
 | 
			
		||||
		} internal;
 | 
			
		||||
		/* KVM_EXIT_OSI */
 | 
			
		||||
		struct {
 | 
			
		||||
			__u64 gprs[32];
 | 
			
		||||
		} osi;
 | 
			
		||||
		/* Fix the size of the union. */
 | 
			
		||||
		char padding[256];
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* for KVM_REGISTER_COALESCED_MMIO / KVM_UNREGISTER_COALESCED_MMIO */
 | 
			
		||||
 | 
			
		||||
struct kvm_coalesced_mmio_zone {
 | 
			
		||||
	__u64 addr;
 | 
			
		||||
	__u32 size;
 | 
			
		||||
	__u32 pad;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct kvm_coalesced_mmio {
 | 
			
		||||
	__u64 phys_addr;
 | 
			
		||||
	__u32 len;
 | 
			
		||||
	__u32 pad;
 | 
			
		||||
	__u8  data[8];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct kvm_coalesced_mmio_ring {
 | 
			
		||||
	__u32 first, last;
 | 
			
		||||
	struct kvm_coalesced_mmio coalesced_mmio[0];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define KVM_COALESCED_MMIO_MAX \
 | 
			
		||||
	((PAGE_SIZE - sizeof(struct kvm_coalesced_mmio_ring)) / \
 | 
			
		||||
	 sizeof(struct kvm_coalesced_mmio))
 | 
			
		||||
 | 
			
		||||
/* for KVM_TRANSLATE */
 | 
			
		||||
struct kvm_translation {
 | 
			
		||||
	/* in */
 | 
			
		||||
	__u64 linear_address;
 | 
			
		||||
 | 
			
		||||
	/* out */
 | 
			
		||||
	__u64 physical_address;
 | 
			
		||||
	__u8  valid;
 | 
			
		||||
	__u8  writeable;
 | 
			
		||||
	__u8  usermode;
 | 
			
		||||
	__u8  pad[5];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* for KVM_INTERRUPT */
 | 
			
		||||
struct kvm_interrupt {
 | 
			
		||||
	/* in */
 | 
			
		||||
	__u32 irq;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* for KVM_GET_DIRTY_LOG */
 | 
			
		||||
struct kvm_dirty_log {
 | 
			
		||||
	__u32 slot;
 | 
			
		||||
	__u32 padding1;
 | 
			
		||||
	union {
 | 
			
		||||
		void *dirty_bitmap; /* one bit per page */
 | 
			
		||||
		__u64 padding2;
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* for KVM_SET_SIGNAL_MASK */
 | 
			
		||||
struct kvm_signal_mask {
 | 
			
		||||
	__u32 len;
 | 
			
		||||
	__u8  sigset[0];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* for KVM_TPR_ACCESS_REPORTING */
 | 
			
		||||
struct kvm_tpr_access_ctl {
 | 
			
		||||
	__u32 enabled;
 | 
			
		||||
	__u32 flags;
 | 
			
		||||
	__u32 reserved[8];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* for KVM_SET_VAPIC_ADDR */
 | 
			
		||||
struct kvm_vapic_addr {
 | 
			
		||||
	__u64 vapic_addr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* for KVM_SET_MPSTATE */
 | 
			
		||||
 | 
			
		||||
#define KVM_MP_STATE_RUNNABLE          0
 | 
			
		||||
#define KVM_MP_STATE_UNINITIALIZED     1
 | 
			
		||||
#define KVM_MP_STATE_INIT_RECEIVED     2
 | 
			
		||||
#define KVM_MP_STATE_HALTED            3
 | 
			
		||||
#define KVM_MP_STATE_SIPI_RECEIVED     4
 | 
			
		||||
 | 
			
		||||
struct kvm_mp_state {
 | 
			
		||||
	__u32 mp_state;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct kvm_s390_psw {
 | 
			
		||||
	__u64 mask;
 | 
			
		||||
	__u64 addr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* valid values for type in kvm_s390_interrupt */
 | 
			
		||||
#define KVM_S390_SIGP_STOP		0xfffe0000u
 | 
			
		||||
#define KVM_S390_PROGRAM_INT		0xfffe0001u
 | 
			
		||||
#define KVM_S390_SIGP_SET_PREFIX	0xfffe0002u
 | 
			
		||||
#define KVM_S390_RESTART		0xfffe0003u
 | 
			
		||||
#define KVM_S390_INT_VIRTIO		0xffff2603u
 | 
			
		||||
#define KVM_S390_INT_SERVICE		0xffff2401u
 | 
			
		||||
#define KVM_S390_INT_EMERGENCY		0xffff1201u
 | 
			
		||||
 | 
			
		||||
struct kvm_s390_interrupt {
 | 
			
		||||
	__u32 type;
 | 
			
		||||
	__u32 parm;
 | 
			
		||||
	__u64 parm64;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* for KVM_SET_GUEST_DEBUG */
 | 
			
		||||
 | 
			
		||||
#define KVM_GUESTDBG_ENABLE		0x00000001
 | 
			
		||||
#define KVM_GUESTDBG_SINGLESTEP		0x00000002
 | 
			
		||||
 | 
			
		||||
struct kvm_guest_debug {
 | 
			
		||||
	__u32 control;
 | 
			
		||||
	__u32 pad;
 | 
			
		||||
	struct kvm_guest_debug_arch arch;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
	kvm_ioeventfd_flag_nr_datamatch,
 | 
			
		||||
	kvm_ioeventfd_flag_nr_pio,
 | 
			
		||||
	kvm_ioeventfd_flag_nr_deassign,
 | 
			
		||||
	kvm_ioeventfd_flag_nr_max,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define KVM_IOEVENTFD_FLAG_DATAMATCH (1 << kvm_ioeventfd_flag_nr_datamatch)
 | 
			
		||||
#define KVM_IOEVENTFD_FLAG_PIO       (1 << kvm_ioeventfd_flag_nr_pio)
 | 
			
		||||
#define KVM_IOEVENTFD_FLAG_DEASSIGN  (1 << kvm_ioeventfd_flag_nr_deassign)
 | 
			
		||||
 | 
			
		||||
#define KVM_IOEVENTFD_VALID_FLAG_MASK  ((1 << kvm_ioeventfd_flag_nr_max) - 1)
 | 
			
		||||
 | 
			
		||||
struct kvm_ioeventfd {
 | 
			
		||||
	__u64 datamatch;
 | 
			
		||||
	__u64 addr;        /* legal pio/mmio address */
 | 
			
		||||
	__u32 len;         /* 1, 2, 4, or 8 bytes    */
 | 
			
		||||
	__s32 fd;
 | 
			
		||||
	__u32 flags;
 | 
			
		||||
	__u8  pad[36];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* for KVM_ENABLE_CAP */
 | 
			
		||||
struct kvm_enable_cap {
 | 
			
		||||
	/* in */
 | 
			
		||||
	__u32 cap;
 | 
			
		||||
	__u32 flags;
 | 
			
		||||
	__u64 args[4];
 | 
			
		||||
	__u8  pad[64];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define KVMIO 0xAE
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * ioctls for /dev/kvm fds:
 | 
			
		||||
 */
 | 
			
		||||
#define KVM_GET_API_VERSION       _IO(KVMIO,   0x00)
 | 
			
		||||
#define KVM_CREATE_VM             _IO(KVMIO,   0x01) /* returns a VM fd */
 | 
			
		||||
#define KVM_GET_MSR_INDEX_LIST    _IOWR(KVMIO, 0x02, struct kvm_msr_list)
 | 
			
		||||
 | 
			
		||||
#define KVM_S390_ENABLE_SIE       _IO(KVMIO,   0x06)
 | 
			
		||||
/*
 | 
			
		||||
 * Check if a kvm extension is available.  Argument is extension number,
 | 
			
		||||
 * return is 1 (yes) or 0 (no, sorry).
 | 
			
		||||
 */
 | 
			
		||||
#define KVM_CHECK_EXTENSION       _IO(KVMIO,   0x03)
 | 
			
		||||
/*
 | 
			
		||||
 * Get size for mmap(vcpu_fd)
 | 
			
		||||
 */
 | 
			
		||||
#define KVM_GET_VCPU_MMAP_SIZE    _IO(KVMIO,   0x04) /* in bytes */
 | 
			
		||||
#define KVM_GET_SUPPORTED_CPUID   _IOWR(KVMIO, 0x05, struct kvm_cpuid2)
 | 
			
		||||
#define KVM_TRACE_ENABLE          __KVM_DEPRECATED_MAIN_W_0x06
 | 
			
		||||
#define KVM_TRACE_PAUSE           __KVM_DEPRECATED_MAIN_0x07
 | 
			
		||||
#define KVM_TRACE_DISABLE         __KVM_DEPRECATED_MAIN_0x08
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Extension capability list.
 | 
			
		||||
 */
 | 
			
		||||
#define KVM_CAP_IRQCHIP	  0
 | 
			
		||||
#define KVM_CAP_HLT	  1
 | 
			
		||||
#define KVM_CAP_MMU_SHADOW_CACHE_CONTROL 2
 | 
			
		||||
#define KVM_CAP_USER_MEMORY 3
 | 
			
		||||
#define KVM_CAP_SET_TSS_ADDR 4
 | 
			
		||||
#define KVM_CAP_VAPIC 6
 | 
			
		||||
#define KVM_CAP_EXT_CPUID 7
 | 
			
		||||
#define KVM_CAP_CLOCKSOURCE 8
 | 
			
		||||
#define KVM_CAP_NR_VCPUS 9       /* returns max vcpus per vm */
 | 
			
		||||
#define KVM_CAP_NR_MEMSLOTS 10   /* returns max memory slots per vm */
 | 
			
		||||
#define KVM_CAP_PIT 11
 | 
			
		||||
#define KVM_CAP_NOP_IO_DELAY 12
 | 
			
		||||
#define KVM_CAP_PV_MMU 13
 | 
			
		||||
#define KVM_CAP_MP_STATE 14
 | 
			
		||||
#define KVM_CAP_COALESCED_MMIO 15
 | 
			
		||||
#define KVM_CAP_SYNC_MMU 16  /* Changes to host mmap are reflected in guest */
 | 
			
		||||
#ifdef __KVM_HAVE_DEVICE_ASSIGNMENT
 | 
			
		||||
#define KVM_CAP_DEVICE_ASSIGNMENT 17
 | 
			
		||||
#endif
 | 
			
		||||
#define KVM_CAP_IOMMU 18
 | 
			
		||||
#ifdef __KVM_HAVE_MSI
 | 
			
		||||
#define KVM_CAP_DEVICE_MSI 20
 | 
			
		||||
#endif
 | 
			
		||||
/* Bug in KVM_SET_USER_MEMORY_REGION fixed: */
 | 
			
		||||
#define KVM_CAP_DESTROY_MEMORY_REGION_WORKS 21
 | 
			
		||||
#ifdef __KVM_HAVE_USER_NMI
 | 
			
		||||
#define KVM_CAP_USER_NMI 22
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef __KVM_HAVE_GUEST_DEBUG
 | 
			
		||||
#define KVM_CAP_SET_GUEST_DEBUG 23
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef __KVM_HAVE_PIT
 | 
			
		||||
#define KVM_CAP_REINJECT_CONTROL 24
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef __KVM_HAVE_IOAPIC
 | 
			
		||||
#define KVM_CAP_IRQ_ROUTING 25
 | 
			
		||||
#endif
 | 
			
		||||
#define KVM_CAP_IRQ_INJECT_STATUS 26
 | 
			
		||||
#ifdef __KVM_HAVE_DEVICE_ASSIGNMENT
 | 
			
		||||
#define KVM_CAP_DEVICE_DEASSIGNMENT 27
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef __KVM_HAVE_MSIX
 | 
			
		||||
#define KVM_CAP_DEVICE_MSIX 28
 | 
			
		||||
#endif
 | 
			
		||||
#define KVM_CAP_ASSIGN_DEV_IRQ 29
 | 
			
		||||
/* Another bug in KVM_SET_USER_MEMORY_REGION fixed: */
 | 
			
		||||
#define KVM_CAP_JOIN_MEMORY_REGIONS_WORKS 30
 | 
			
		||||
#ifdef __KVM_HAVE_MCE
 | 
			
		||||
#define KVM_CAP_MCE 31
 | 
			
		||||
#endif
 | 
			
		||||
#define KVM_CAP_IRQFD 32
 | 
			
		||||
#ifdef __KVM_HAVE_PIT
 | 
			
		||||
#define KVM_CAP_PIT2 33
 | 
			
		||||
#endif
 | 
			
		||||
#define KVM_CAP_SET_BOOT_CPU_ID 34
 | 
			
		||||
#ifdef __KVM_HAVE_PIT_STATE2
 | 
			
		||||
#define KVM_CAP_PIT_STATE2 35
 | 
			
		||||
#endif
 | 
			
		||||
#define KVM_CAP_IOEVENTFD 36
 | 
			
		||||
#define KVM_CAP_SET_IDENTITY_MAP_ADDR 37
 | 
			
		||||
#ifdef __KVM_HAVE_XEN_HVM
 | 
			
		||||
#define KVM_CAP_XEN_HVM 38
 | 
			
		||||
#endif
 | 
			
		||||
#define KVM_CAP_ADJUST_CLOCK 39
 | 
			
		||||
#define KVM_CAP_INTERNAL_ERROR_DATA 40
 | 
			
		||||
#ifdef __KVM_HAVE_VCPU_EVENTS
 | 
			
		||||
#define KVM_CAP_VCPU_EVENTS 41
 | 
			
		||||
#endif
 | 
			
		||||
#define KVM_CAP_S390_PSW 42
 | 
			
		||||
#define KVM_CAP_PPC_SEGSTATE 43
 | 
			
		||||
#define KVM_CAP_HYPERV 44
 | 
			
		||||
#define KVM_CAP_HYPERV_VAPIC 45
 | 
			
		||||
#define KVM_CAP_HYPERV_SPIN 46
 | 
			
		||||
#define KVM_CAP_PCI_SEGMENT 47
 | 
			
		||||
#define KVM_CAP_PPC_PAIRED_SINGLES 48
 | 
			
		||||
#define KVM_CAP_INTR_SHADOW 49
 | 
			
		||||
#ifdef __KVM_HAVE_DEBUGREGS
 | 
			
		||||
#define KVM_CAP_DEBUGREGS 50
 | 
			
		||||
#endif
 | 
			
		||||
#define KVM_CAP_X86_ROBUST_SINGLESTEP 51
 | 
			
		||||
#define KVM_CAP_PPC_OSI 52
 | 
			
		||||
#define KVM_CAP_PPC_UNSET_IRQ 53
 | 
			
		||||
#define KVM_CAP_ENABLE_CAP 54
 | 
			
		||||
#ifdef __KVM_HAVE_XSAVE
 | 
			
		||||
#define KVM_CAP_XSAVE 55
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef __KVM_HAVE_XCRS
 | 
			
		||||
#define KVM_CAP_XCRS 56
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef KVM_CAP_IRQ_ROUTING
 | 
			
		||||
 | 
			
		||||
struct kvm_irq_routing_irqchip {
 | 
			
		||||
	__u32 irqchip;
 | 
			
		||||
	__u32 pin;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct kvm_irq_routing_msi {
 | 
			
		||||
	__u32 address_lo;
 | 
			
		||||
	__u32 address_hi;
 | 
			
		||||
	__u32 data;
 | 
			
		||||
	__u32 pad;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* gsi routing entry types */
 | 
			
		||||
#define KVM_IRQ_ROUTING_IRQCHIP 1
 | 
			
		||||
#define KVM_IRQ_ROUTING_MSI 2
 | 
			
		||||
 | 
			
		||||
struct kvm_irq_routing_entry {
 | 
			
		||||
	__u32 gsi;
 | 
			
		||||
	__u32 type;
 | 
			
		||||
	__u32 flags;
 | 
			
		||||
	__u32 pad;
 | 
			
		||||
	union {
 | 
			
		||||
		struct kvm_irq_routing_irqchip irqchip;
 | 
			
		||||
		struct kvm_irq_routing_msi msi;
 | 
			
		||||
		__u32 pad[8];
 | 
			
		||||
	} u;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct kvm_irq_routing {
 | 
			
		||||
	__u32 nr;
 | 
			
		||||
	__u32 flags;
 | 
			
		||||
	struct kvm_irq_routing_entry entries[0];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef KVM_CAP_MCE
 | 
			
		||||
/* x86 MCE */
 | 
			
		||||
struct kvm_x86_mce {
 | 
			
		||||
	__u64 status;
 | 
			
		||||
	__u64 addr;
 | 
			
		||||
	__u64 misc;
 | 
			
		||||
	__u64 mcg_status;
 | 
			
		||||
	__u8 bank;
 | 
			
		||||
	__u8 pad1[7];
 | 
			
		||||
	__u64 pad2[3];
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef KVM_CAP_XEN_HVM
 | 
			
		||||
struct kvm_xen_hvm_config {
 | 
			
		||||
	__u32 flags;
 | 
			
		||||
	__u32 msr;
 | 
			
		||||
	__u64 blob_addr_32;
 | 
			
		||||
	__u64 blob_addr_64;
 | 
			
		||||
	__u8 blob_size_32;
 | 
			
		||||
	__u8 blob_size_64;
 | 
			
		||||
	__u8 pad2[30];
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define KVM_IRQFD_FLAG_DEASSIGN (1 << 0)
 | 
			
		||||
 | 
			
		||||
struct kvm_irqfd {
 | 
			
		||||
	__u32 fd;
 | 
			
		||||
	__u32 gsi;
 | 
			
		||||
	__u32 flags;
 | 
			
		||||
	__u8  pad[20];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct kvm_clock_data {
 | 
			
		||||
	__u64 clock;
 | 
			
		||||
	__u32 flags;
 | 
			
		||||
	__u32 pad[9];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * ioctls for VM fds
 | 
			
		||||
 */
 | 
			
		||||
#define KVM_SET_MEMORY_REGION     _IOW(KVMIO,  0x40, struct kvm_memory_region)
 | 
			
		||||
/*
 | 
			
		||||
 * KVM_CREATE_VCPU receives as a parameter the vcpu slot, and returns
 | 
			
		||||
 * a vcpu fd.
 | 
			
		||||
 */
 | 
			
		||||
#define KVM_CREATE_VCPU           _IO(KVMIO,   0x41)
 | 
			
		||||
#define KVM_GET_DIRTY_LOG         _IOW(KVMIO,  0x42, struct kvm_dirty_log)
 | 
			
		||||
#define KVM_SET_MEMORY_ALIAS      _IOW(KVMIO,  0x43, struct kvm_memory_alias)
 | 
			
		||||
#define KVM_SET_NR_MMU_PAGES      _IO(KVMIO,   0x44)
 | 
			
		||||
#define KVM_GET_NR_MMU_PAGES      _IO(KVMIO,   0x45)
 | 
			
		||||
#define KVM_SET_USER_MEMORY_REGION _IOW(KVMIO, 0x46, \
 | 
			
		||||
					struct kvm_userspace_memory_region)
 | 
			
		||||
#define KVM_SET_TSS_ADDR          _IO(KVMIO,   0x47)
 | 
			
		||||
#define KVM_SET_IDENTITY_MAP_ADDR _IOW(KVMIO,  0x48, __u64)
 | 
			
		||||
/* Device model IOC */
 | 
			
		||||
#define KVM_CREATE_IRQCHIP        _IO(KVMIO,   0x60)
 | 
			
		||||
#define KVM_IRQ_LINE              _IOW(KVMIO,  0x61, struct kvm_irq_level)
 | 
			
		||||
#define KVM_GET_IRQCHIP           _IOWR(KVMIO, 0x62, struct kvm_irqchip)
 | 
			
		||||
#define KVM_SET_IRQCHIP           _IOR(KVMIO,  0x63, struct kvm_irqchip)
 | 
			
		||||
#define KVM_CREATE_PIT            _IO(KVMIO,   0x64)
 | 
			
		||||
#define KVM_GET_PIT               _IOWR(KVMIO, 0x65, struct kvm_pit_state)
 | 
			
		||||
#define KVM_SET_PIT               _IOR(KVMIO,  0x66, struct kvm_pit_state)
 | 
			
		||||
#define KVM_IRQ_LINE_STATUS       _IOWR(KVMIO, 0x67, struct kvm_irq_level)
 | 
			
		||||
#define KVM_REGISTER_COALESCED_MMIO \
 | 
			
		||||
			_IOW(KVMIO,  0x67, struct kvm_coalesced_mmio_zone)
 | 
			
		||||
#define KVM_UNREGISTER_COALESCED_MMIO \
 | 
			
		||||
			_IOW(KVMIO,  0x68, struct kvm_coalesced_mmio_zone)
 | 
			
		||||
#define KVM_ASSIGN_PCI_DEVICE     _IOR(KVMIO,  0x69, \
 | 
			
		||||
				       struct kvm_assigned_pci_dev)
 | 
			
		||||
#define KVM_SET_GSI_ROUTING       _IOW(KVMIO,  0x6a, struct kvm_irq_routing)
 | 
			
		||||
/* deprecated, replaced by KVM_ASSIGN_DEV_IRQ */
 | 
			
		||||
#define KVM_ASSIGN_IRQ            __KVM_DEPRECATED_VM_R_0x70
 | 
			
		||||
#define KVM_ASSIGN_DEV_IRQ        _IOW(KVMIO,  0x70, struct kvm_assigned_irq)
 | 
			
		||||
#define KVM_REINJECT_CONTROL      _IO(KVMIO,   0x71)
 | 
			
		||||
#define KVM_DEASSIGN_PCI_DEVICE   _IOW(KVMIO,  0x72, \
 | 
			
		||||
				       struct kvm_assigned_pci_dev)
 | 
			
		||||
#define KVM_ASSIGN_SET_MSIX_NR    _IOW(KVMIO,  0x73, \
 | 
			
		||||
				       struct kvm_assigned_msix_nr)
 | 
			
		||||
#define KVM_ASSIGN_SET_MSIX_ENTRY _IOW(KVMIO,  0x74, \
 | 
			
		||||
				       struct kvm_assigned_msix_entry)
 | 
			
		||||
#define KVM_DEASSIGN_DEV_IRQ      _IOW(KVMIO,  0x75, struct kvm_assigned_irq)
 | 
			
		||||
#define KVM_IRQFD                 _IOW(KVMIO,  0x76, struct kvm_irqfd)
 | 
			
		||||
#define KVM_CREATE_PIT2		  _IOW(KVMIO,  0x77, struct kvm_pit_config)
 | 
			
		||||
#define KVM_SET_BOOT_CPU_ID       _IO(KVMIO,   0x78)
 | 
			
		||||
#define KVM_IOEVENTFD             _IOW(KVMIO,  0x79, struct kvm_ioeventfd)
 | 
			
		||||
#define KVM_XEN_HVM_CONFIG        _IOW(KVMIO,  0x7a, struct kvm_xen_hvm_config)
 | 
			
		||||
#define KVM_SET_CLOCK             _IOW(KVMIO,  0x7b, struct kvm_clock_data)
 | 
			
		||||
#define KVM_GET_CLOCK             _IOR(KVMIO,  0x7c, struct kvm_clock_data)
 | 
			
		||||
/* Available with KVM_CAP_PIT_STATE2 */
 | 
			
		||||
#define KVM_GET_PIT2              _IOR(KVMIO,  0x9f, struct kvm_pit_state2)
 | 
			
		||||
#define KVM_SET_PIT2              _IOW(KVMIO,  0xa0, struct kvm_pit_state2)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * ioctls for vcpu fds
 | 
			
		||||
 */
 | 
			
		||||
#define KVM_RUN                   _IO(KVMIO,   0x80)
 | 
			
		||||
#define KVM_GET_REGS              _IOR(KVMIO,  0x81, struct kvm_regs)
 | 
			
		||||
#define KVM_SET_REGS              _IOW(KVMIO,  0x82, struct kvm_regs)
 | 
			
		||||
#define KVM_GET_SREGS             _IOR(KVMIO,  0x83, struct kvm_sregs)
 | 
			
		||||
#define KVM_SET_SREGS             _IOW(KVMIO,  0x84, struct kvm_sregs)
 | 
			
		||||
#define KVM_TRANSLATE             _IOWR(KVMIO, 0x85, struct kvm_translation)
 | 
			
		||||
#define KVM_INTERRUPT             _IOW(KVMIO,  0x86, struct kvm_interrupt)
 | 
			
		||||
/* KVM_DEBUG_GUEST is no longer supported, use KVM_SET_GUEST_DEBUG instead */
 | 
			
		||||
#define KVM_DEBUG_GUEST           __KVM_DEPRECATED_VCPU_W_0x87
 | 
			
		||||
#define KVM_GET_MSRS              _IOWR(KVMIO, 0x88, struct kvm_msrs)
 | 
			
		||||
#define KVM_SET_MSRS              _IOW(KVMIO,  0x89, struct kvm_msrs)
 | 
			
		||||
#define KVM_SET_CPUID             _IOW(KVMIO,  0x8a, struct kvm_cpuid)
 | 
			
		||||
#define KVM_SET_SIGNAL_MASK       _IOW(KVMIO,  0x8b, struct kvm_signal_mask)
 | 
			
		||||
#define KVM_GET_FPU               _IOR(KVMIO,  0x8c, struct kvm_fpu)
 | 
			
		||||
#define KVM_SET_FPU               _IOW(KVMIO,  0x8d, struct kvm_fpu)
 | 
			
		||||
#define KVM_GET_LAPIC             _IOR(KVMIO,  0x8e, struct kvm_lapic_state)
 | 
			
		||||
#define KVM_SET_LAPIC             _IOW(KVMIO,  0x8f, struct kvm_lapic_state)
 | 
			
		||||
#define KVM_SET_CPUID2            _IOW(KVMIO,  0x90, struct kvm_cpuid2)
 | 
			
		||||
#define KVM_GET_CPUID2            _IOWR(KVMIO, 0x91, struct kvm_cpuid2)
 | 
			
		||||
/* Available with KVM_CAP_VAPIC */
 | 
			
		||||
#define KVM_TPR_ACCESS_REPORTING  _IOWR(KVMIO, 0x92, struct kvm_tpr_access_ctl)
 | 
			
		||||
/* Available with KVM_CAP_VAPIC */
 | 
			
		||||
#define KVM_SET_VAPIC_ADDR        _IOW(KVMIO,  0x93, struct kvm_vapic_addr)
 | 
			
		||||
/* valid for virtual machine (for floating interrupt)_and_ vcpu */
 | 
			
		||||
#define KVM_S390_INTERRUPT        _IOW(KVMIO,  0x94, struct kvm_s390_interrupt)
 | 
			
		||||
/* store status for s390 */
 | 
			
		||||
#define KVM_S390_STORE_STATUS_NOADDR    (-1ul)
 | 
			
		||||
#define KVM_S390_STORE_STATUS_PREFIXED  (-2ul)
 | 
			
		||||
#define KVM_S390_STORE_STATUS	  _IOW(KVMIO,  0x95, unsigned long)
 | 
			
		||||
/* initial ipl psw for s390 */
 | 
			
		||||
#define KVM_S390_SET_INITIAL_PSW  _IOW(KVMIO,  0x96, struct kvm_s390_psw)
 | 
			
		||||
/* initial reset for s390 */
 | 
			
		||||
#define KVM_S390_INITIAL_RESET    _IO(KVMIO,   0x97)
 | 
			
		||||
#define KVM_GET_MP_STATE          _IOR(KVMIO,  0x98, struct kvm_mp_state)
 | 
			
		||||
#define KVM_SET_MP_STATE          _IOW(KVMIO,  0x99, struct kvm_mp_state)
 | 
			
		||||
/* Available with KVM_CAP_NMI */
 | 
			
		||||
#define KVM_NMI                   _IO(KVMIO,   0x9a)
 | 
			
		||||
/* Available with KVM_CAP_SET_GUEST_DEBUG */
 | 
			
		||||
#define KVM_SET_GUEST_DEBUG       _IOW(KVMIO,  0x9b, struct kvm_guest_debug)
 | 
			
		||||
/* MCE for x86 */
 | 
			
		||||
#define KVM_X86_SETUP_MCE         _IOW(KVMIO,  0x9c, __u64)
 | 
			
		||||
#define KVM_X86_GET_MCE_CAP_SUPPORTED _IOR(KVMIO,  0x9d, __u64)
 | 
			
		||||
#define KVM_X86_SET_MCE           _IOW(KVMIO,  0x9e, struct kvm_x86_mce)
 | 
			
		||||
/* IA64 stack access */
 | 
			
		||||
#define KVM_IA64_VCPU_GET_STACK   _IOR(KVMIO,  0x9a, void *)
 | 
			
		||||
#define KVM_IA64_VCPU_SET_STACK   _IOW(KVMIO,  0x9b, void *)
 | 
			
		||||
/* Available with KVM_CAP_VCPU_EVENTS */
 | 
			
		||||
#define KVM_GET_VCPU_EVENTS       _IOR(KVMIO,  0x9f, struct kvm_vcpu_events)
 | 
			
		||||
#define KVM_SET_VCPU_EVENTS       _IOW(KVMIO,  0xa0, struct kvm_vcpu_events)
 | 
			
		||||
/* Available with KVM_CAP_DEBUGREGS */
 | 
			
		||||
#define KVM_GET_DEBUGREGS         _IOR(KVMIO,  0xa1, struct kvm_debugregs)
 | 
			
		||||
#define KVM_SET_DEBUGREGS         _IOW(KVMIO,  0xa2, struct kvm_debugregs)
 | 
			
		||||
#define KVM_ENABLE_CAP            _IOW(KVMIO,  0xa3, struct kvm_enable_cap)
 | 
			
		||||
/* Available with KVM_CAP_XSAVE */
 | 
			
		||||
#define KVM_GET_XSAVE		  _IOR(KVMIO,  0xa4, struct kvm_xsave)
 | 
			
		||||
#define KVM_SET_XSAVE		  _IOW(KVMIO,  0xa5, struct kvm_xsave)
 | 
			
		||||
/* Available with KVM_CAP_XCRS */
 | 
			
		||||
#define KVM_GET_XCRS		  _IOR(KVMIO,  0xa6, struct kvm_xcrs)
 | 
			
		||||
#define KVM_SET_XCRS		  _IOW(KVMIO,  0xa7, struct kvm_xcrs)
 | 
			
		||||
 | 
			
		||||
#define KVM_DEV_ASSIGN_ENABLE_IOMMU	(1 << 0)
 | 
			
		||||
 | 
			
		||||
struct kvm_assigned_pci_dev {
 | 
			
		||||
	__u32 assigned_dev_id;
 | 
			
		||||
	__u32 busnr;
 | 
			
		||||
	__u32 devfn;
 | 
			
		||||
	__u32 flags;
 | 
			
		||||
	__u32 segnr;
 | 
			
		||||
	union {
 | 
			
		||||
		__u32 reserved[11];
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define KVM_DEV_IRQ_HOST_INTX    (1 << 0)
 | 
			
		||||
#define KVM_DEV_IRQ_HOST_MSI     (1 << 1)
 | 
			
		||||
#define KVM_DEV_IRQ_HOST_MSIX    (1 << 2)
 | 
			
		||||
 | 
			
		||||
#define KVM_DEV_IRQ_GUEST_INTX   (1 << 8)
 | 
			
		||||
#define KVM_DEV_IRQ_GUEST_MSI    (1 << 9)
 | 
			
		||||
#define KVM_DEV_IRQ_GUEST_MSIX   (1 << 10)
 | 
			
		||||
 | 
			
		||||
#define KVM_DEV_IRQ_HOST_MASK	 0x00ff
 | 
			
		||||
#define KVM_DEV_IRQ_GUEST_MASK   0xff00
 | 
			
		||||
 | 
			
		||||
struct kvm_assigned_irq {
 | 
			
		||||
	__u32 assigned_dev_id;
 | 
			
		||||
	__u32 host_irq;
 | 
			
		||||
	__u32 guest_irq;
 | 
			
		||||
	__u32 flags;
 | 
			
		||||
	union {
 | 
			
		||||
		struct {
 | 
			
		||||
			__u32 addr_lo;
 | 
			
		||||
			__u32 addr_hi;
 | 
			
		||||
			__u32 data;
 | 
			
		||||
		} guest_msi;
 | 
			
		||||
		__u32 reserved[12];
 | 
			
		||||
	};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct kvm_assigned_msix_nr {
 | 
			
		||||
	__u32 assigned_dev_id;
 | 
			
		||||
	__u16 entry_nr;
 | 
			
		||||
	__u16 padding;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define KVM_MAX_MSIX_PER_DEV		256
 | 
			
		||||
struct kvm_assigned_msix_entry {
 | 
			
		||||
	__u32 assigned_dev_id;
 | 
			
		||||
	__u32 gsi;
 | 
			
		||||
	__u16 entry; /* The index of entry in the MSI-X table */
 | 
			
		||||
	__u16 padding[3];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif /* __LINUX_KVM_H */
 | 
			
		||||
							
								
								
									
										41
									
								
								kvm/include/linux/kvm_para.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								kvm/include/linux/kvm_para.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
#ifndef __LINUX_KVM_PARA_H
 | 
			
		||||
#define __LINUX_KVM_PARA_H
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This header file provides a method for making a hypercall to the host
 | 
			
		||||
 * Architectures should define:
 | 
			
		||||
 * - kvm_hypercall0, kvm_hypercall1...
 | 
			
		||||
 * - kvm_arch_para_features
 | 
			
		||||
 * - kvm_para_available
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Return values for hypercalls */
 | 
			
		||||
#define KVM_ENOSYS		1000
 | 
			
		||||
#define KVM_EFAULT		EFAULT
 | 
			
		||||
#define KVM_E2BIG		E2BIG
 | 
			
		||||
#define KVM_EPERM		EPERM
 | 
			
		||||
 | 
			
		||||
#define KVM_HC_VAPIC_POLL_IRQ		1
 | 
			
		||||
#define KVM_HC_MMU_OP			2
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * hypercalls use architecture specific
 | 
			
		||||
 */
 | 
			
		||||
#include <asm/kvm_para.h>
 | 
			
		||||
 | 
			
		||||
#ifdef __KERNEL__
 | 
			
		||||
#ifdef CONFIG_KVM_GUEST
 | 
			
		||||
void __init kvm_guest_init(void);
 | 
			
		||||
#else
 | 
			
		||||
#define kvm_guest_init() do { } while (0)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static inline int kvm_para_has_feature(unsigned int feature)
 | 
			
		||||
{
 | 
			
		||||
	if (kvm_arch_para_features() & (1UL << feature))
 | 
			
		||||
		return 1;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
#endif /* __KERNEL__ */
 | 
			
		||||
#endif /* __LINUX_KVM_PARA_H */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										130
									
								
								kvm/include/linux/vhost.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								kvm/include/linux/vhost.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,130 @@
 | 
			
		||||
#ifndef _LINUX_VHOST_H
 | 
			
		||||
#define _LINUX_VHOST_H
 | 
			
		||||
/* Userspace interface for in-kernel virtio accelerators. */
 | 
			
		||||
 | 
			
		||||
/* vhost is used to reduce the number of system calls involved in virtio.
 | 
			
		||||
 *
 | 
			
		||||
 * Existing virtio net code is used in the guest without modification.
 | 
			
		||||
 *
 | 
			
		||||
 * This header includes interface used by userspace hypervisor for
 | 
			
		||||
 * device configuration.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
 | 
			
		||||
#include <linux/ioctl.h>
 | 
			
		||||
#include <linux/virtio_config.h>
 | 
			
		||||
#include <linux/virtio_ring.h>
 | 
			
		||||
 | 
			
		||||
struct vhost_vring_state {
 | 
			
		||||
	unsigned int index;
 | 
			
		||||
	unsigned int num;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct vhost_vring_file {
 | 
			
		||||
	unsigned int index;
 | 
			
		||||
	int fd; /* Pass -1 to unbind from file. */
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct vhost_vring_addr {
 | 
			
		||||
	unsigned int index;
 | 
			
		||||
	/* Option flags. */
 | 
			
		||||
	unsigned int flags;
 | 
			
		||||
	/* Flag values: */
 | 
			
		||||
	/* Whether log address is valid. If set enables logging. */
 | 
			
		||||
#define VHOST_VRING_F_LOG 0
 | 
			
		||||
 | 
			
		||||
	/* Start of array of descriptors (virtually contiguous) */
 | 
			
		||||
	__u64 desc_user_addr;
 | 
			
		||||
	/* Used structure address. Must be 32 bit aligned */
 | 
			
		||||
	__u64 used_user_addr;
 | 
			
		||||
	/* Available structure address. Must be 16 bit aligned */
 | 
			
		||||
	__u64 avail_user_addr;
 | 
			
		||||
	/* Logging support. */
 | 
			
		||||
	/* Log writes to used structure, at offset calculated from specified
 | 
			
		||||
	 * address. Address must be 32 bit aligned. */
 | 
			
		||||
	__u64 log_guest_addr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct vhost_memory_region {
 | 
			
		||||
	__u64 guest_phys_addr;
 | 
			
		||||
	__u64 memory_size; /* bytes */
 | 
			
		||||
	__u64 userspace_addr;
 | 
			
		||||
	__u64 flags_padding; /* No flags are currently specified. */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* All region addresses and sizes must be 4K aligned. */
 | 
			
		||||
#define VHOST_PAGE_SIZE 0x1000
 | 
			
		||||
 | 
			
		||||
struct vhost_memory {
 | 
			
		||||
	__u32 nregions;
 | 
			
		||||
	__u32 padding;
 | 
			
		||||
	struct vhost_memory_region regions[0];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* ioctls */
 | 
			
		||||
 | 
			
		||||
#define VHOST_VIRTIO 0xAF
 | 
			
		||||
 | 
			
		||||
/* Features bitmask for forward compatibility.  Transport bits are used for
 | 
			
		||||
 * vhost specific features. */
 | 
			
		||||
#define VHOST_GET_FEATURES	_IOR(VHOST_VIRTIO, 0x00, __u64)
 | 
			
		||||
#define VHOST_SET_FEATURES	_IOW(VHOST_VIRTIO, 0x00, __u64)
 | 
			
		||||
 | 
			
		||||
/* Set current process as the (exclusive) owner of this file descriptor.  This
 | 
			
		||||
 * must be called before any other vhost command.  Further calls to
 | 
			
		||||
 * VHOST_OWNER_SET fail until VHOST_OWNER_RESET is called. */
 | 
			
		||||
#define VHOST_SET_OWNER _IO(VHOST_VIRTIO, 0x01)
 | 
			
		||||
/* Give up ownership, and reset the device to default values.
 | 
			
		||||
 * Allows subsequent call to VHOST_OWNER_SET to succeed. */
 | 
			
		||||
#define VHOST_RESET_OWNER _IO(VHOST_VIRTIO, 0x02)
 | 
			
		||||
 | 
			
		||||
/* Set up/modify memory layout */
 | 
			
		||||
#define VHOST_SET_MEM_TABLE	_IOW(VHOST_VIRTIO, 0x03, struct vhost_memory)
 | 
			
		||||
 | 
			
		||||
/* Write logging setup. */
 | 
			
		||||
/* Memory writes can optionally be logged by setting bit at an offset
 | 
			
		||||
 * (calculated from the physical address) from specified log base.
 | 
			
		||||
 * The bit is set using an atomic 32 bit operation. */
 | 
			
		||||
/* Set base address for logging. */
 | 
			
		||||
#define VHOST_SET_LOG_BASE _IOW(VHOST_VIRTIO, 0x04, __u64)
 | 
			
		||||
/* Specify an eventfd file descriptor to signal on log write. */
 | 
			
		||||
#define VHOST_SET_LOG_FD _IOW(VHOST_VIRTIO, 0x07, int)
 | 
			
		||||
 | 
			
		||||
/* Ring setup. */
 | 
			
		||||
/* Set number of descriptors in ring. This parameter can not
 | 
			
		||||
 * be modified while ring is running (bound to a device). */
 | 
			
		||||
#define VHOST_SET_VRING_NUM _IOW(VHOST_VIRTIO, 0x10, struct vhost_vring_state)
 | 
			
		||||
/* Set addresses for the ring. */
 | 
			
		||||
#define VHOST_SET_VRING_ADDR _IOW(VHOST_VIRTIO, 0x11, struct vhost_vring_addr)
 | 
			
		||||
/* Base value where queue looks for available descriptors */
 | 
			
		||||
#define VHOST_SET_VRING_BASE _IOW(VHOST_VIRTIO, 0x12, struct vhost_vring_state)
 | 
			
		||||
/* Get accessor: reads index, writes value in num */
 | 
			
		||||
#define VHOST_GET_VRING_BASE _IOWR(VHOST_VIRTIO, 0x12, struct vhost_vring_state)
 | 
			
		||||
 | 
			
		||||
/* The following ioctls use eventfd file descriptors to signal and poll
 | 
			
		||||
 * for events. */
 | 
			
		||||
 | 
			
		||||
/* Set eventfd to poll for added buffers */
 | 
			
		||||
#define VHOST_SET_VRING_KICK _IOW(VHOST_VIRTIO, 0x20, struct vhost_vring_file)
 | 
			
		||||
/* Set eventfd to signal when buffers have beed used */
 | 
			
		||||
#define VHOST_SET_VRING_CALL _IOW(VHOST_VIRTIO, 0x21, struct vhost_vring_file)
 | 
			
		||||
/* Set eventfd to signal an error */
 | 
			
		||||
#define VHOST_SET_VRING_ERR _IOW(VHOST_VIRTIO, 0x22, struct vhost_vring_file)
 | 
			
		||||
 | 
			
		||||
/* VHOST_NET specific defines */
 | 
			
		||||
 | 
			
		||||
/* Attach virtio net ring to a raw socket, or tap device.
 | 
			
		||||
 * The socket must be already bound to an ethernet device, this device will be
 | 
			
		||||
 * used for transmit.  Pass fd -1 to unbind from the socket and the transmit
 | 
			
		||||
 * device.  This can be used to stop the ring (e.g. for migration). */
 | 
			
		||||
#define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file)
 | 
			
		||||
 | 
			
		||||
/* Feature bits */
 | 
			
		||||
/* Log all write descriptors. Can be changed while device is active. */
 | 
			
		||||
#define VHOST_F_LOG_ALL 26
 | 
			
		||||
/* vhost-net should add virtio_net_hdr for RX, and strip for TX packets. */
 | 
			
		||||
#define VHOST_NET_F_VIRTIO_NET_HDR 27
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										62
									
								
								kvm/include/powerpc/asm/kvm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								kvm/include/powerpc/asm/kvm.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License, version 2, as
 | 
			
		||||
 * published by the Free Software Foundation.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright IBM Corp. 2007
 | 
			
		||||
 *
 | 
			
		||||
 * Authors: Hollis Blanchard <hollisb@us.ibm.com>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __LINUX_KVM_POWERPC_H
 | 
			
		||||
#define __LINUX_KVM_POWERPC_H
 | 
			
		||||
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
 | 
			
		||||
struct kvm_regs {
 | 
			
		||||
	__u64 pc;
 | 
			
		||||
	__u64 cr;
 | 
			
		||||
	__u64 ctr;
 | 
			
		||||
	__u64 lr;
 | 
			
		||||
	__u64 xer;
 | 
			
		||||
	__u64 msr;
 | 
			
		||||
	__u64 srr0;
 | 
			
		||||
	__u64 srr1;
 | 
			
		||||
	__u64 pid;
 | 
			
		||||
 | 
			
		||||
	__u64 sprg0;
 | 
			
		||||
	__u64 sprg1;
 | 
			
		||||
	__u64 sprg2;
 | 
			
		||||
	__u64 sprg3;
 | 
			
		||||
	__u64 sprg4;
 | 
			
		||||
	__u64 sprg5;
 | 
			
		||||
	__u64 sprg6;
 | 
			
		||||
	__u64 sprg7;
 | 
			
		||||
 | 
			
		||||
	__u64 gpr[32];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct kvm_sregs {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct kvm_fpu {
 | 
			
		||||
	__u64 fpr[32];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct kvm_debug_exit_arch {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* for KVM_SET_GUEST_DEBUG */
 | 
			
		||||
struct kvm_guest_debug_arch {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif /* __LINUX_KVM_POWERPC_H */
 | 
			
		||||
							
								
								
									
										37
									
								
								kvm/include/powerpc/asm/kvm_para.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								kvm/include/powerpc/asm/kvm_para.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License, version 2, as
 | 
			
		||||
 * published by the Free Software Foundation.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright IBM Corp. 2008
 | 
			
		||||
 *
 | 
			
		||||
 * Authors: Hollis Blanchard <hollisb@us.ibm.com>
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __POWERPC_KVM_PARA_H__
 | 
			
		||||
#define __POWERPC_KVM_PARA_H__
 | 
			
		||||
 | 
			
		||||
#ifdef __KERNEL__
 | 
			
		||||
 | 
			
		||||
static inline int kvm_para_available(void)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline unsigned int kvm_arch_para_features(void)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* __KERNEL__ */
 | 
			
		||||
 | 
			
		||||
#endif /* __POWERPC_KVM_PARA_H__ */
 | 
			
		||||
							
								
								
									
										324
									
								
								kvm/include/x86/asm/kvm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										324
									
								
								kvm/include/x86/asm/kvm.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,324 @@
 | 
			
		||||
#ifndef _ASM_X86_KVM_H
 | 
			
		||||
#define _ASM_X86_KVM_H
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * KVM x86 specific structures and definitions
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/ioctl.h>
 | 
			
		||||
 | 
			
		||||
/* Select x86 specific features in <linux/kvm.h> */
 | 
			
		||||
#define __KVM_HAVE_PIT
 | 
			
		||||
#define __KVM_HAVE_IOAPIC
 | 
			
		||||
#define __KVM_HAVE_DEVICE_ASSIGNMENT
 | 
			
		||||
#define __KVM_HAVE_MSI
 | 
			
		||||
#define __KVM_HAVE_USER_NMI
 | 
			
		||||
#define __KVM_HAVE_GUEST_DEBUG
 | 
			
		||||
#define __KVM_HAVE_MSIX
 | 
			
		||||
#define __KVM_HAVE_MCE
 | 
			
		||||
#define __KVM_HAVE_PIT_STATE2
 | 
			
		||||
#define __KVM_HAVE_XEN_HVM
 | 
			
		||||
#define __KVM_HAVE_VCPU_EVENTS
 | 
			
		||||
#define __KVM_HAVE_DEBUGREGS
 | 
			
		||||
#define __KVM_HAVE_XSAVE
 | 
			
		||||
#define __KVM_HAVE_XCRS
 | 
			
		||||
 | 
			
		||||
/* Architectural interrupt line count. */
 | 
			
		||||
#define KVM_NR_INTERRUPTS 256
 | 
			
		||||
 | 
			
		||||
struct kvm_memory_alias {
 | 
			
		||||
	__u32 slot;  /* this has a different namespace than memory slots */
 | 
			
		||||
	__u32 flags;
 | 
			
		||||
	__u64 guest_phys_addr;
 | 
			
		||||
	__u64 memory_size;
 | 
			
		||||
	__u64 target_phys_addr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* for KVM_GET_IRQCHIP and KVM_SET_IRQCHIP */
 | 
			
		||||
struct kvm_pic_state {
 | 
			
		||||
	__u8 last_irr;	/* edge detection */
 | 
			
		||||
	__u8 irr;		/* interrupt request register */
 | 
			
		||||
	__u8 imr;		/* interrupt mask register */
 | 
			
		||||
	__u8 isr;		/* interrupt service register */
 | 
			
		||||
	__u8 priority_add;	/* highest irq priority */
 | 
			
		||||
	__u8 irq_base;
 | 
			
		||||
	__u8 read_reg_select;
 | 
			
		||||
	__u8 poll;
 | 
			
		||||
	__u8 special_mask;
 | 
			
		||||
	__u8 init_state;
 | 
			
		||||
	__u8 auto_eoi;
 | 
			
		||||
	__u8 rotate_on_auto_eoi;
 | 
			
		||||
	__u8 special_fully_nested_mode;
 | 
			
		||||
	__u8 init4;		/* true if 4 byte init */
 | 
			
		||||
	__u8 elcr;		/* PIIX edge/trigger selection */
 | 
			
		||||
	__u8 elcr_mask;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define KVM_IOAPIC_NUM_PINS  24
 | 
			
		||||
struct kvm_ioapic_state {
 | 
			
		||||
	__u64 base_address;
 | 
			
		||||
	__u32 ioregsel;
 | 
			
		||||
	__u32 id;
 | 
			
		||||
	__u32 irr;
 | 
			
		||||
	__u32 pad;
 | 
			
		||||
	union {
 | 
			
		||||
		__u64 bits;
 | 
			
		||||
		struct {
 | 
			
		||||
			__u8 vector;
 | 
			
		||||
			__u8 delivery_mode:3;
 | 
			
		||||
			__u8 dest_mode:1;
 | 
			
		||||
			__u8 delivery_status:1;
 | 
			
		||||
			__u8 polarity:1;
 | 
			
		||||
			__u8 remote_irr:1;
 | 
			
		||||
			__u8 trig_mode:1;
 | 
			
		||||
			__u8 mask:1;
 | 
			
		||||
			__u8 reserve:7;
 | 
			
		||||
			__u8 reserved[4];
 | 
			
		||||
			__u8 dest_id;
 | 
			
		||||
		} fields;
 | 
			
		||||
	} redirtbl[KVM_IOAPIC_NUM_PINS];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define KVM_IRQCHIP_PIC_MASTER   0
 | 
			
		||||
#define KVM_IRQCHIP_PIC_SLAVE    1
 | 
			
		||||
#define KVM_IRQCHIP_IOAPIC       2
 | 
			
		||||
#define KVM_NR_IRQCHIPS          3
 | 
			
		||||
 | 
			
		||||
/* for KVM_GET_REGS and KVM_SET_REGS */
 | 
			
		||||
struct kvm_regs {
 | 
			
		||||
	/* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
 | 
			
		||||
	__u64 rax, rbx, rcx, rdx;
 | 
			
		||||
	__u64 rsi, rdi, rsp, rbp;
 | 
			
		||||
	__u64 r8,  r9,  r10, r11;
 | 
			
		||||
	__u64 r12, r13, r14, r15;
 | 
			
		||||
	__u64 rip, rflags;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* for KVM_GET_LAPIC and KVM_SET_LAPIC */
 | 
			
		||||
#define KVM_APIC_REG_SIZE 0x400
 | 
			
		||||
struct kvm_lapic_state {
 | 
			
		||||
	char regs[KVM_APIC_REG_SIZE];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct kvm_segment {
 | 
			
		||||
	__u64 base;
 | 
			
		||||
	__u32 limit;
 | 
			
		||||
	__u16 selector;
 | 
			
		||||
	__u8  type;
 | 
			
		||||
	__u8  present, dpl, db, s, l, g, avl;
 | 
			
		||||
	__u8  unusable;
 | 
			
		||||
	__u8  padding;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct kvm_dtable {
 | 
			
		||||
	__u64 base;
 | 
			
		||||
	__u16 limit;
 | 
			
		||||
	__u16 padding[3];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* for KVM_GET_SREGS and KVM_SET_SREGS */
 | 
			
		||||
struct kvm_sregs {
 | 
			
		||||
	/* out (KVM_GET_SREGS) / in (KVM_SET_SREGS) */
 | 
			
		||||
	struct kvm_segment cs, ds, es, fs, gs, ss;
 | 
			
		||||
	struct kvm_segment tr, ldt;
 | 
			
		||||
	struct kvm_dtable gdt, idt;
 | 
			
		||||
	__u64 cr0, cr2, cr3, cr4, cr8;
 | 
			
		||||
	__u64 efer;
 | 
			
		||||
	__u64 apic_base;
 | 
			
		||||
	__u64 interrupt_bitmap[(KVM_NR_INTERRUPTS + 63) / 64];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* for KVM_GET_FPU and KVM_SET_FPU */
 | 
			
		||||
struct kvm_fpu {
 | 
			
		||||
	__u8  fpr[8][16];
 | 
			
		||||
	__u16 fcw;
 | 
			
		||||
	__u16 fsw;
 | 
			
		||||
	__u8  ftwx;  /* in fxsave format */
 | 
			
		||||
	__u8  pad1;
 | 
			
		||||
	__u16 last_opcode;
 | 
			
		||||
	__u64 last_ip;
 | 
			
		||||
	__u64 last_dp;
 | 
			
		||||
	__u8  xmm[16][16];
 | 
			
		||||
	__u32 mxcsr;
 | 
			
		||||
	__u32 pad2;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct kvm_msr_entry {
 | 
			
		||||
	__u32 index;
 | 
			
		||||
	__u32 reserved;
 | 
			
		||||
	__u64 data;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* for KVM_GET_MSRS and KVM_SET_MSRS */
 | 
			
		||||
struct kvm_msrs {
 | 
			
		||||
	__u32 nmsrs; /* number of msrs in entries */
 | 
			
		||||
	__u32 pad;
 | 
			
		||||
 | 
			
		||||
	struct kvm_msr_entry entries[0];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* for KVM_GET_MSR_INDEX_LIST */
 | 
			
		||||
struct kvm_msr_list {
 | 
			
		||||
	__u32 nmsrs; /* number of msrs in entries */
 | 
			
		||||
	__u32 indices[0];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct kvm_cpuid_entry {
 | 
			
		||||
	__u32 function;
 | 
			
		||||
	__u32 eax;
 | 
			
		||||
	__u32 ebx;
 | 
			
		||||
	__u32 ecx;
 | 
			
		||||
	__u32 edx;
 | 
			
		||||
	__u32 padding;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* for KVM_SET_CPUID */
 | 
			
		||||
struct kvm_cpuid {
 | 
			
		||||
	__u32 nent;
 | 
			
		||||
	__u32 padding;
 | 
			
		||||
	struct kvm_cpuid_entry entries[0];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct kvm_cpuid_entry2 {
 | 
			
		||||
	__u32 function;
 | 
			
		||||
	__u32 index;
 | 
			
		||||
	__u32 flags;
 | 
			
		||||
	__u32 eax;
 | 
			
		||||
	__u32 ebx;
 | 
			
		||||
	__u32 ecx;
 | 
			
		||||
	__u32 edx;
 | 
			
		||||
	__u32 padding[3];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX 1
 | 
			
		||||
#define KVM_CPUID_FLAG_STATEFUL_FUNC    2
 | 
			
		||||
#define KVM_CPUID_FLAG_STATE_READ_NEXT  4
 | 
			
		||||
 | 
			
		||||
/* for KVM_SET_CPUID2 */
 | 
			
		||||
struct kvm_cpuid2 {
 | 
			
		||||
	__u32 nent;
 | 
			
		||||
	__u32 padding;
 | 
			
		||||
	struct kvm_cpuid_entry2 entries[0];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* for KVM_GET_PIT and KVM_SET_PIT */
 | 
			
		||||
struct kvm_pit_channel_state {
 | 
			
		||||
	__u32 count; /* can be 65536 */
 | 
			
		||||
	__u16 latched_count;
 | 
			
		||||
	__u8 count_latched;
 | 
			
		||||
	__u8 status_latched;
 | 
			
		||||
	__u8 status;
 | 
			
		||||
	__u8 read_state;
 | 
			
		||||
	__u8 write_state;
 | 
			
		||||
	__u8 write_latch;
 | 
			
		||||
	__u8 rw_mode;
 | 
			
		||||
	__u8 mode;
 | 
			
		||||
	__u8 bcd;
 | 
			
		||||
	__u8 gate;
 | 
			
		||||
	__s64 count_load_time;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct kvm_debug_exit_arch {
 | 
			
		||||
	__u32 exception;
 | 
			
		||||
	__u32 pad;
 | 
			
		||||
	__u64 pc;
 | 
			
		||||
	__u64 dr6;
 | 
			
		||||
	__u64 dr7;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define KVM_GUESTDBG_USE_SW_BP		0x00010000
 | 
			
		||||
#define KVM_GUESTDBG_USE_HW_BP		0x00020000
 | 
			
		||||
#define KVM_GUESTDBG_INJECT_DB		0x00040000
 | 
			
		||||
#define KVM_GUESTDBG_INJECT_BP		0x00080000
 | 
			
		||||
 | 
			
		||||
/* for KVM_SET_GUEST_DEBUG */
 | 
			
		||||
struct kvm_guest_debug_arch {
 | 
			
		||||
	__u64 debugreg[8];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct kvm_pit_state {
 | 
			
		||||
	struct kvm_pit_channel_state channels[3];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define KVM_PIT_FLAGS_HPET_LEGACY  0x00000001
 | 
			
		||||
 | 
			
		||||
struct kvm_pit_state2 {
 | 
			
		||||
	struct kvm_pit_channel_state channels[3];
 | 
			
		||||
	__u32 flags;
 | 
			
		||||
	__u32 reserved[9];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct kvm_reinject_control {
 | 
			
		||||
	__u8 pit_reinject;
 | 
			
		||||
	__u8 reserved[31];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* When set in flags, include corresponding fields on KVM_SET_VCPU_EVENTS */
 | 
			
		||||
#define KVM_VCPUEVENT_VALID_NMI_PENDING	0x00000001
 | 
			
		||||
#define KVM_VCPUEVENT_VALID_SIPI_VECTOR	0x00000002
 | 
			
		||||
#define KVM_VCPUEVENT_VALID_SHADOW	0x00000004
 | 
			
		||||
 | 
			
		||||
/* Interrupt shadow states */
 | 
			
		||||
#define KVM_X86_SHADOW_INT_MOV_SS	0x01
 | 
			
		||||
#define KVM_X86_SHADOW_INT_STI		0x02
 | 
			
		||||
 | 
			
		||||
/* for KVM_GET/SET_VCPU_EVENTS */
 | 
			
		||||
struct kvm_vcpu_events {
 | 
			
		||||
	struct {
 | 
			
		||||
		__u8 injected;
 | 
			
		||||
		__u8 nr;
 | 
			
		||||
		__u8 has_error_code;
 | 
			
		||||
		__u8 pad;
 | 
			
		||||
		__u32 error_code;
 | 
			
		||||
	} exception;
 | 
			
		||||
	struct {
 | 
			
		||||
		__u8 injected;
 | 
			
		||||
		__u8 nr;
 | 
			
		||||
		__u8 soft;
 | 
			
		||||
		__u8 shadow;
 | 
			
		||||
	} interrupt;
 | 
			
		||||
	struct {
 | 
			
		||||
		__u8 injected;
 | 
			
		||||
		__u8 pending;
 | 
			
		||||
		__u8 masked;
 | 
			
		||||
		__u8 pad;
 | 
			
		||||
	} nmi;
 | 
			
		||||
	__u32 sipi_vector;
 | 
			
		||||
	__u32 flags;
 | 
			
		||||
	__u32 reserved[10];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* for KVM_GET/SET_DEBUGREGS */
 | 
			
		||||
struct kvm_debugregs {
 | 
			
		||||
	__u64 db[4];
 | 
			
		||||
	__u64 dr6;
 | 
			
		||||
	__u64 dr7;
 | 
			
		||||
	__u64 flags;
 | 
			
		||||
	__u64 reserved[9];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* for KVM_CAP_XSAVE */
 | 
			
		||||
struct kvm_xsave {
 | 
			
		||||
	__u32 region[1024];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define KVM_MAX_XCRS	16
 | 
			
		||||
 | 
			
		||||
struct kvm_xcr {
 | 
			
		||||
	__u32 xcr;
 | 
			
		||||
	__u32 reserved;
 | 
			
		||||
	__u64 value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct kvm_xcrs {
 | 
			
		||||
	__u32 nr_xcrs;
 | 
			
		||||
	__u32 flags;
 | 
			
		||||
	struct kvm_xcr xcrs[KVM_MAX_XCRS];
 | 
			
		||||
	__u64 padding[16];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif /* _ASM_X86_KVM_H */
 | 
			
		||||
							
								
								
									
										149
									
								
								kvm/include/x86/asm/kvm_para.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								kvm/include/x86/asm/kvm_para.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,149 @@
 | 
			
		||||
#ifndef _ASM_X86_KVM_PARA_H
 | 
			
		||||
#define _ASM_X86_KVM_PARA_H
 | 
			
		||||
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
 | 
			
		||||
/* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx.  It
 | 
			
		||||
 * should be used to determine that a VM is running under KVM.
 | 
			
		||||
 */
 | 
			
		||||
#define KVM_CPUID_SIGNATURE	0x40000000
 | 
			
		||||
 | 
			
		||||
/* This CPUID returns a feature bitmap in eax.  Before enabling a particular
 | 
			
		||||
 * paravirtualization, the appropriate feature bit should be checked.
 | 
			
		||||
 */
 | 
			
		||||
#define KVM_CPUID_FEATURES	0x40000001
 | 
			
		||||
#define KVM_FEATURE_CLOCKSOURCE		0
 | 
			
		||||
#define KVM_FEATURE_NOP_IO_DELAY	1
 | 
			
		||||
#define KVM_FEATURE_MMU_OP		2
 | 
			
		||||
 | 
			
		||||
#define MSR_KVM_WALL_CLOCK  0x11
 | 
			
		||||
#define MSR_KVM_SYSTEM_TIME 0x12
 | 
			
		||||
 | 
			
		||||
#define KVM_MAX_MMU_OP_BATCH           32
 | 
			
		||||
 | 
			
		||||
/* Operations for KVM_HC_MMU_OP */
 | 
			
		||||
#define KVM_MMU_OP_WRITE_PTE            1
 | 
			
		||||
#define KVM_MMU_OP_FLUSH_TLB	        2
 | 
			
		||||
#define KVM_MMU_OP_RELEASE_PT	        3
 | 
			
		||||
 | 
			
		||||
/* Payload for KVM_HC_MMU_OP */
 | 
			
		||||
struct kvm_mmu_op_header {
 | 
			
		||||
	__u32 op;
 | 
			
		||||
	__u32 pad;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct kvm_mmu_op_write_pte {
 | 
			
		||||
	struct kvm_mmu_op_header header;
 | 
			
		||||
	__u64 pte_phys;
 | 
			
		||||
	__u64 pte_val;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct kvm_mmu_op_flush_tlb {
 | 
			
		||||
	struct kvm_mmu_op_header header;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct kvm_mmu_op_release_pt {
 | 
			
		||||
	struct kvm_mmu_op_header header;
 | 
			
		||||
	__u64 pt_phys;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef __KERNEL__
 | 
			
		||||
#include <asm/processor.h>
 | 
			
		||||
 | 
			
		||||
extern void kvmclock_init(void);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* This instruction is vmcall.  On non-VT architectures, it will generate a
 | 
			
		||||
 * trap that we will then rewrite to the appropriate instruction.
 | 
			
		||||
 */
 | 
			
		||||
#define KVM_HYPERCALL ".byte 0x0f,0x01,0xc1"
 | 
			
		||||
 | 
			
		||||
/* For KVM hypercalls, a three-byte sequence of either the vmrun or the vmmrun
 | 
			
		||||
 * instruction.  The hypervisor may replace it with something else but only the
 | 
			
		||||
 * instructions are guaranteed to be supported.
 | 
			
		||||
 *
 | 
			
		||||
 * Up to four arguments may be passed in rbx, rcx, rdx, and rsi respectively.
 | 
			
		||||
 * The hypercall number should be placed in rax and the return value will be
 | 
			
		||||
 * placed in rax.  No other registers will be clobbered unless explicited
 | 
			
		||||
 * noted by the particular hypercall.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static inline long kvm_hypercall0(unsigned int nr)
 | 
			
		||||
{
 | 
			
		||||
	long ret;
 | 
			
		||||
	asm volatile(KVM_HYPERCALL
 | 
			
		||||
		     : "=a"(ret)
 | 
			
		||||
		     : "a"(nr)
 | 
			
		||||
		     : "memory");
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline long kvm_hypercall1(unsigned int nr, unsigned long p1)
 | 
			
		||||
{
 | 
			
		||||
	long ret;
 | 
			
		||||
	asm volatile(KVM_HYPERCALL
 | 
			
		||||
		     : "=a"(ret)
 | 
			
		||||
		     : "a"(nr), "b"(p1)
 | 
			
		||||
		     : "memory");
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline long kvm_hypercall2(unsigned int nr, unsigned long p1,
 | 
			
		||||
				  unsigned long p2)
 | 
			
		||||
{
 | 
			
		||||
	long ret;
 | 
			
		||||
	asm volatile(KVM_HYPERCALL
 | 
			
		||||
		     : "=a"(ret)
 | 
			
		||||
		     : "a"(nr), "b"(p1), "c"(p2)
 | 
			
		||||
		     : "memory");
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline long kvm_hypercall3(unsigned int nr, unsigned long p1,
 | 
			
		||||
				  unsigned long p2, unsigned long p3)
 | 
			
		||||
{
 | 
			
		||||
	long ret;
 | 
			
		||||
	asm volatile(KVM_HYPERCALL
 | 
			
		||||
		     : "=a"(ret)
 | 
			
		||||
		     : "a"(nr), "b"(p1), "c"(p2), "d"(p3)
 | 
			
		||||
		     : "memory");
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline long kvm_hypercall4(unsigned int nr, unsigned long p1,
 | 
			
		||||
				  unsigned long p2, unsigned long p3,
 | 
			
		||||
				  unsigned long p4)
 | 
			
		||||
{
 | 
			
		||||
	long ret;
 | 
			
		||||
	asm volatile(KVM_HYPERCALL
 | 
			
		||||
		     : "=a"(ret)
 | 
			
		||||
		     : "a"(nr), "b"(p1), "c"(p2), "d"(p3), "S"(p4)
 | 
			
		||||
		     : "memory");
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int kvm_para_available(void)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int eax, ebx, ecx, edx;
 | 
			
		||||
	char signature[13];
 | 
			
		||||
 | 
			
		||||
	cpuid(KVM_CPUID_SIGNATURE, &eax, &ebx, &ecx, &edx);
 | 
			
		||||
	memcpy(signature + 0, &ebx, 4);
 | 
			
		||||
	memcpy(signature + 4, &ecx, 4);
 | 
			
		||||
	memcpy(signature + 8, &edx, 4);
 | 
			
		||||
	signature[12] = 0;
 | 
			
		||||
 | 
			
		||||
	if (strcmp(signature, "KVMKVMKVM") == 0)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline unsigned int kvm_arch_para_features(void)
 | 
			
		||||
{
 | 
			
		||||
	return cpuid_eax(KVM_CPUID_FEATURES);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* _ASM_X86_KVM_PARA_H */
 | 
			
		||||
							
								
								
									
										139
									
								
								kvm/kvm.spec
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								kvm/kvm.spec
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,139 @@
 | 
			
		||||
Name:           kvm
 | 
			
		||||
Version:        0.0
 | 
			
		||||
Release:        0
 | 
			
		||||
Summary:        Kernel Virtual Machine virtualization environment
 | 
			
		||||
 | 
			
		||||
Group:          System Environment/Kernel
 | 
			
		||||
License:        GPL
 | 
			
		||||
URL:            http://www.qumranet.com
 | 
			
		||||
BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}
 | 
			
		||||
 | 
			
		||||
ExclusiveArch:  i386 x86_64 ia64
 | 
			
		||||
 | 
			
		||||
Requires:	kvm-kmod bridge-utils
 | 
			
		||||
 | 
			
		||||
%define Distribution %(rpm -q -qf /etc/redhat-release --qf '%%{name}' | cut -d"-"  -f 1)
 | 
			
		||||
%define os_version %(rpm -q --qf '%%{version}' %{Distribution}-release)
 | 
			
		||||
%define os_release %(rpm -q --qf '%%{release}' %{Distribution}-release | cut -d"." -f 1)
 | 
			
		||||
 | 
			
		||||
%if %([ x"%{Distribution}" = x"fedora" -a x"%{os_version}" = x"5" ] && echo 1 || echo 0)
 | 
			
		||||
%define require_gccver 32
 | 
			
		||||
%endif
 | 
			
		||||
 | 
			
		||||
%if %([ x"%{Distribution}" = x"fedora" -a 0"%{os_version}" -ge "8" ] && echo 1 || echo 0)
 | 
			
		||||
%define qemuldflags --qemu-ldflags=-Wl,--build-id
 | 
			
		||||
%else
 | 
			
		||||
%define qemuldflags ""
 | 
			
		||||
%endif
 | 
			
		||||
 | 
			
		||||
%if %([ x"%{Distribution}" = x"centos" -a x"%{os_version}" = x"4" ] && echo 1 || echo 0)
 | 
			
		||||
%define require_gccver 32
 | 
			
		||||
%endif
 | 
			
		||||
 | 
			
		||||
%if %([ x"%{Distribution}" = x"redhat" -a x"%{os_release}" = x"5" ] && echo 1 || echo 0)
 | 
			
		||||
%define require_gccver 34
 | 
			
		||||
%endif
 | 
			
		||||
 | 
			
		||||
%if %( [ x"%{require_gccver}" = x"32" ] && echo 1 || echo 0)
 | 
			
		||||
BuildRequires: compat-gcc-32
 | 
			
		||||
%else
 | 
			
		||||
BuildRequires: compat-gcc-34
 | 
			
		||||
%endif
 | 
			
		||||
 | 
			
		||||
BuildRequires:  SDL-devel zlib-devel alsa-lib-devel
 | 
			
		||||
 | 
			
		||||
%define _prebuilt %{?prebuilt:1}%{!?prebuilt:0}
 | 
			
		||||
 | 
			
		||||
%if !%{_prebuilt}
 | 
			
		||||
Source0: kvm.tar.gz
 | 
			
		||||
Source1: user.tar.gz
 | 
			
		||||
Source2: kernel.tar.gz
 | 
			
		||||
Source3: scripts.tar.gz
 | 
			
		||||
Source4: Makefile
 | 
			
		||||
Source5: configure
 | 
			
		||||
Source6: kvm_stat
 | 
			
		||||
Source7: libkvm.tar.gz
 | 
			
		||||
Source8: extboot.tar.gz
 | 
			
		||||
%endif
 | 
			
		||||
 | 
			
		||||
%description
 | 
			
		||||
The Kernel Virtual Machine provides a virtualization enviroment for processors
 | 
			
		||||
with hardware support for virtualization: Intel's VT-x&VT-i and AMD's AMD-V.
 | 
			
		||||
 | 
			
		||||
%prep
 | 
			
		||||
 | 
			
		||||
%if !%{_prebuilt}
 | 
			
		||||
%setup -T -b 0 -n qemu
 | 
			
		||||
%setup -T -b 1 -n user -D
 | 
			
		||||
%setup -T -b 2 -n kernel -D
 | 
			
		||||
%setup -T -b 7 -n libkvm -D
 | 
			
		||||
%setup -T -b 3 -n scripts -D
 | 
			
		||||
%setup -T -b 8 -n extboot -D
 | 
			
		||||
cd ..
 | 
			
		||||
cp %{_sourcedir}/Makefile %{_sourcedir}/configure %{_sourcedir}/kvm_stat .
 | 
			
		||||
%endif
 | 
			
		||||
 | 
			
		||||
%build
 | 
			
		||||
 | 
			
		||||
rm -rf %{buildroot}
 | 
			
		||||
 | 
			
		||||
%if !%{_prebuilt}
 | 
			
		||||
cd ..
 | 
			
		||||
./configure --prefix=/usr/kvm %{qemuldflags}
 | 
			
		||||
make -C libkvm
 | 
			
		||||
make -C user
 | 
			
		||||
%ifarch i386 x86_64
 | 
			
		||||
make extboot
 | 
			
		||||
%endif
 | 
			
		||||
#(cd qemu;
 | 
			
		||||
#    ./co
 | 
			
		||||
#   kpath="$(readlink -f ../kernel/include)"
 | 
			
		||||
#   upath="$(readlink -f ../user)"
 | 
			
		||||
#   ./configure --target-list=$(uname -i)-softmmu \
 | 
			
		||||
#	    --extra-cflags="-I$kpath -I$upath" \
 | 
			
		||||
#	    --extra-ldflags="-L$upath" \
 | 
			
		||||
#	    --disable-kqemu --enable-kvm --prefix=/usr/kvm
 | 
			
		||||
#)
 | 
			
		||||
make -C qemu
 | 
			
		||||
%endif
 | 
			
		||||
 | 
			
		||||
%install
 | 
			
		||||
 | 
			
		||||
%if !%{_prebuilt}
 | 
			
		||||
cd ..
 | 
			
		||||
%else
 | 
			
		||||
cd %{objdir}
 | 
			
		||||
%endif
 | 
			
		||||
 | 
			
		||||
make DESTDIR=%{buildroot} install-rpm
 | 
			
		||||
 | 
			
		||||
%define bindir /usr/bin
 | 
			
		||||
%define bin %{bindir}/kvm
 | 
			
		||||
%define initdir /etc/init.d
 | 
			
		||||
%define confdir /etc/kvm
 | 
			
		||||
%define utilsdir /etc/kvm/utils
 | 
			
		||||
 | 
			
		||||
%post 
 | 
			
		||||
/sbin/chkconfig --add kvm
 | 
			
		||||
/sbin/chkconfig --level 2345 kvm on
 | 
			
		||||
/sbin/chkconfig --level 16 kvm off
 | 
			
		||||
/usr/sbin/groupadd -fg 444 kvm
 | 
			
		||||
 | 
			
		||||
%preun
 | 
			
		||||
if [ "$1" != 0 ]; then
 | 
			
		||||
	/sbin/service kvm stop
 | 
			
		||||
	/sbin/chkconfig --level 2345 kvm off
 | 
			
		||||
	/sbin/chkconfig --del kvm
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
%clean
 | 
			
		||||
%{__rm} -rf %{buildroot}
 | 
			
		||||
 | 
			
		||||
%files
 | 
			
		||||
/usr/bin/kvm
 | 
			
		||||
/usr/bin/kvm_stat
 | 
			
		||||
%{confdir}/qemu-ifup
 | 
			
		||||
%{initdir}/kvm  
 | 
			
		||||
/etc/udev/rules.d/*kvm*.rules
 | 
			
		||||
/usr/kvm
 | 
			
		||||
%changelog
 | 
			
		||||
							
								
								
									
										469
									
								
								kvm/kvm_stat
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										469
									
								
								kvm/kvm_stat
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,469 @@
 | 
			
		||||
#!/usr/bin/python
 | 
			
		||||
 | 
			
		||||
import curses
 | 
			
		||||
import sys, os, time, optparse
 | 
			
		||||
 | 
			
		||||
class DebugfsProvider(object):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        self.base = '/sys/kernel/debug/kvm'
 | 
			
		||||
        self._fields = os.listdir(self.base)
 | 
			
		||||
    def fields(self):
 | 
			
		||||
        return self._fields
 | 
			
		||||
    def select(self, fields):
 | 
			
		||||
        self._fields = fields
 | 
			
		||||
    def read(self):
 | 
			
		||||
        def val(key):
 | 
			
		||||
            return int(file(self.base + '/' + key).read())
 | 
			
		||||
        return dict([(key, val(key)) for key in self._fields])
 | 
			
		||||
 | 
			
		||||
vmx_exit_reasons = {
 | 
			
		||||
    0: 'EXCEPTION_NMI',
 | 
			
		||||
    1: 'EXTERNAL_INTERRUPT',
 | 
			
		||||
    2: 'TRIPLE_FAULT',
 | 
			
		||||
    7: 'PENDING_INTERRUPT',
 | 
			
		||||
    8: 'NMI_WINDOW',
 | 
			
		||||
    9: 'TASK_SWITCH',
 | 
			
		||||
    10: 'CPUID',
 | 
			
		||||
    12: 'HLT',
 | 
			
		||||
    14: 'INVLPG',
 | 
			
		||||
    15: 'RDPMC',
 | 
			
		||||
    16: 'RDTSC',
 | 
			
		||||
    18: 'VMCALL',
 | 
			
		||||
    19: 'VMCLEAR',
 | 
			
		||||
    20: 'VMLAUNCH',
 | 
			
		||||
    21: 'VMPTRLD',
 | 
			
		||||
    22: 'VMPTRST',
 | 
			
		||||
    23: 'VMREAD',
 | 
			
		||||
    24: 'VMRESUME',
 | 
			
		||||
    25: 'VMWRITE',
 | 
			
		||||
    26: 'VMOFF',
 | 
			
		||||
    27: 'VMON',
 | 
			
		||||
    28: 'CR_ACCESS',
 | 
			
		||||
    29: 'DR_ACCESS',
 | 
			
		||||
    30: 'IO_INSTRUCTION',
 | 
			
		||||
    31: 'MSR_READ',
 | 
			
		||||
    32: 'MSR_WRITE',
 | 
			
		||||
    33: 'INVALID_STATE',
 | 
			
		||||
    36: 'MWAIT_INSTRUCTION',
 | 
			
		||||
    39: 'MONITOR_INSTRUCTION',
 | 
			
		||||
    40: 'PAUSE_INSTRUCTION',
 | 
			
		||||
    41: 'MCE_DURING_VMENTRY',
 | 
			
		||||
    43: 'TPR_BELOW_THRESHOLD',
 | 
			
		||||
    44: 'APIC_ACCESS',
 | 
			
		||||
    48: 'EPT_VIOLATION',
 | 
			
		||||
    49: 'EPT_MISCONFIG',
 | 
			
		||||
    54: 'WBINVD',
 | 
			
		||||
    55: 'XSETBV',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
svm_exit_reasons = {
 | 
			
		||||
    0x000: 'READ_CR0',
 | 
			
		||||
    0x003: 'READ_CR3',
 | 
			
		||||
    0x004: 'READ_CR4',
 | 
			
		||||
    0x008: 'READ_CR8',
 | 
			
		||||
    0x010: 'WRITE_CR0',
 | 
			
		||||
    0x013: 'WRITE_CR3',
 | 
			
		||||
    0x014: 'WRITE_CR4',
 | 
			
		||||
    0x018: 'WRITE_CR8',
 | 
			
		||||
    0x020: 'READ_DR0',
 | 
			
		||||
    0x021: 'READ_DR1',
 | 
			
		||||
    0x022: 'READ_DR2',
 | 
			
		||||
    0x023: 'READ_DR3',
 | 
			
		||||
    0x024: 'READ_DR4',
 | 
			
		||||
    0x025: 'READ_DR5',
 | 
			
		||||
    0x026: 'READ_DR6',
 | 
			
		||||
    0x027: 'READ_DR7',
 | 
			
		||||
    0x030: 'WRITE_DR0',
 | 
			
		||||
    0x031: 'WRITE_DR1',
 | 
			
		||||
    0x032: 'WRITE_DR2',
 | 
			
		||||
    0x033: 'WRITE_DR3',
 | 
			
		||||
    0x034: 'WRITE_DR4',
 | 
			
		||||
    0x035: 'WRITE_DR5',
 | 
			
		||||
    0x036: 'WRITE_DR6',
 | 
			
		||||
    0x037: 'WRITE_DR7',
 | 
			
		||||
    0x040: 'EXCP_BASE',
 | 
			
		||||
    0x060: 'INTR',
 | 
			
		||||
    0x061: 'NMI',
 | 
			
		||||
    0x062: 'SMI',
 | 
			
		||||
    0x063: 'INIT',
 | 
			
		||||
    0x064: 'VINTR',
 | 
			
		||||
    0x065: 'CR0_SEL_WRITE',
 | 
			
		||||
    0x066: 'IDTR_READ',
 | 
			
		||||
    0x067: 'GDTR_READ',
 | 
			
		||||
    0x068: 'LDTR_READ',
 | 
			
		||||
    0x069: 'TR_READ',
 | 
			
		||||
    0x06a: 'IDTR_WRITE',
 | 
			
		||||
    0x06b: 'GDTR_WRITE',
 | 
			
		||||
    0x06c: 'LDTR_WRITE',
 | 
			
		||||
    0x06d: 'TR_WRITE',
 | 
			
		||||
    0x06e: 'RDTSC',
 | 
			
		||||
    0x06f: 'RDPMC',
 | 
			
		||||
    0x070: 'PUSHF',
 | 
			
		||||
    0x071: 'POPF',
 | 
			
		||||
    0x072: 'CPUID',
 | 
			
		||||
    0x073: 'RSM',
 | 
			
		||||
    0x074: 'IRET',
 | 
			
		||||
    0x075: 'SWINT',
 | 
			
		||||
    0x076: 'INVD',
 | 
			
		||||
    0x077: 'PAUSE',
 | 
			
		||||
    0x078: 'HLT',
 | 
			
		||||
    0x079: 'INVLPG',
 | 
			
		||||
    0x07a: 'INVLPGA',
 | 
			
		||||
    0x07b: 'IOIO',
 | 
			
		||||
    0x07c: 'MSR',
 | 
			
		||||
    0x07d: 'TASK_SWITCH',
 | 
			
		||||
    0x07e: 'FERR_FREEZE',
 | 
			
		||||
    0x07f: 'SHUTDOWN',
 | 
			
		||||
    0x080: 'VMRUN',
 | 
			
		||||
    0x081: 'VMMCALL',
 | 
			
		||||
    0x082: 'VMLOAD',
 | 
			
		||||
    0x083: 'VMSAVE',
 | 
			
		||||
    0x084: 'STGI',
 | 
			
		||||
    0x085: 'CLGI',
 | 
			
		||||
    0x086: 'SKINIT',
 | 
			
		||||
    0x087: 'RDTSCP',
 | 
			
		||||
    0x088: 'ICEBP',
 | 
			
		||||
    0x089: 'WBINVD',
 | 
			
		||||
    0x08a: 'MONITOR',
 | 
			
		||||
    0x08b: 'MWAIT',
 | 
			
		||||
    0x08c: 'MWAIT_COND',
 | 
			
		||||
    0x400: 'NPF',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
vendor_exit_reasons = {
 | 
			
		||||
    'vmx': vmx_exit_reasons,
 | 
			
		||||
    'svm': svm_exit_reasons,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
exit_reasons = None
 | 
			
		||||
 | 
			
		||||
for line in file('/proc/cpuinfo').readlines():
 | 
			
		||||
    if line.startswith('flags'):
 | 
			
		||||
        for flag in line.split():
 | 
			
		||||
            if flag in vendor_exit_reasons:
 | 
			
		||||
                exit_reasons = vendor_exit_reasons[flag]
 | 
			
		||||
 | 
			
		||||
filters = {
 | 
			
		||||
    'kvm_exit': ('exit_reason', exit_reasons)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
def invert(d):
 | 
			
		||||
    return dict((x[1], x[0]) for x in d.iteritems())
 | 
			
		||||
 | 
			
		||||
for f in filters:
 | 
			
		||||
    filters[f] = (filters[f][0], invert(filters[f][1]))
 | 
			
		||||
 | 
			
		||||
import ctypes, struct, array
 | 
			
		||||
 | 
			
		||||
libc = ctypes.CDLL('libc.so.6')
 | 
			
		||||
syscall = libc.syscall
 | 
			
		||||
class perf_event_attr(ctypes.Structure):
 | 
			
		||||
    _fields_ = [('type', ctypes.c_uint32),
 | 
			
		||||
                ('size', ctypes.c_uint32),
 | 
			
		||||
                ('config', ctypes.c_uint64),
 | 
			
		||||
                ('sample_freq', ctypes.c_uint64),
 | 
			
		||||
                ('sample_type', ctypes.c_uint64),
 | 
			
		||||
                ('read_format', ctypes.c_uint64),
 | 
			
		||||
                ('flags', ctypes.c_uint64),
 | 
			
		||||
                ('wakeup_events', ctypes.c_uint32),
 | 
			
		||||
                ('bp_type', ctypes.c_uint32),
 | 
			
		||||
                ('bp_addr', ctypes.c_uint64),
 | 
			
		||||
                ('bp_len', ctypes.c_uint64),
 | 
			
		||||
                ]
 | 
			
		||||
def _perf_event_open(attr, pid, cpu, group_fd, flags):
 | 
			
		||||
    return syscall(298, ctypes.pointer(attr), ctypes.c_int(pid),
 | 
			
		||||
                   ctypes.c_int(cpu), ctypes.c_int(group_fd),
 | 
			
		||||
                   ctypes.c_long(flags))
 | 
			
		||||
 | 
			
		||||
PERF_TYPE_HARDWARE			= 0
 | 
			
		||||
PERF_TYPE_SOFTWARE			= 1
 | 
			
		||||
PERF_TYPE_TRACEPOINT			= 2
 | 
			
		||||
PERF_TYPE_HW_CACHE			= 3
 | 
			
		||||
PERF_TYPE_RAW				= 4
 | 
			
		||||
PERF_TYPE_BREAKPOINT			= 5
 | 
			
		||||
 | 
			
		||||
PERF_SAMPLE_IP				= 1 << 0
 | 
			
		||||
PERF_SAMPLE_TID				= 1 << 1
 | 
			
		||||
PERF_SAMPLE_TIME			= 1 << 2
 | 
			
		||||
PERF_SAMPLE_ADDR			= 1 << 3
 | 
			
		||||
PERF_SAMPLE_READ			= 1 << 4
 | 
			
		||||
PERF_SAMPLE_CALLCHAIN			= 1 << 5
 | 
			
		||||
PERF_SAMPLE_ID				= 1 << 6
 | 
			
		||||
PERF_SAMPLE_CPU				= 1 << 7
 | 
			
		||||
PERF_SAMPLE_PERIOD			= 1 << 8
 | 
			
		||||
PERF_SAMPLE_STREAM_ID			= 1 << 9
 | 
			
		||||
PERF_SAMPLE_RAW				= 1 << 10
 | 
			
		||||
 | 
			
		||||
PERF_FORMAT_TOTAL_TIME_ENABLED		= 1 << 0
 | 
			
		||||
PERF_FORMAT_TOTAL_TIME_RUNNING		= 1 << 1
 | 
			
		||||
PERF_FORMAT_ID				= 1 << 2
 | 
			
		||||
PERF_FORMAT_GROUP			= 1 << 3
 | 
			
		||||
 | 
			
		||||
import re
 | 
			
		||||
 | 
			
		||||
sys_tracing = '/sys/kernel/debug/tracing'
 | 
			
		||||
 | 
			
		||||
class Group(object):
 | 
			
		||||
    def __init__(self, cpu):
 | 
			
		||||
        self.events = []
 | 
			
		||||
        self.group_leader = None
 | 
			
		||||
        self.cpu = cpu
 | 
			
		||||
    def add_event(self, name, event_set, tracepoint, filter = None):
 | 
			
		||||
        self.events.append(Event(group = self,
 | 
			
		||||
                                 name = name, event_set = event_set,
 | 
			
		||||
                                 tracepoint = tracepoint, filter = filter))
 | 
			
		||||
        if len(self.events) == 1:
 | 
			
		||||
            self.file = os.fdopen(self.events[0].fd)
 | 
			
		||||
    def read(self):
 | 
			
		||||
        bytes = 8 * (1 + len(self.events))
 | 
			
		||||
        fmt = 'xxxxxxxx' + 'q' * len(self.events)
 | 
			
		||||
        return dict(zip([event.name for event in self.events],
 | 
			
		||||
                        struct.unpack(fmt, self.file.read(bytes))))
 | 
			
		||||
 | 
			
		||||
class Event(object):
 | 
			
		||||
    def __init__(self, group, name, event_set, tracepoint, filter = None):
 | 
			
		||||
        self.name = name
 | 
			
		||||
        attr = perf_event_attr()
 | 
			
		||||
        attr.type = PERF_TYPE_TRACEPOINT
 | 
			
		||||
        attr.size = ctypes.sizeof(attr)
 | 
			
		||||
        id_path = os.path.join(sys_tracing, 'events', event_set,
 | 
			
		||||
                               tracepoint, 'id')
 | 
			
		||||
        id = int(file(id_path).read())
 | 
			
		||||
        attr.config = id
 | 
			
		||||
        attr.sample_type = (PERF_SAMPLE_RAW
 | 
			
		||||
                            | PERF_SAMPLE_TIME
 | 
			
		||||
                            | PERF_SAMPLE_CPU)
 | 
			
		||||
        attr.sample_period = 1
 | 
			
		||||
        attr.read_format = PERF_FORMAT_GROUP
 | 
			
		||||
        group_leader = -1
 | 
			
		||||
        if group.events:
 | 
			
		||||
            group_leader = group.events[0].fd
 | 
			
		||||
        fd = _perf_event_open(attr, -1, group.cpu, group_leader, 0)
 | 
			
		||||
        if fd == -1:
 | 
			
		||||
            raise Exception('perf_event_open failed')
 | 
			
		||||
        if filter:
 | 
			
		||||
            import fcntl
 | 
			
		||||
            fcntl.ioctl(fd, 0x40082406, filter)
 | 
			
		||||
        self.fd = fd
 | 
			
		||||
    def enable(self):
 | 
			
		||||
        import fcntl
 | 
			
		||||
        fcntl.ioctl(self.fd, 0x00002400, 0)
 | 
			
		||||
    def disable(self):
 | 
			
		||||
        import fcntl
 | 
			
		||||
        fcntl.ioctl(self.fd, 0x00002401, 0)
 | 
			
		||||
 | 
			
		||||
class TracepointProvider(object):
 | 
			
		||||
    def __init__(self):
 | 
			
		||||
        path = os.path.join(sys_tracing, 'events', 'kvm')
 | 
			
		||||
        fields = [f
 | 
			
		||||
                  for f in os.listdir(path)
 | 
			
		||||
                  if os.path.isdir(os.path.join(path, f))]
 | 
			
		||||
        extra = []
 | 
			
		||||
        for f in fields:
 | 
			
		||||
            if f in filters:
 | 
			
		||||
                subfield, values = filters[f]
 | 
			
		||||
                for name, number in values.iteritems():
 | 
			
		||||
                    extra.append(f + '(' + name + ')')
 | 
			
		||||
        fields += extra
 | 
			
		||||
        self._setup(fields)
 | 
			
		||||
        self.select(fields)
 | 
			
		||||
    def fields(self):
 | 
			
		||||
        return self._fields
 | 
			
		||||
    def _setup(self, _fields):
 | 
			
		||||
        self._fields = _fields
 | 
			
		||||
        cpure = r'cpu([0-9]+)'
 | 
			
		||||
        self.cpus = [int(re.match(cpure, x).group(1))
 | 
			
		||||
                     for x in os.listdir('/sys/devices/system/cpu')
 | 
			
		||||
                     if re.match(cpure, x)]
 | 
			
		||||
        import resource
 | 
			
		||||
        nfiles = len(self.cpus) * 1000
 | 
			
		||||
        resource.setrlimit(resource.RLIMIT_NOFILE, (nfiles, nfiles))
 | 
			
		||||
        events = []
 | 
			
		||||
        self.group_leaders = []
 | 
			
		||||
        for cpu in self.cpus:
 | 
			
		||||
            group = Group(cpu)
 | 
			
		||||
            for name in _fields:
 | 
			
		||||
                tracepoint = name
 | 
			
		||||
                filter = None
 | 
			
		||||
                m = re.match(r'(.*)\((.*)\)', name)
 | 
			
		||||
                if m:
 | 
			
		||||
                    tracepoint, sub = m.groups()
 | 
			
		||||
                    filter = '%s==%d\0' % (filters[tracepoint][0],
 | 
			
		||||
                                           filters[tracepoint][1][sub])
 | 
			
		||||
                event = group.add_event(name, event_set = 'kvm',
 | 
			
		||||
                                        tracepoint = tracepoint,
 | 
			
		||||
                                        filter = filter)
 | 
			
		||||
            self.group_leaders.append(group)
 | 
			
		||||
    def select(self, fields):
 | 
			
		||||
        for group in self.group_leaders:
 | 
			
		||||
            for event in group.events:
 | 
			
		||||
                if event.name in fields:
 | 
			
		||||
                    event.enable()
 | 
			
		||||
                else:
 | 
			
		||||
                    event.disable()
 | 
			
		||||
    def read(self):
 | 
			
		||||
        from collections import defaultdict
 | 
			
		||||
        ret = defaultdict(int)
 | 
			
		||||
        for group in self.group_leaders:
 | 
			
		||||
            for name, val in group.read().iteritems():
 | 
			
		||||
                ret[name] += val
 | 
			
		||||
        return ret
 | 
			
		||||
 | 
			
		||||
class Stats:
 | 
			
		||||
    def __init__(self, provider, fields = None):
 | 
			
		||||
        self.provider = provider
 | 
			
		||||
        self.fields_filter = fields
 | 
			
		||||
        self._update()
 | 
			
		||||
    def _update(self):
 | 
			
		||||
        def wanted(key):
 | 
			
		||||
            import re
 | 
			
		||||
            if not self.fields_filter:
 | 
			
		||||
                return True
 | 
			
		||||
            return re.match(self.fields_filter, key) is not None
 | 
			
		||||
        self.values = dict([(key, None)
 | 
			
		||||
                            for key in provider.fields()
 | 
			
		||||
                            if wanted(key)])
 | 
			
		||||
        self.provider.select(self.values.keys())
 | 
			
		||||
    def set_fields_filter(self, fields_filter):
 | 
			
		||||
        self.fields_filter = fields_filter
 | 
			
		||||
        self._update()
 | 
			
		||||
    def get(self):
 | 
			
		||||
        new = self.provider.read()
 | 
			
		||||
        for key in self.provider.fields():
 | 
			
		||||
            oldval = self.values.get(key, (0, 0))
 | 
			
		||||
            newval = new[key]
 | 
			
		||||
            newdelta = None
 | 
			
		||||
            if oldval is not None:
 | 
			
		||||
                newdelta = newval - oldval[0]
 | 
			
		||||
            self.values[key] = (newval, newdelta)
 | 
			
		||||
        return self.values
 | 
			
		||||
 | 
			
		||||
if not os.access('/sys/kernel/debug', os.F_OK):
 | 
			
		||||
    print 'Please enable CONFIG_DEBUG_FS in your kernel'
 | 
			
		||||
    sys.exit(1)
 | 
			
		||||
if not os.access('/sys/kernel/debug/kvm', os.F_OK):
 | 
			
		||||
    print "Please mount debugfs ('mount -t debugfs debugfs /sys/kernel/debug')"
 | 
			
		||||
    print "and ensure the kvm modules are loaded"
 | 
			
		||||
    sys.exit(1)
 | 
			
		||||
 | 
			
		||||
label_width = 40
 | 
			
		||||
number_width = 10
 | 
			
		||||
 | 
			
		||||
def tui(screen, stats):
 | 
			
		||||
    curses.use_default_colors()
 | 
			
		||||
    curses.noecho()
 | 
			
		||||
    drilldown = False
 | 
			
		||||
    fields_filter = stats.fields_filter
 | 
			
		||||
    def update_drilldown():
 | 
			
		||||
        if not fields_filter:
 | 
			
		||||
            if drilldown:
 | 
			
		||||
                stats.set_fields_filter(None)
 | 
			
		||||
            else:
 | 
			
		||||
                stats.set_fields_filter(r'^[^\(]*$')
 | 
			
		||||
    update_drilldown()
 | 
			
		||||
    def refresh(sleeptime):
 | 
			
		||||
        screen.erase()
 | 
			
		||||
        screen.addstr(0, 0, 'kvm statistics')
 | 
			
		||||
        row = 2
 | 
			
		||||
        s = stats.get()
 | 
			
		||||
        def sortkey(x):
 | 
			
		||||
            if s[x][1]:
 | 
			
		||||
                return (-s[x][1], -s[x][0])
 | 
			
		||||
            else:
 | 
			
		||||
                return (0, -s[x][0])
 | 
			
		||||
        for key in sorted(s.keys(), key = sortkey):
 | 
			
		||||
            if row >= screen.getmaxyx()[0]:
 | 
			
		||||
                break
 | 
			
		||||
            values = s[key]
 | 
			
		||||
            if not values[0] and not values[1]:
 | 
			
		||||
                break
 | 
			
		||||
            col = 1
 | 
			
		||||
            screen.addstr(row, col, key)
 | 
			
		||||
            col += label_width
 | 
			
		||||
            screen.addstr(row, col, '%10d' % (values[0],))
 | 
			
		||||
            col += number_width
 | 
			
		||||
            if values[1] is not None:
 | 
			
		||||
                screen.addstr(row, col, '%8d' % (values[1] / sleeptime,))
 | 
			
		||||
            row += 1
 | 
			
		||||
        screen.refresh()
 | 
			
		||||
 | 
			
		||||
    sleeptime = 0.25
 | 
			
		||||
    while True:
 | 
			
		||||
        refresh(sleeptime)
 | 
			
		||||
        curses.halfdelay(int(sleeptime * 10))
 | 
			
		||||
        sleeptime = 3
 | 
			
		||||
        try:
 | 
			
		||||
            c = screen.getkey()
 | 
			
		||||
            if c == 'x':
 | 
			
		||||
                drilldown = not drilldown
 | 
			
		||||
                update_drilldown()
 | 
			
		||||
            if c == 'q':
 | 
			
		||||
                break
 | 
			
		||||
        except KeyboardInterrupt:
 | 
			
		||||
            break
 | 
			
		||||
        except curses.error:
 | 
			
		||||
            continue
 | 
			
		||||
 | 
			
		||||
def batch(stats):
 | 
			
		||||
    s = stats.get()
 | 
			
		||||
    time.sleep(1)
 | 
			
		||||
    s = stats.get()
 | 
			
		||||
    for key in sorted(s.keys()):
 | 
			
		||||
        values = s[key]
 | 
			
		||||
        print '%-22s%10d%10d' % (key, values[0], values[1])
 | 
			
		||||
 | 
			
		||||
def log(stats):
 | 
			
		||||
    keys = sorted(stats.get().iterkeys())
 | 
			
		||||
    def banner():
 | 
			
		||||
        for k in keys:
 | 
			
		||||
            print '%10s' % k[0:9],
 | 
			
		||||
        print
 | 
			
		||||
    def statline():
 | 
			
		||||
        s = stats.get()
 | 
			
		||||
        for k in keys:
 | 
			
		||||
            print ' %9d' % s[k][1],
 | 
			
		||||
        print
 | 
			
		||||
    line = 0
 | 
			
		||||
    banner_repeat = 20
 | 
			
		||||
    while True:
 | 
			
		||||
        time.sleep(1)
 | 
			
		||||
        if line % banner_repeat == 0:
 | 
			
		||||
            banner()
 | 
			
		||||
        statline()
 | 
			
		||||
        line += 1
 | 
			
		||||
 | 
			
		||||
options = optparse.OptionParser()
 | 
			
		||||
options.add_option('-1', '--once', '--batch',
 | 
			
		||||
                   action = 'store_true',
 | 
			
		||||
                   default = False,
 | 
			
		||||
                   dest = 'once',
 | 
			
		||||
                   help = 'run in batch mode for one second',
 | 
			
		||||
                   )
 | 
			
		||||
options.add_option('-l', '--log',
 | 
			
		||||
                   action = 'store_true',
 | 
			
		||||
                   default = False,
 | 
			
		||||
                   dest = 'log',
 | 
			
		||||
                   help = 'run in logging mode (like vmstat)',
 | 
			
		||||
                   )
 | 
			
		||||
options.add_option('-f', '--fields',
 | 
			
		||||
                   action = 'store',
 | 
			
		||||
                   default = None,
 | 
			
		||||
                   dest = 'fields',
 | 
			
		||||
                   help = 'fields to display (regex)',
 | 
			
		||||
                   )
 | 
			
		||||
(options, args) = options.parse_args(sys.argv)
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    provider = TracepointProvider()
 | 
			
		||||
except:
 | 
			
		||||
    provider = DebugfsProvider()
 | 
			
		||||
 | 
			
		||||
stats = Stats(provider, fields = options.fields)
 | 
			
		||||
 | 
			
		||||
if options.log:
 | 
			
		||||
    log(stats)
 | 
			
		||||
elif not options.once:
 | 
			
		||||
    import curses.wrapper
 | 
			
		||||
    curses.wrapper(tui, stats)
 | 
			
		||||
else:
 | 
			
		||||
    batch(stats)
 | 
			
		||||
							
								
								
									
										19
									
								
								kvm/libfdt/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								kvm/libfdt/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
include ../config.mak
 | 
			
		||||
include ../user/config.mak
 | 
			
		||||
 | 
			
		||||
LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
 | 
			
		||||
LIBFDT_INCLUDES = fdt.h libfdt.h
 | 
			
		||||
LIBFDT_EXTRA = libfdt_internal.h
 | 
			
		||||
LIBFDT_LIB = libfdt.a
 | 
			
		||||
 | 
			
		||||
LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
 | 
			
		||||
 | 
			
		||||
CFLAGS += -I .
 | 
			
		||||
 | 
			
		||||
$(LIBFDT_LIB): $(LIBFDT_OBJS)
 | 
			
		||||
	$(AR) rcs $@ $^
 | 
			
		||||
 | 
			
		||||
all: $(LIBFDT_LIB)
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	rm -rf *.o *.a
 | 
			
		||||
							
								
								
									
										3
									
								
								kvm/libfdt/README
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								kvm/libfdt/README
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
libfdt was grabbed from dtc source. This is the upstream source for libfdt.
 | 
			
		||||
It can be found here:
 | 
			
		||||
http://www.jdl.com/software/
 | 
			
		||||
							
								
								
									
										194
									
								
								kvm/libfdt/fdt.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								kvm/libfdt/fdt.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,194 @@
 | 
			
		||||
/*
 | 
			
		||||
 * libfdt - Flat Device Tree manipulation
 | 
			
		||||
 * Copyright (C) 2006 David Gibson, IBM Corporation.
 | 
			
		||||
 *
 | 
			
		||||
 * libfdt is dual licensed: you can use it either under the terms of
 | 
			
		||||
 * the GPL, or the BSD license, at your option.
 | 
			
		||||
 *
 | 
			
		||||
 *  a) This library is free software; you can redistribute it and/or
 | 
			
		||||
 *     modify it under the terms of the GNU General Public License as
 | 
			
		||||
 *     published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 *     License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 *     This library is distributed in the hope that it will be useful,
 | 
			
		||||
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *     GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *     You should have received a copy of the GNU General Public
 | 
			
		||||
 *     License along with this library; if not, write to the Free
 | 
			
		||||
 *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
 | 
			
		||||
 *     MA 02110-1301 USA
 | 
			
		||||
 *
 | 
			
		||||
 * Alternatively,
 | 
			
		||||
 *
 | 
			
		||||
 *  b) Redistribution and use in source and binary forms, with or
 | 
			
		||||
 *     without modification, are permitted provided that the following
 | 
			
		||||
 *     conditions are met:
 | 
			
		||||
 *
 | 
			
		||||
 *     1. Redistributions of source code must retain the above
 | 
			
		||||
 *        copyright notice, this list of conditions and the following
 | 
			
		||||
 *        disclaimer.
 | 
			
		||||
 *     2. Redistributions in binary form must reproduce the above
 | 
			
		||||
 *        copyright notice, this list of conditions and the following
 | 
			
		||||
 *        disclaimer in the documentation and/or other materials
 | 
			
		||||
 *        provided with the distribution.
 | 
			
		||||
 *
 | 
			
		||||
 *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 | 
			
		||||
 *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 | 
			
		||||
 *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
			
		||||
 *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
 *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 | 
			
		||||
 *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
 *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 | 
			
		||||
 *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
 *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
			
		||||
 *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 | 
			
		||||
 *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 | 
			
		||||
 *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
#include "libfdt_env.h"
 | 
			
		||||
 | 
			
		||||
#include <fdt.h>
 | 
			
		||||
#include <libfdt.h>
 | 
			
		||||
 | 
			
		||||
#include "libfdt_internal.h"
 | 
			
		||||
 | 
			
		||||
int fdt_check_header(const void *fdt)
 | 
			
		||||
{
 | 
			
		||||
	if (fdt_magic(fdt) == FDT_MAGIC) {
 | 
			
		||||
		/* Complete tree */
 | 
			
		||||
		if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
 | 
			
		||||
			return -FDT_ERR_BADVERSION;
 | 
			
		||||
		if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
 | 
			
		||||
			return -FDT_ERR_BADVERSION;
 | 
			
		||||
	} else if (fdt_magic(fdt) == SW_MAGIC) {
 | 
			
		||||
		/* Unfinished sequential-write blob */
 | 
			
		||||
		if (fdt_size_dt_struct(fdt) == 0)
 | 
			
		||||
			return -FDT_ERR_BADSTATE;
 | 
			
		||||
	} else {
 | 
			
		||||
		return -FDT_ERR_BADMAGIC;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const void *fdt_offset_ptr(const void *fdt, int offset, int len)
 | 
			
		||||
{
 | 
			
		||||
	const void *p;
 | 
			
		||||
 | 
			
		||||
	if (fdt_version(fdt) >= 0x11)
 | 
			
		||||
		if (((offset + len) < offset)
 | 
			
		||||
		    || ((offset + len) > fdt_size_dt_struct(fdt)))
 | 
			
		||||
			return NULL;
 | 
			
		||||
 | 
			
		||||
	p = _fdt_offset_ptr(fdt, offset);
 | 
			
		||||
 | 
			
		||||
	if (p + len < p)
 | 
			
		||||
		return NULL;
 | 
			
		||||
	return p;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset)
 | 
			
		||||
{
 | 
			
		||||
	const uint32_t *tagp, *lenp;
 | 
			
		||||
	uint32_t tag;
 | 
			
		||||
	const char *p;
 | 
			
		||||
 | 
			
		||||
	if (offset % FDT_TAGSIZE)
 | 
			
		||||
		return -1;
 | 
			
		||||
 | 
			
		||||
	tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
 | 
			
		||||
	if (! tagp)
 | 
			
		||||
		return FDT_END; /* premature end */
 | 
			
		||||
	tag = fdt32_to_cpu(*tagp);
 | 
			
		||||
	offset += FDT_TAGSIZE;
 | 
			
		||||
 | 
			
		||||
	switch (tag) {
 | 
			
		||||
	case FDT_BEGIN_NODE:
 | 
			
		||||
		/* skip name */
 | 
			
		||||
		do {
 | 
			
		||||
			p = fdt_offset_ptr(fdt, offset++, 1);
 | 
			
		||||
		} while (p && (*p != '\0'));
 | 
			
		||||
		if (! p)
 | 
			
		||||
			return FDT_END;
 | 
			
		||||
		break;
 | 
			
		||||
	case FDT_PROP:
 | 
			
		||||
		lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
 | 
			
		||||
		if (! lenp)
 | 
			
		||||
			return FDT_END;
 | 
			
		||||
		/* skip name offset, length and value */
 | 
			
		||||
		offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (nextoffset)
 | 
			
		||||
		*nextoffset = ALIGN(offset, FDT_TAGSIZE);
 | 
			
		||||
 | 
			
		||||
	return tag;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_next_node(const void *fdt, int offset, int *depth)
 | 
			
		||||
{
 | 
			
		||||
	int nextoffset = 0;
 | 
			
		||||
	uint32_t tag;
 | 
			
		||||
 | 
			
		||||
	if (offset >= 0) {
 | 
			
		||||
		tag = fdt_next_tag(fdt, offset, &nextoffset);
 | 
			
		||||
		if (tag != FDT_BEGIN_NODE)
 | 
			
		||||
			return -FDT_ERR_BADOFFSET;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		offset = nextoffset;
 | 
			
		||||
		tag = fdt_next_tag(fdt, offset, &nextoffset);
 | 
			
		||||
 | 
			
		||||
		switch (tag) {
 | 
			
		||||
		case FDT_PROP:
 | 
			
		||||
		case FDT_NOP:
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case FDT_BEGIN_NODE:
 | 
			
		||||
			if (depth)
 | 
			
		||||
				(*depth)++;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case FDT_END_NODE:
 | 
			
		||||
			if (depth)
 | 
			
		||||
				(*depth)--;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case FDT_END:
 | 
			
		||||
			return -FDT_ERR_NOTFOUND;
 | 
			
		||||
 | 
			
		||||
		default:
 | 
			
		||||
			return -FDT_ERR_BADSTRUCTURE;
 | 
			
		||||
		}
 | 
			
		||||
	} while (tag != FDT_BEGIN_NODE);
 | 
			
		||||
 | 
			
		||||
	return offset;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
 | 
			
		||||
{
 | 
			
		||||
	int len = strlen(s) + 1;
 | 
			
		||||
	const char *last = strtab + tabsize - len;
 | 
			
		||||
	const char *p;
 | 
			
		||||
 | 
			
		||||
	for (p = strtab; p <= last; p++)
 | 
			
		||||
		if (memeq(p, s, len))
 | 
			
		||||
			return p;
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_move(const void *fdt, void *buf, int bufsize)
 | 
			
		||||
{
 | 
			
		||||
	CHECK_HEADER(fdt);
 | 
			
		||||
 | 
			
		||||
	if (fdt_totalsize(fdt) > bufsize)
 | 
			
		||||
		return -FDT_ERR_NOSPACE;
 | 
			
		||||
 | 
			
		||||
	memmove(buf, fdt, fdt_totalsize(fdt));
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										60
									
								
								kvm/libfdt/fdt.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								kvm/libfdt/fdt.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,60 @@
 | 
			
		||||
#ifndef _FDT_H
 | 
			
		||||
#define _FDT_H
 | 
			
		||||
 | 
			
		||||
#ifndef __ASSEMBLY__
 | 
			
		||||
 | 
			
		||||
struct fdt_header {
 | 
			
		||||
	uint32_t magic;			 /* magic word FDT_MAGIC */
 | 
			
		||||
	uint32_t totalsize;		 /* total size of DT block */
 | 
			
		||||
	uint32_t off_dt_struct;		 /* offset to structure */
 | 
			
		||||
	uint32_t off_dt_strings;	 /* offset to strings */
 | 
			
		||||
	uint32_t off_mem_rsvmap;	 /* offset to memory reserve map */
 | 
			
		||||
	uint32_t version;		 /* format version */
 | 
			
		||||
	uint32_t last_comp_version;	 /* last compatible version */
 | 
			
		||||
 | 
			
		||||
	/* version 2 fields below */
 | 
			
		||||
	uint32_t boot_cpuid_phys;	 /* Which physical CPU id we're
 | 
			
		||||
					    booting on */
 | 
			
		||||
	/* version 3 fields below */
 | 
			
		||||
	uint32_t size_dt_strings;	 /* size of the strings block */
 | 
			
		||||
 | 
			
		||||
	/* version 17 fields below */
 | 
			
		||||
	uint32_t size_dt_struct;	 /* size of the structure block */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct fdt_reserve_entry {
 | 
			
		||||
	uint64_t address;
 | 
			
		||||
	uint64_t size;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct fdt_node_header {
 | 
			
		||||
	uint32_t tag;
 | 
			
		||||
	char name[0];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct fdt_property {
 | 
			
		||||
	uint32_t tag;
 | 
			
		||||
	uint32_t len;
 | 
			
		||||
	uint32_t nameoff;
 | 
			
		||||
	char data[0];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif /* !__ASSEMBLY */
 | 
			
		||||
 | 
			
		||||
#define FDT_MAGIC	0xd00dfeed	/* 4: version, 4: total size */
 | 
			
		||||
#define FDT_TAGSIZE	sizeof(uint32_t)
 | 
			
		||||
 | 
			
		||||
#define FDT_BEGIN_NODE	0x1		/* Start node: full name */
 | 
			
		||||
#define FDT_END_NODE	0x2		/* End node */
 | 
			
		||||
#define FDT_PROP	0x3		/* Property: name off,
 | 
			
		||||
					   size, content */
 | 
			
		||||
#define FDT_NOP		0x4		/* nop */
 | 
			
		||||
#define FDT_END		0x9
 | 
			
		||||
 | 
			
		||||
#define FDT_V1_SIZE	(7*sizeof(uint32_t))
 | 
			
		||||
#define FDT_V2_SIZE	(FDT_V1_SIZE + sizeof(uint32_t))
 | 
			
		||||
#define FDT_V3_SIZE	(FDT_V2_SIZE + sizeof(uint32_t))
 | 
			
		||||
#define FDT_V16_SIZE	FDT_V3_SIZE
 | 
			
		||||
#define FDT_V17_SIZE	(FDT_V16_SIZE + sizeof(uint32_t))
 | 
			
		||||
 | 
			
		||||
#endif /* _FDT_H */
 | 
			
		||||
							
								
								
									
										476
									
								
								kvm/libfdt/fdt_ro.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										476
									
								
								kvm/libfdt/fdt_ro.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,476 @@
 | 
			
		||||
/*
 | 
			
		||||
 * libfdt - Flat Device Tree manipulation
 | 
			
		||||
 * Copyright (C) 2006 David Gibson, IBM Corporation.
 | 
			
		||||
 *
 | 
			
		||||
 * libfdt is dual licensed: you can use it either under the terms of
 | 
			
		||||
 * the GPL, or the BSD license, at your option.
 | 
			
		||||
 *
 | 
			
		||||
 *  a) This library is free software; you can redistribute it and/or
 | 
			
		||||
 *     modify it under the terms of the GNU General Public License as
 | 
			
		||||
 *     published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 *     License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 *     This library is distributed in the hope that it will be useful,
 | 
			
		||||
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *     GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *     You should have received a copy of the GNU General Public
 | 
			
		||||
 *     License along with this library; if not, write to the Free
 | 
			
		||||
 *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
 | 
			
		||||
 *     MA 02110-1301 USA
 | 
			
		||||
 *
 | 
			
		||||
 * Alternatively,
 | 
			
		||||
 *
 | 
			
		||||
 *  b) Redistribution and use in source and binary forms, with or
 | 
			
		||||
 *     without modification, are permitted provided that the following
 | 
			
		||||
 *     conditions are met:
 | 
			
		||||
 *
 | 
			
		||||
 *     1. Redistributions of source code must retain the above
 | 
			
		||||
 *        copyright notice, this list of conditions and the following
 | 
			
		||||
 *        disclaimer.
 | 
			
		||||
 *     2. Redistributions in binary form must reproduce the above
 | 
			
		||||
 *        copyright notice, this list of conditions and the following
 | 
			
		||||
 *        disclaimer in the documentation and/or other materials
 | 
			
		||||
 *        provided with the distribution.
 | 
			
		||||
 *
 | 
			
		||||
 *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 | 
			
		||||
 *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 | 
			
		||||
 *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
			
		||||
 *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
 *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 | 
			
		||||
 *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
 *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 | 
			
		||||
 *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
 *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
			
		||||
 *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 | 
			
		||||
 *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 | 
			
		||||
 *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
#include "libfdt_env.h"
 | 
			
		||||
 | 
			
		||||
#include <fdt.h>
 | 
			
		||||
#include <libfdt.h>
 | 
			
		||||
 | 
			
		||||
#include "libfdt_internal.h"
 | 
			
		||||
 | 
			
		||||
static int nodename_eq(const void *fdt, int offset,
 | 
			
		||||
		       const char *s, int len)
 | 
			
		||||
{
 | 
			
		||||
	const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
 | 
			
		||||
 | 
			
		||||
	if (! p)
 | 
			
		||||
		/* short match */
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (memcmp(p, s, len) != 0)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (p[len] == '\0')
 | 
			
		||||
		return 1;
 | 
			
		||||
	else if (!memchr(s, '@', len) && (p[len] == '@'))
 | 
			
		||||
		return 1;
 | 
			
		||||
	else
 | 
			
		||||
		return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *fdt_string(const void *fdt, int stroffset)
 | 
			
		||||
{
 | 
			
		||||
	return (char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
 | 
			
		||||
{
 | 
			
		||||
	CHECK_HEADER(fdt);
 | 
			
		||||
	*address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address);
 | 
			
		||||
	*size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_num_mem_rsv(const void *fdt)
 | 
			
		||||
{
 | 
			
		||||
	int i = 0;
 | 
			
		||||
 | 
			
		||||
	while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0)
 | 
			
		||||
		i++;
 | 
			
		||||
	return i;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_subnode_offset_namelen(const void *fdt, int offset,
 | 
			
		||||
			       const char *name, int namelen)
 | 
			
		||||
{
 | 
			
		||||
	int depth;
 | 
			
		||||
 | 
			
		||||
	CHECK_HEADER(fdt);
 | 
			
		||||
 | 
			
		||||
	for (depth = 0;
 | 
			
		||||
	     offset >= 0;
 | 
			
		||||
	     offset = fdt_next_node(fdt, offset, &depth)) {
 | 
			
		||||
		if (depth < 0)
 | 
			
		||||
			return -FDT_ERR_NOTFOUND;
 | 
			
		||||
		else if ((depth == 1)
 | 
			
		||||
			 && nodename_eq(fdt, offset, name, namelen))
 | 
			
		||||
			return offset;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return offset; /* error */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_subnode_offset(const void *fdt, int parentoffset,
 | 
			
		||||
		       const char *name)
 | 
			
		||||
{
 | 
			
		||||
	return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_path_offset(const void *fdt, const char *path)
 | 
			
		||||
{
 | 
			
		||||
	const char *end = path + strlen(path);
 | 
			
		||||
	const char *p = path;
 | 
			
		||||
	int offset = 0;
 | 
			
		||||
 | 
			
		||||
	CHECK_HEADER(fdt);
 | 
			
		||||
 | 
			
		||||
	if (*path != '/')
 | 
			
		||||
		return -FDT_ERR_BADPATH;
 | 
			
		||||
 | 
			
		||||
	while (*p) {
 | 
			
		||||
		const char *q;
 | 
			
		||||
 | 
			
		||||
		while (*p == '/')
 | 
			
		||||
			p++;
 | 
			
		||||
		if (! *p)
 | 
			
		||||
			return offset;
 | 
			
		||||
		q = strchr(p, '/');
 | 
			
		||||
		if (! q)
 | 
			
		||||
			q = end;
 | 
			
		||||
 | 
			
		||||
		offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p);
 | 
			
		||||
		if (offset < 0)
 | 
			
		||||
			return offset;
 | 
			
		||||
 | 
			
		||||
		p = q;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return offset;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
 | 
			
		||||
{
 | 
			
		||||
	const struct fdt_node_header *nh;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	if ((err = fdt_check_header(fdt)) != 0)
 | 
			
		||||
		goto fail;
 | 
			
		||||
 | 
			
		||||
	err = -FDT_ERR_BADOFFSET;
 | 
			
		||||
	nh = fdt_offset_ptr(fdt, nodeoffset, sizeof(*nh));
 | 
			
		||||
	if (!nh || (fdt32_to_cpu(nh->tag) != FDT_BEGIN_NODE))
 | 
			
		||||
		goto fail;
 | 
			
		||||
 | 
			
		||||
	if (len)
 | 
			
		||||
		*len = strlen(nh->name);
 | 
			
		||||
 | 
			
		||||
	return nh->name;
 | 
			
		||||
 | 
			
		||||
 fail:
 | 
			
		||||
	if (len)
 | 
			
		||||
		*len = err;
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const struct fdt_property *fdt_get_property(const void *fdt,
 | 
			
		||||
					    int nodeoffset,
 | 
			
		||||
					    const char *name, int *lenp)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t tag;
 | 
			
		||||
	const struct fdt_property *prop;
 | 
			
		||||
	int namestroff;
 | 
			
		||||
	int offset, nextoffset;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	if ((err = fdt_check_header(fdt)) != 0)
 | 
			
		||||
		goto fail;
 | 
			
		||||
 | 
			
		||||
	err = -FDT_ERR_BADOFFSET;
 | 
			
		||||
	if (nodeoffset % FDT_TAGSIZE)
 | 
			
		||||
		goto fail;
 | 
			
		||||
 | 
			
		||||
	tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
 | 
			
		||||
	if (tag != FDT_BEGIN_NODE)
 | 
			
		||||
		goto fail;
 | 
			
		||||
 | 
			
		||||
	do {
 | 
			
		||||
		offset = nextoffset;
 | 
			
		||||
 | 
			
		||||
		tag = fdt_next_tag(fdt, offset, &nextoffset);
 | 
			
		||||
		switch (tag) {
 | 
			
		||||
		case FDT_END:
 | 
			
		||||
			err = -FDT_ERR_TRUNCATED;
 | 
			
		||||
			goto fail;
 | 
			
		||||
 | 
			
		||||
		case FDT_BEGIN_NODE:
 | 
			
		||||
		case FDT_END_NODE:
 | 
			
		||||
		case FDT_NOP:
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case FDT_PROP:
 | 
			
		||||
			err = -FDT_ERR_BADSTRUCTURE;
 | 
			
		||||
			prop = fdt_offset_ptr(fdt, offset, sizeof(*prop));
 | 
			
		||||
			if (! prop)
 | 
			
		||||
				goto fail;
 | 
			
		||||
			namestroff = fdt32_to_cpu(prop->nameoff);
 | 
			
		||||
			if (streq(fdt_string(fdt, namestroff), name)) {
 | 
			
		||||
				/* Found it! */
 | 
			
		||||
				int len = fdt32_to_cpu(prop->len);
 | 
			
		||||
				prop = fdt_offset_ptr(fdt, offset,
 | 
			
		||||
						      sizeof(*prop)+len);
 | 
			
		||||
				if (! prop)
 | 
			
		||||
					goto fail;
 | 
			
		||||
 | 
			
		||||
				if (lenp)
 | 
			
		||||
					*lenp = len;
 | 
			
		||||
 | 
			
		||||
				return prop;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		default:
 | 
			
		||||
			err = -FDT_ERR_BADSTRUCTURE;
 | 
			
		||||
			goto fail;
 | 
			
		||||
		}
 | 
			
		||||
	} while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE));
 | 
			
		||||
 | 
			
		||||
	err = -FDT_ERR_NOTFOUND;
 | 
			
		||||
 fail:
 | 
			
		||||
	if (lenp)
 | 
			
		||||
		*lenp = err;
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const void *fdt_getprop(const void *fdt, int nodeoffset,
 | 
			
		||||
		  const char *name, int *lenp)
 | 
			
		||||
{
 | 
			
		||||
	const struct fdt_property *prop;
 | 
			
		||||
 | 
			
		||||
	prop = fdt_get_property(fdt, nodeoffset, name, lenp);
 | 
			
		||||
	if (! prop)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	return prop->data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
 | 
			
		||||
{
 | 
			
		||||
	const uint32_t *php;
 | 
			
		||||
	int len;
 | 
			
		||||
 | 
			
		||||
	php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
 | 
			
		||||
	if (!php || (len != sizeof(*php)))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	return fdt32_to_cpu(*php);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
 | 
			
		||||
{
 | 
			
		||||
	int pdepth = 0, p = 0;
 | 
			
		||||
	int offset, depth, namelen;
 | 
			
		||||
	const char *name;
 | 
			
		||||
 | 
			
		||||
	CHECK_HEADER(fdt);
 | 
			
		||||
 | 
			
		||||
	if (buflen < 2)
 | 
			
		||||
		return -FDT_ERR_NOSPACE;
 | 
			
		||||
 | 
			
		||||
	for (offset = 0, depth = 0;
 | 
			
		||||
	     (offset >= 0) && (offset <= nodeoffset);
 | 
			
		||||
	     offset = fdt_next_node(fdt, offset, &depth)) {
 | 
			
		||||
		if (pdepth < depth)
 | 
			
		||||
			continue; /* overflowed buffer */
 | 
			
		||||
 | 
			
		||||
		while (pdepth > depth) {
 | 
			
		||||
			do {
 | 
			
		||||
				p--;
 | 
			
		||||
			} while (buf[p-1] != '/');
 | 
			
		||||
			pdepth--;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		name = fdt_get_name(fdt, offset, &namelen);
 | 
			
		||||
		if (!name)
 | 
			
		||||
			return namelen;
 | 
			
		||||
		if ((p + namelen + 1) <= buflen) {
 | 
			
		||||
			memcpy(buf + p, name, namelen);
 | 
			
		||||
			p += namelen;
 | 
			
		||||
			buf[p++] = '/';
 | 
			
		||||
			pdepth++;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (offset == nodeoffset) {
 | 
			
		||||
			if (pdepth < (depth + 1))
 | 
			
		||||
				return -FDT_ERR_NOSPACE;
 | 
			
		||||
 | 
			
		||||
			if (p > 1) /* special case so that root path is "/", not "" */
 | 
			
		||||
				p--;
 | 
			
		||||
			buf[p] = '\0';
 | 
			
		||||
			return p;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
 | 
			
		||||
		return -FDT_ERR_BADOFFSET;
 | 
			
		||||
	else if (offset == -FDT_ERR_BADOFFSET)
 | 
			
		||||
		return -FDT_ERR_BADSTRUCTURE;
 | 
			
		||||
 | 
			
		||||
	return offset; /* error from fdt_next_node() */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
 | 
			
		||||
				 int supernodedepth, int *nodedepth)
 | 
			
		||||
{
 | 
			
		||||
	int offset, depth;
 | 
			
		||||
	int supernodeoffset = -FDT_ERR_INTERNAL;
 | 
			
		||||
 | 
			
		||||
	CHECK_HEADER(fdt);
 | 
			
		||||
 | 
			
		||||
	if (supernodedepth < 0)
 | 
			
		||||
		return -FDT_ERR_NOTFOUND;
 | 
			
		||||
 | 
			
		||||
	for (offset = 0, depth = 0;
 | 
			
		||||
	     (offset >= 0) && (offset <= nodeoffset);
 | 
			
		||||
	     offset = fdt_next_node(fdt, offset, &depth)) {
 | 
			
		||||
		if (depth == supernodedepth)
 | 
			
		||||
			supernodeoffset = offset;
 | 
			
		||||
 | 
			
		||||
		if (offset == nodeoffset) {
 | 
			
		||||
			if (nodedepth)
 | 
			
		||||
				*nodedepth = depth;
 | 
			
		||||
 | 
			
		||||
			if (supernodedepth > depth)
 | 
			
		||||
				return -FDT_ERR_NOTFOUND;
 | 
			
		||||
			else
 | 
			
		||||
				return supernodeoffset;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
 | 
			
		||||
		return -FDT_ERR_BADOFFSET;
 | 
			
		||||
	else if (offset == -FDT_ERR_BADOFFSET)
 | 
			
		||||
		return -FDT_ERR_BADSTRUCTURE;
 | 
			
		||||
 | 
			
		||||
	return offset; /* error from fdt_next_node() */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_node_depth(const void *fdt, int nodeoffset)
 | 
			
		||||
{
 | 
			
		||||
	int nodedepth;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
 | 
			
		||||
	if (err)
 | 
			
		||||
		return (err < 0) ? err : -FDT_ERR_INTERNAL;
 | 
			
		||||
	return nodedepth;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_parent_offset(const void *fdt, int nodeoffset)
 | 
			
		||||
{
 | 
			
		||||
	int nodedepth = fdt_node_depth(fdt, nodeoffset);
 | 
			
		||||
 | 
			
		||||
	if (nodedepth < 0)
 | 
			
		||||
		return nodedepth;
 | 
			
		||||
	return fdt_supernode_atdepth_offset(fdt, nodeoffset,
 | 
			
		||||
					    nodedepth - 1, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
 | 
			
		||||
				  const char *propname,
 | 
			
		||||
				  const void *propval, int proplen)
 | 
			
		||||
{
 | 
			
		||||
	int offset;
 | 
			
		||||
	const void *val;
 | 
			
		||||
	int len;
 | 
			
		||||
 | 
			
		||||
	CHECK_HEADER(fdt);
 | 
			
		||||
 | 
			
		||||
	/* FIXME: The algorithm here is pretty horrible: we scan each
 | 
			
		||||
	 * property of a node in fdt_getprop(), then if that didn't
 | 
			
		||||
	 * find what we want, we scan over them again making our way
 | 
			
		||||
	 * to the next node.  Still it's the easiest to implement
 | 
			
		||||
	 * approach; performance can come later. */
 | 
			
		||||
	for (offset = fdt_next_node(fdt, startoffset, NULL);
 | 
			
		||||
	     offset >= 0;
 | 
			
		||||
	     offset = fdt_next_node(fdt, offset, NULL)) {
 | 
			
		||||
		val = fdt_getprop(fdt, offset, propname, &len);
 | 
			
		||||
		if (val && (len == proplen)
 | 
			
		||||
		    && (memcmp(val, propval, len) == 0))
 | 
			
		||||
			return offset;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return offset; /* error from fdt_next_node() */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
 | 
			
		||||
{
 | 
			
		||||
	if ((phandle == 0) || (phandle == -1))
 | 
			
		||||
		return -FDT_ERR_BADPHANDLE;
 | 
			
		||||
	phandle = cpu_to_fdt32(phandle);
 | 
			
		||||
	return fdt_node_offset_by_prop_value(fdt, -1, "linux,phandle",
 | 
			
		||||
					     &phandle, sizeof(phandle));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int _stringlist_contains(const void *strlist, int listlen, const char *str)
 | 
			
		||||
{
 | 
			
		||||
	int len = strlen(str);
 | 
			
		||||
	const void *p;
 | 
			
		||||
 | 
			
		||||
	while (listlen >= len) {
 | 
			
		||||
		if (memcmp(str, strlist, len+1) == 0)
 | 
			
		||||
			return 1;
 | 
			
		||||
		p = memchr(strlist, '\0', listlen);
 | 
			
		||||
		if (!p)
 | 
			
		||||
			return 0; /* malformed strlist.. */
 | 
			
		||||
		listlen -= (p-strlist) + 1;
 | 
			
		||||
		strlist = p + 1;
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_node_check_compatible(const void *fdt, int nodeoffset,
 | 
			
		||||
			      const char *compatible)
 | 
			
		||||
{
 | 
			
		||||
	const void *prop;
 | 
			
		||||
	int len;
 | 
			
		||||
 | 
			
		||||
	prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
 | 
			
		||||
	if (!prop)
 | 
			
		||||
		return len;
 | 
			
		||||
	if (_stringlist_contains(prop, len, compatible))
 | 
			
		||||
		return 0;
 | 
			
		||||
	else
 | 
			
		||||
		return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
 | 
			
		||||
				  const char *compatible)
 | 
			
		||||
{
 | 
			
		||||
	int offset, err;
 | 
			
		||||
 | 
			
		||||
	CHECK_HEADER(fdt);
 | 
			
		||||
 | 
			
		||||
	/* FIXME: The algorithm here is pretty horrible: we scan each
 | 
			
		||||
	 * property of a node in fdt_node_check_compatible(), then if
 | 
			
		||||
	 * that didn't find what we want, we scan over them again
 | 
			
		||||
	 * making our way to the next node.  Still it's the easiest to
 | 
			
		||||
	 * implement approach; performance can come later. */
 | 
			
		||||
	for (offset = fdt_next_node(fdt, startoffset, NULL);
 | 
			
		||||
	     offset >= 0;
 | 
			
		||||
	     offset = fdt_next_node(fdt, offset, NULL)) {
 | 
			
		||||
		err = fdt_node_check_compatible(fdt, offset, compatible);
 | 
			
		||||
		if ((err < 0) && (err != -FDT_ERR_NOTFOUND))
 | 
			
		||||
			return err;
 | 
			
		||||
		else if (err == 0)
 | 
			
		||||
			return offset;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return offset; /* error from fdt_next_node() */
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										467
									
								
								kvm/libfdt/fdt_rw.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										467
									
								
								kvm/libfdt/fdt_rw.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,467 @@
 | 
			
		||||
/*
 | 
			
		||||
 * libfdt - Flat Device Tree manipulation
 | 
			
		||||
 * Copyright (C) 2006 David Gibson, IBM Corporation.
 | 
			
		||||
 *
 | 
			
		||||
 * libfdt is dual licensed: you can use it either under the terms of
 | 
			
		||||
 * the GPL, or the BSD license, at your option.
 | 
			
		||||
 *
 | 
			
		||||
 *  a) This library is free software; you can redistribute it and/or
 | 
			
		||||
 *     modify it under the terms of the GNU General Public License as
 | 
			
		||||
 *     published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 *     License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 *     This library is distributed in the hope that it will be useful,
 | 
			
		||||
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *     GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *     You should have received a copy of the GNU General Public
 | 
			
		||||
 *     License along with this library; if not, write to the Free
 | 
			
		||||
 *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
 | 
			
		||||
 *     MA 02110-1301 USA
 | 
			
		||||
 *
 | 
			
		||||
 * Alternatively,
 | 
			
		||||
 *
 | 
			
		||||
 *  b) Redistribution and use in source and binary forms, with or
 | 
			
		||||
 *     without modification, are permitted provided that the following
 | 
			
		||||
 *     conditions are met:
 | 
			
		||||
 *
 | 
			
		||||
 *     1. Redistributions of source code must retain the above
 | 
			
		||||
 *        copyright notice, this list of conditions and the following
 | 
			
		||||
 *        disclaimer.
 | 
			
		||||
 *     2. Redistributions in binary form must reproduce the above
 | 
			
		||||
 *        copyright notice, this list of conditions and the following
 | 
			
		||||
 *        disclaimer in the documentation and/or other materials
 | 
			
		||||
 *        provided with the distribution.
 | 
			
		||||
 *
 | 
			
		||||
 *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 | 
			
		||||
 *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 | 
			
		||||
 *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
			
		||||
 *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
 *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 | 
			
		||||
 *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
 *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 | 
			
		||||
 *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
 *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
			
		||||
 *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 | 
			
		||||
 *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 | 
			
		||||
 *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
#include "libfdt_env.h"
 | 
			
		||||
 | 
			
		||||
#include <fdt.h>
 | 
			
		||||
#include <libfdt.h>
 | 
			
		||||
 | 
			
		||||
#include "libfdt_internal.h"
 | 
			
		||||
 | 
			
		||||
static int _blocks_misordered(const void *fdt,
 | 
			
		||||
			      int mem_rsv_size, int struct_size)
 | 
			
		||||
{
 | 
			
		||||
	return (fdt_off_mem_rsvmap(fdt) < ALIGN(sizeof(struct fdt_header), 8))
 | 
			
		||||
		|| (fdt_off_dt_struct(fdt) <
 | 
			
		||||
		    (fdt_off_mem_rsvmap(fdt) + mem_rsv_size))
 | 
			
		||||
		|| (fdt_off_dt_strings(fdt) <
 | 
			
		||||
		    (fdt_off_dt_struct(fdt) + struct_size))
 | 
			
		||||
		|| (fdt_totalsize(fdt) <
 | 
			
		||||
		    (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int rw_check_header(void *fdt)
 | 
			
		||||
{
 | 
			
		||||
	CHECK_HEADER(fdt);
 | 
			
		||||
 | 
			
		||||
	if (fdt_version(fdt) < 17)
 | 
			
		||||
		return -FDT_ERR_BADVERSION;
 | 
			
		||||
	if (_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry),
 | 
			
		||||
			       fdt_size_dt_struct(fdt)))
 | 
			
		||||
		return -FDT_ERR_BADLAYOUT;
 | 
			
		||||
	if (fdt_version(fdt) > 17)
 | 
			
		||||
		fdt_set_version(fdt, 17);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define RW_CHECK_HEADER(fdt) \
 | 
			
		||||
	{ \
 | 
			
		||||
		int err; \
 | 
			
		||||
		if ((err = rw_check_header(fdt)) != 0) \
 | 
			
		||||
			return err; \
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
static inline int _blob_data_size(void *fdt)
 | 
			
		||||
{
 | 
			
		||||
	return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _blob_splice(void *fdt, void *p, int oldlen, int newlen)
 | 
			
		||||
{
 | 
			
		||||
	void *end = fdt + _blob_data_size(fdt);
 | 
			
		||||
 | 
			
		||||
	if (((p + oldlen) < p) || ((p + oldlen) > end))
 | 
			
		||||
		return -FDT_ERR_BADOFFSET;
 | 
			
		||||
	if ((end - oldlen + newlen) > (fdt + fdt_totalsize(fdt)))
 | 
			
		||||
		return -FDT_ERR_NOSPACE;
 | 
			
		||||
	memmove(p + newlen, p + oldlen, end - p - oldlen);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _blob_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
 | 
			
		||||
				int oldn, int newn)
 | 
			
		||||
{
 | 
			
		||||
	int delta = (newn - oldn) * sizeof(*p);
 | 
			
		||||
	int err;
 | 
			
		||||
	err = _blob_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
 | 
			
		||||
	if (err)
 | 
			
		||||
		return err;
 | 
			
		||||
	fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
 | 
			
		||||
	fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _blob_splice_struct(void *fdt, void *p,
 | 
			
		||||
			       int oldlen, int newlen)
 | 
			
		||||
{
 | 
			
		||||
	int delta = newlen - oldlen;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	if ((err = _blob_splice(fdt, p, oldlen, newlen)))
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
 | 
			
		||||
	fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _blob_splice_string(void *fdt, int newlen)
 | 
			
		||||
{
 | 
			
		||||
	void *p = fdt + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	if ((err = _blob_splice(fdt, p, 0, newlen)))
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _find_add_string(void *fdt, const char *s)
 | 
			
		||||
{
 | 
			
		||||
	char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
 | 
			
		||||
	const char *p;
 | 
			
		||||
	char *new;
 | 
			
		||||
	int len = strlen(s) + 1;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s);
 | 
			
		||||
	if (p)
 | 
			
		||||
		/* found it */
 | 
			
		||||
		return (p - strtab);
 | 
			
		||||
 | 
			
		||||
	new = strtab + fdt_size_dt_strings(fdt);
 | 
			
		||||
	err = _blob_splice_string(fdt, len);
 | 
			
		||||
	if (err)
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	memcpy(new, s, len);
 | 
			
		||||
	return (new - strtab);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
 | 
			
		||||
{
 | 
			
		||||
	struct fdt_reserve_entry *re;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	if ((err = rw_check_header(fdt)))
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt));
 | 
			
		||||
	err = _blob_splice_mem_rsv(fdt, re, 0, 1);
 | 
			
		||||
	if (err)
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	re->address = cpu_to_fdt64(address);
 | 
			
		||||
	re->size = cpu_to_fdt64(size);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_del_mem_rsv(void *fdt, int n)
 | 
			
		||||
{
 | 
			
		||||
	struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	if ((err = rw_check_header(fdt)))
 | 
			
		||||
		return err;
 | 
			
		||||
	if (n >= fdt_num_mem_rsv(fdt))
 | 
			
		||||
		return -FDT_ERR_NOTFOUND;
 | 
			
		||||
 | 
			
		||||
	err = _blob_splice_mem_rsv(fdt, re, 1, 0);
 | 
			
		||||
	if (err)
 | 
			
		||||
		return err;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _resize_property(void *fdt, int nodeoffset, const char *name, int len,
 | 
			
		||||
			    struct fdt_property **prop)
 | 
			
		||||
{
 | 
			
		||||
	int oldlen;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	*prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
 | 
			
		||||
	if (! (*prop))
 | 
			
		||||
		return oldlen;
 | 
			
		||||
 | 
			
		||||
	if ((err = _blob_splice_struct(fdt, (*prop)->data,
 | 
			
		||||
				       ALIGN(oldlen, FDT_TAGSIZE),
 | 
			
		||||
				       ALIGN(len, FDT_TAGSIZE))))
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	(*prop)->len = cpu_to_fdt32(len);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int _add_property(void *fdt, int nodeoffset, const char *name, int len,
 | 
			
		||||
			 struct fdt_property **prop)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t tag;
 | 
			
		||||
	int proplen;
 | 
			
		||||
	int nextoffset;
 | 
			
		||||
	int namestroff;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
 | 
			
		||||
	if (tag != FDT_BEGIN_NODE)
 | 
			
		||||
		return -FDT_ERR_BADOFFSET;
 | 
			
		||||
 | 
			
		||||
	namestroff = _find_add_string(fdt, name);
 | 
			
		||||
	if (namestroff < 0)
 | 
			
		||||
		return namestroff;
 | 
			
		||||
 | 
			
		||||
	*prop = _fdt_offset_ptr_w(fdt, nextoffset);
 | 
			
		||||
	proplen = sizeof(**prop) + ALIGN(len, FDT_TAGSIZE);
 | 
			
		||||
 | 
			
		||||
	err = _blob_splice_struct(fdt, *prop, 0, proplen);
 | 
			
		||||
	if (err)
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	(*prop)->tag = cpu_to_fdt32(FDT_PROP);
 | 
			
		||||
	(*prop)->nameoff = cpu_to_fdt32(namestroff);
 | 
			
		||||
	(*prop)->len = cpu_to_fdt32(len);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_set_name(void *fdt, int nodeoffset, const char *name)
 | 
			
		||||
{
 | 
			
		||||
	char *namep;
 | 
			
		||||
	int oldlen, newlen;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	if ((err = rw_check_header(fdt)))
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	namep = (char *)fdt_get_name(fdt, nodeoffset, &oldlen);
 | 
			
		||||
	if (!namep)
 | 
			
		||||
		return oldlen;
 | 
			
		||||
 | 
			
		||||
	newlen = strlen(name);
 | 
			
		||||
 | 
			
		||||
	err = _blob_splice_struct(fdt, namep, ALIGN(oldlen+1, FDT_TAGSIZE),
 | 
			
		||||
				  ALIGN(newlen+1, FDT_TAGSIZE));
 | 
			
		||||
	if (err)
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	memcpy(namep, name, newlen+1);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_setprop(void *fdt, int nodeoffset, const char *name,
 | 
			
		||||
		const void *val, int len)
 | 
			
		||||
{
 | 
			
		||||
	struct fdt_property *prop;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	if ((err = rw_check_header(fdt)))
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	err = _resize_property(fdt, nodeoffset, name, len, &prop);
 | 
			
		||||
	if (err == -FDT_ERR_NOTFOUND)
 | 
			
		||||
		err = _add_property(fdt, nodeoffset, name, len, &prop);
 | 
			
		||||
	if (err)
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	memcpy(prop->data, val, len);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_delprop(void *fdt, int nodeoffset, const char *name)
 | 
			
		||||
{
 | 
			
		||||
	struct fdt_property *prop;
 | 
			
		||||
	int len, proplen;
 | 
			
		||||
 | 
			
		||||
	RW_CHECK_HEADER(fdt);
 | 
			
		||||
 | 
			
		||||
	prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
 | 
			
		||||
	if (! prop)
 | 
			
		||||
		return len;
 | 
			
		||||
 | 
			
		||||
	proplen = sizeof(*prop) + ALIGN(len, FDT_TAGSIZE);
 | 
			
		||||
	return _blob_splice_struct(fdt, prop, proplen, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_add_subnode_namelen(void *fdt, int parentoffset,
 | 
			
		||||
			    const char *name, int namelen)
 | 
			
		||||
{
 | 
			
		||||
	struct fdt_node_header *nh;
 | 
			
		||||
	int offset, nextoffset;
 | 
			
		||||
	int nodelen;
 | 
			
		||||
	int err;
 | 
			
		||||
	uint32_t tag;
 | 
			
		||||
	uint32_t *endtag;
 | 
			
		||||
 | 
			
		||||
	RW_CHECK_HEADER(fdt);
 | 
			
		||||
 | 
			
		||||
	offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
 | 
			
		||||
	if (offset >= 0)
 | 
			
		||||
		return -FDT_ERR_EXISTS;
 | 
			
		||||
	else if (offset != -FDT_ERR_NOTFOUND)
 | 
			
		||||
		return offset;
 | 
			
		||||
 | 
			
		||||
	/* Try to place the new node after the parent's properties */
 | 
			
		||||
	fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */
 | 
			
		||||
	do {
 | 
			
		||||
		offset = nextoffset;
 | 
			
		||||
		tag = fdt_next_tag(fdt, offset, &nextoffset);
 | 
			
		||||
	} while ((tag == FDT_PROP) || (tag == FDT_NOP));
 | 
			
		||||
 | 
			
		||||
	nh = _fdt_offset_ptr_w(fdt, offset);
 | 
			
		||||
	nodelen = sizeof(*nh) + ALIGN(namelen+1, FDT_TAGSIZE) + FDT_TAGSIZE;
 | 
			
		||||
 | 
			
		||||
	err = _blob_splice_struct(fdt, nh, 0, nodelen);
 | 
			
		||||
	if (err)
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
 | 
			
		||||
	memset(nh->name, 0, ALIGN(namelen+1, FDT_TAGSIZE));
 | 
			
		||||
	memcpy(nh->name, name, namelen);
 | 
			
		||||
	endtag = (uint32_t *)((void *)nh + nodelen - FDT_TAGSIZE);
 | 
			
		||||
	*endtag = cpu_to_fdt32(FDT_END_NODE);
 | 
			
		||||
 | 
			
		||||
	return offset;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_add_subnode(void *fdt, int parentoffset, const char *name)
 | 
			
		||||
{
 | 
			
		||||
	return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_del_node(void *fdt, int nodeoffset)
 | 
			
		||||
{
 | 
			
		||||
	int endoffset;
 | 
			
		||||
 | 
			
		||||
	RW_CHECK_HEADER(fdt);
 | 
			
		||||
 | 
			
		||||
	endoffset = _fdt_node_end_offset(fdt, nodeoffset);
 | 
			
		||||
	if (endoffset < 0)
 | 
			
		||||
		return endoffset;
 | 
			
		||||
 | 
			
		||||
	return _blob_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset),
 | 
			
		||||
				   endoffset - nodeoffset, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _packblocks(const void *fdt, void *buf,
 | 
			
		||||
		       int mem_rsv_size, int struct_size)
 | 
			
		||||
{
 | 
			
		||||
	int mem_rsv_off, struct_off, strings_off;
 | 
			
		||||
 | 
			
		||||
	mem_rsv_off = ALIGN(sizeof(struct fdt_header), 8);
 | 
			
		||||
	struct_off = mem_rsv_off + mem_rsv_size;
 | 
			
		||||
	strings_off = struct_off + struct_size;
 | 
			
		||||
 | 
			
		||||
	memmove(buf + mem_rsv_off, fdt + fdt_off_mem_rsvmap(fdt), mem_rsv_size);
 | 
			
		||||
	fdt_set_off_mem_rsvmap(buf, mem_rsv_off);
 | 
			
		||||
 | 
			
		||||
	memmove(buf + struct_off, fdt + fdt_off_dt_struct(fdt), struct_size);
 | 
			
		||||
	fdt_set_off_dt_struct(buf, struct_off);
 | 
			
		||||
	fdt_set_size_dt_struct(buf, struct_size);
 | 
			
		||||
 | 
			
		||||
	memmove(buf + strings_off, fdt + fdt_off_dt_strings(fdt),
 | 
			
		||||
		fdt_size_dt_strings(fdt));
 | 
			
		||||
	fdt_set_off_dt_strings(buf, strings_off);
 | 
			
		||||
	fdt_set_size_dt_strings(buf, fdt_size_dt_strings(fdt));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_open_into(const void *fdt, void *buf, int bufsize)
 | 
			
		||||
{
 | 
			
		||||
	int err;
 | 
			
		||||
	int mem_rsv_size, struct_size;
 | 
			
		||||
	int newsize;
 | 
			
		||||
	void *tmp;
 | 
			
		||||
 | 
			
		||||
	CHECK_HEADER(fdt);
 | 
			
		||||
 | 
			
		||||
	mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
 | 
			
		||||
		* sizeof(struct fdt_reserve_entry);
 | 
			
		||||
 | 
			
		||||
	if (fdt_version(fdt) >= 17) {
 | 
			
		||||
		struct_size = fdt_size_dt_struct(fdt);
 | 
			
		||||
	} else {
 | 
			
		||||
		struct_size = 0;
 | 
			
		||||
		while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
 | 
			
		||||
			;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
 | 
			
		||||
		/* no further work necessary */
 | 
			
		||||
		err = fdt_move(fdt, buf, bufsize);
 | 
			
		||||
		if (err)
 | 
			
		||||
			return err;
 | 
			
		||||
		fdt_set_version(buf, 17);
 | 
			
		||||
		fdt_set_size_dt_struct(buf, struct_size);
 | 
			
		||||
		fdt_set_totalsize(buf, bufsize);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Need to reorder */
 | 
			
		||||
	newsize = ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size
 | 
			
		||||
		+ struct_size + fdt_size_dt_strings(fdt);
 | 
			
		||||
 | 
			
		||||
	if (bufsize < newsize)
 | 
			
		||||
		return -FDT_ERR_NOSPACE;
 | 
			
		||||
 | 
			
		||||
	if (((buf + newsize) <= fdt)
 | 
			
		||||
	    || (buf >= (fdt + fdt_totalsize(fdt)))) {
 | 
			
		||||
		tmp = buf;
 | 
			
		||||
	} else {
 | 
			
		||||
		tmp = (void *)fdt + fdt_totalsize(fdt);
 | 
			
		||||
		if ((tmp + newsize) > (buf + bufsize))
 | 
			
		||||
			return -FDT_ERR_NOSPACE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_packblocks(fdt, tmp, mem_rsv_size, struct_size);
 | 
			
		||||
	memmove(buf, tmp, newsize);
 | 
			
		||||
 | 
			
		||||
	fdt_set_magic(buf, FDT_MAGIC);
 | 
			
		||||
	fdt_set_totalsize(buf, bufsize);
 | 
			
		||||
	fdt_set_version(buf, 17);
 | 
			
		||||
	fdt_set_last_comp_version(buf, 16);
 | 
			
		||||
	fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt));
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_pack(void *fdt)
 | 
			
		||||
{
 | 
			
		||||
	int mem_rsv_size;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	err = rw_check_header(fdt);
 | 
			
		||||
	if (err)
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
 | 
			
		||||
		* sizeof(struct fdt_reserve_entry);
 | 
			
		||||
	_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
 | 
			
		||||
	fdt_set_totalsize(fdt, _blob_data_size(fdt));
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										96
									
								
								kvm/libfdt/fdt_strerror.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								kvm/libfdt/fdt_strerror.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,96 @@
 | 
			
		||||
/*
 | 
			
		||||
 * libfdt - Flat Device Tree manipulation
 | 
			
		||||
 * Copyright (C) 2006 David Gibson, IBM Corporation.
 | 
			
		||||
 *
 | 
			
		||||
 * libfdt is dual licensed: you can use it either under the terms of
 | 
			
		||||
 * the GPL, or the BSD license, at your option.
 | 
			
		||||
 *
 | 
			
		||||
 *  a) This library is free software; you can redistribute it and/or
 | 
			
		||||
 *     modify it under the terms of the GNU General Public License as
 | 
			
		||||
 *     published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 *     License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 *     This library is distributed in the hope that it will be useful,
 | 
			
		||||
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *     GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *     You should have received a copy of the GNU General Public
 | 
			
		||||
 *     License along with this library; if not, write to the Free
 | 
			
		||||
 *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
 | 
			
		||||
 *     MA 02110-1301 USA
 | 
			
		||||
 *
 | 
			
		||||
 * Alternatively,
 | 
			
		||||
 *
 | 
			
		||||
 *  b) Redistribution and use in source and binary forms, with or
 | 
			
		||||
 *     without modification, are permitted provided that the following
 | 
			
		||||
 *     conditions are met:
 | 
			
		||||
 *
 | 
			
		||||
 *     1. Redistributions of source code must retain the above
 | 
			
		||||
 *        copyright notice, this list of conditions and the following
 | 
			
		||||
 *        disclaimer.
 | 
			
		||||
 *     2. Redistributions in binary form must reproduce the above
 | 
			
		||||
 *        copyright notice, this list of conditions and the following
 | 
			
		||||
 *        disclaimer in the documentation and/or other materials
 | 
			
		||||
 *        provided with the distribution.
 | 
			
		||||
 *
 | 
			
		||||
 *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 | 
			
		||||
 *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 | 
			
		||||
 *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
			
		||||
 *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
 *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 | 
			
		||||
 *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
 *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 | 
			
		||||
 *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
 *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
			
		||||
 *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 | 
			
		||||
 *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 | 
			
		||||
 *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
#include "libfdt_env.h"
 | 
			
		||||
 | 
			
		||||
#include <fdt.h>
 | 
			
		||||
#include <libfdt.h>
 | 
			
		||||
 | 
			
		||||
#include "libfdt_internal.h"
 | 
			
		||||
 | 
			
		||||
struct errtabent {
 | 
			
		||||
	const char *str;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define ERRTABENT(val) \
 | 
			
		||||
	[(val)] = { .str = #val, }
 | 
			
		||||
 | 
			
		||||
static struct errtabent errtable[] = {
 | 
			
		||||
	ERRTABENT(FDT_ERR_NOTFOUND),
 | 
			
		||||
	ERRTABENT(FDT_ERR_EXISTS),
 | 
			
		||||
	ERRTABENT(FDT_ERR_NOSPACE),
 | 
			
		||||
 | 
			
		||||
	ERRTABENT(FDT_ERR_BADOFFSET),
 | 
			
		||||
	ERRTABENT(FDT_ERR_BADPATH),
 | 
			
		||||
	ERRTABENT(FDT_ERR_BADSTATE),
 | 
			
		||||
 | 
			
		||||
	ERRTABENT(FDT_ERR_TRUNCATED),
 | 
			
		||||
	ERRTABENT(FDT_ERR_BADMAGIC),
 | 
			
		||||
	ERRTABENT(FDT_ERR_BADVERSION),
 | 
			
		||||
	ERRTABENT(FDT_ERR_BADSTRUCTURE),
 | 
			
		||||
	ERRTABENT(FDT_ERR_BADLAYOUT),
 | 
			
		||||
};
 | 
			
		||||
#define ERRTABSIZE	(sizeof(errtable) / sizeof(errtable[0]))
 | 
			
		||||
 | 
			
		||||
const char *fdt_strerror(int errval)
 | 
			
		||||
{
 | 
			
		||||
	if (errval > 0)
 | 
			
		||||
		return "<valid offset/length>";
 | 
			
		||||
	else if (errval == 0)
 | 
			
		||||
		return "<no error>";
 | 
			
		||||
	else if (errval > -ERRTABSIZE) {
 | 
			
		||||
		const char *s = errtable[-errval].str;
 | 
			
		||||
 | 
			
		||||
		if (s)
 | 
			
		||||
			return s;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return "<unknown error>";
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										258
									
								
								kvm/libfdt/fdt_sw.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										258
									
								
								kvm/libfdt/fdt_sw.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,258 @@
 | 
			
		||||
/*
 | 
			
		||||
 * libfdt - Flat Device Tree manipulation
 | 
			
		||||
 * Copyright (C) 2006 David Gibson, IBM Corporation.
 | 
			
		||||
 *
 | 
			
		||||
 * libfdt is dual licensed: you can use it either under the terms of
 | 
			
		||||
 * the GPL, or the BSD license, at your option.
 | 
			
		||||
 *
 | 
			
		||||
 *  a) This library is free software; you can redistribute it and/or
 | 
			
		||||
 *     modify it under the terms of the GNU General Public License as
 | 
			
		||||
 *     published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 *     License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 *     This library is distributed in the hope that it will be useful,
 | 
			
		||||
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *     GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *     You should have received a copy of the GNU General Public
 | 
			
		||||
 *     License along with this library; if not, write to the Free
 | 
			
		||||
 *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
 | 
			
		||||
 *     MA 02110-1301 USA
 | 
			
		||||
 *
 | 
			
		||||
 * Alternatively,
 | 
			
		||||
 *
 | 
			
		||||
 *  b) Redistribution and use in source and binary forms, with or
 | 
			
		||||
 *     without modification, are permitted provided that the following
 | 
			
		||||
 *     conditions are met:
 | 
			
		||||
 *
 | 
			
		||||
 *     1. Redistributions of source code must retain the above
 | 
			
		||||
 *        copyright notice, this list of conditions and the following
 | 
			
		||||
 *        disclaimer.
 | 
			
		||||
 *     2. Redistributions in binary form must reproduce the above
 | 
			
		||||
 *        copyright notice, this list of conditions and the following
 | 
			
		||||
 *        disclaimer in the documentation and/or other materials
 | 
			
		||||
 *        provided with the distribution.
 | 
			
		||||
 *
 | 
			
		||||
 *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 | 
			
		||||
 *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 | 
			
		||||
 *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
			
		||||
 *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
 *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 | 
			
		||||
 *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
 *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 | 
			
		||||
 *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
 *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
			
		||||
 *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 | 
			
		||||
 *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 | 
			
		||||
 *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
#include "libfdt_env.h"
 | 
			
		||||
 | 
			
		||||
#include <fdt.h>
 | 
			
		||||
#include <libfdt.h>
 | 
			
		||||
 | 
			
		||||
#include "libfdt_internal.h"
 | 
			
		||||
 | 
			
		||||
static int check_header_sw(void *fdt)
 | 
			
		||||
{
 | 
			
		||||
	if (fdt_magic(fdt) != SW_MAGIC)
 | 
			
		||||
		return -FDT_ERR_BADMAGIC;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void *grab_space(void *fdt, int len)
 | 
			
		||||
{
 | 
			
		||||
	int offset = fdt_size_dt_struct(fdt);
 | 
			
		||||
	int spaceleft;
 | 
			
		||||
 | 
			
		||||
	spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
 | 
			
		||||
		- fdt_size_dt_strings(fdt);
 | 
			
		||||
 | 
			
		||||
	if ((offset + len < offset) || (offset + len > spaceleft))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	fdt_set_size_dt_struct(fdt, offset + len);
 | 
			
		||||
	return fdt_offset_ptr_w(fdt, offset, len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_create(void *buf, int bufsize)
 | 
			
		||||
{
 | 
			
		||||
	void *fdt = buf;
 | 
			
		||||
 | 
			
		||||
	if (bufsize < sizeof(struct fdt_header))
 | 
			
		||||
		return -FDT_ERR_NOSPACE;
 | 
			
		||||
 | 
			
		||||
	memset(buf, 0, bufsize);
 | 
			
		||||
 | 
			
		||||
	fdt_set_magic(fdt, SW_MAGIC);
 | 
			
		||||
	fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
 | 
			
		||||
	fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
 | 
			
		||||
	fdt_set_totalsize(fdt,  bufsize);
 | 
			
		||||
 | 
			
		||||
	fdt_set_off_mem_rsvmap(fdt, ALIGN(sizeof(struct fdt_header),
 | 
			
		||||
					  sizeof(struct fdt_reserve_entry)));
 | 
			
		||||
	fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
 | 
			
		||||
	fdt_set_off_dt_strings(fdt, bufsize);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
 | 
			
		||||
{
 | 
			
		||||
	struct fdt_reserve_entry *re;
 | 
			
		||||
	int err = check_header_sw(fdt);
 | 
			
		||||
	int offset;
 | 
			
		||||
 | 
			
		||||
	if (err)
 | 
			
		||||
		return err;
 | 
			
		||||
	if (fdt_size_dt_struct(fdt))
 | 
			
		||||
		return -FDT_ERR_BADSTATE;
 | 
			
		||||
 | 
			
		||||
	offset = fdt_off_dt_struct(fdt);
 | 
			
		||||
	if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
 | 
			
		||||
		return -FDT_ERR_NOSPACE;
 | 
			
		||||
 | 
			
		||||
	re = (struct fdt_reserve_entry *)(fdt + offset);
 | 
			
		||||
	re->address = cpu_to_fdt64(addr);
 | 
			
		||||
	re->size = cpu_to_fdt64(size);
 | 
			
		||||
 | 
			
		||||
	fdt_set_off_dt_struct(fdt, offset + sizeof(*re));
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_finish_reservemap(void *fdt)
 | 
			
		||||
{
 | 
			
		||||
	return fdt_add_reservemap_entry(fdt, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_begin_node(void *fdt, const char *name)
 | 
			
		||||
{
 | 
			
		||||
	struct fdt_node_header *nh;
 | 
			
		||||
	int err = check_header_sw(fdt);
 | 
			
		||||
	int namelen = strlen(name) + 1;
 | 
			
		||||
 | 
			
		||||
	if (err)
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	nh = grab_space(fdt, sizeof(*nh) + ALIGN(namelen, FDT_TAGSIZE));
 | 
			
		||||
	if (! nh)
 | 
			
		||||
		return -FDT_ERR_NOSPACE;
 | 
			
		||||
 | 
			
		||||
	nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
 | 
			
		||||
	memcpy(nh->name, name, namelen);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_end_node(void *fdt)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t *en;
 | 
			
		||||
	int err = check_header_sw(fdt);
 | 
			
		||||
 | 
			
		||||
	if (err)
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	en = grab_space(fdt, FDT_TAGSIZE);
 | 
			
		||||
	if (! en)
 | 
			
		||||
		return -FDT_ERR_NOSPACE;
 | 
			
		||||
 | 
			
		||||
	*en = cpu_to_fdt32(FDT_END_NODE);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int find_add_string(void *fdt, const char *s)
 | 
			
		||||
{
 | 
			
		||||
	char *strtab = (char *)fdt + fdt_totalsize(fdt);
 | 
			
		||||
	const char *p;
 | 
			
		||||
	int strtabsize = fdt_size_dt_strings(fdt);
 | 
			
		||||
	int len = strlen(s) + 1;
 | 
			
		||||
	int struct_top, offset;
 | 
			
		||||
 | 
			
		||||
	p = _fdt_find_string(strtab - strtabsize, strtabsize, s);
 | 
			
		||||
	if (p)
 | 
			
		||||
		return p - strtab;
 | 
			
		||||
 | 
			
		||||
	/* Add it */
 | 
			
		||||
	offset = -strtabsize - len;
 | 
			
		||||
	struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
 | 
			
		||||
	if (fdt_totalsize(fdt) + offset < struct_top)
 | 
			
		||||
		return 0; /* no more room :( */
 | 
			
		||||
 | 
			
		||||
	memcpy(strtab + offset, s, len);
 | 
			
		||||
	fdt_set_size_dt_strings(fdt, strtabsize + len);
 | 
			
		||||
	return offset;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_property(void *fdt, const char *name, const void *val, int len)
 | 
			
		||||
{
 | 
			
		||||
	struct fdt_property *prop;
 | 
			
		||||
	int err = check_header_sw(fdt);
 | 
			
		||||
	int nameoff;
 | 
			
		||||
 | 
			
		||||
	if (err)
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	nameoff = find_add_string(fdt, name);
 | 
			
		||||
	if (nameoff == 0)
 | 
			
		||||
		return -FDT_ERR_NOSPACE;
 | 
			
		||||
 | 
			
		||||
	prop = grab_space(fdt, sizeof(*prop) + ALIGN(len, FDT_TAGSIZE));
 | 
			
		||||
	if (! prop)
 | 
			
		||||
		return -FDT_ERR_NOSPACE;
 | 
			
		||||
 | 
			
		||||
	prop->tag = cpu_to_fdt32(FDT_PROP);
 | 
			
		||||
	prop->nameoff = cpu_to_fdt32(nameoff);
 | 
			
		||||
	prop->len = cpu_to_fdt32(len);
 | 
			
		||||
	memcpy(prop->data, val, len);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_finish(void *fdt)
 | 
			
		||||
{
 | 
			
		||||
	int err = check_header_sw(fdt);
 | 
			
		||||
	char *p = (char *)fdt;
 | 
			
		||||
	uint32_t *end;
 | 
			
		||||
	int oldstroffset, newstroffset;
 | 
			
		||||
	uint32_t tag;
 | 
			
		||||
	int offset, nextoffset;
 | 
			
		||||
 | 
			
		||||
	if (err)
 | 
			
		||||
		return err;
 | 
			
		||||
 | 
			
		||||
	/* Add terminator */
 | 
			
		||||
	end = grab_space(fdt, sizeof(*end));
 | 
			
		||||
	if (! end)
 | 
			
		||||
		return -FDT_ERR_NOSPACE;
 | 
			
		||||
	*end = cpu_to_fdt32(FDT_END);
 | 
			
		||||
 | 
			
		||||
	/* Relocate the string table */
 | 
			
		||||
	oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt);
 | 
			
		||||
	newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
 | 
			
		||||
	memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt));
 | 
			
		||||
	fdt_set_off_dt_strings(fdt, newstroffset);
 | 
			
		||||
 | 
			
		||||
	/* Walk the structure, correcting string offsets */
 | 
			
		||||
	offset = 0;
 | 
			
		||||
	while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
 | 
			
		||||
		if (tag == FDT_PROP) {
 | 
			
		||||
			struct fdt_property *prop =
 | 
			
		||||
				fdt_offset_ptr_w(fdt, offset, sizeof(*prop));
 | 
			
		||||
			int nameoff;
 | 
			
		||||
 | 
			
		||||
			if (! prop)
 | 
			
		||||
				return -FDT_ERR_BADSTRUCTURE;
 | 
			
		||||
 | 
			
		||||
			nameoff = fdt32_to_cpu(prop->nameoff);
 | 
			
		||||
			nameoff += fdt_size_dt_strings(fdt);
 | 
			
		||||
			prop->nameoff = cpu_to_fdt32(nameoff);
 | 
			
		||||
		}
 | 
			
		||||
		offset = nextoffset;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Finally, adjust the header */
 | 
			
		||||
	fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
 | 
			
		||||
	fdt_set_magic(fdt, FDT_MAGIC);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										144
									
								
								kvm/libfdt/fdt_wip.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								kvm/libfdt/fdt_wip.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,144 @@
 | 
			
		||||
/*
 | 
			
		||||
 * libfdt - Flat Device Tree manipulation
 | 
			
		||||
 * Copyright (C) 2006 David Gibson, IBM Corporation.
 | 
			
		||||
 *
 | 
			
		||||
 * libfdt is dual licensed: you can use it either under the terms of
 | 
			
		||||
 * the GPL, or the BSD license, at your option.
 | 
			
		||||
 *
 | 
			
		||||
 *  a) This library is free software; you can redistribute it and/or
 | 
			
		||||
 *     modify it under the terms of the GNU General Public License as
 | 
			
		||||
 *     published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 *     License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 *     This library is distributed in the hope that it will be useful,
 | 
			
		||||
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *     GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *     You should have received a copy of the GNU General Public
 | 
			
		||||
 *     License along with this library; if not, write to the Free
 | 
			
		||||
 *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
 | 
			
		||||
 *     MA 02110-1301 USA
 | 
			
		||||
 *
 | 
			
		||||
 * Alternatively,
 | 
			
		||||
 *
 | 
			
		||||
 *  b) Redistribution and use in source and binary forms, with or
 | 
			
		||||
 *     without modification, are permitted provided that the following
 | 
			
		||||
 *     conditions are met:
 | 
			
		||||
 *
 | 
			
		||||
 *     1. Redistributions of source code must retain the above
 | 
			
		||||
 *        copyright notice, this list of conditions and the following
 | 
			
		||||
 *        disclaimer.
 | 
			
		||||
 *     2. Redistributions in binary form must reproduce the above
 | 
			
		||||
 *        copyright notice, this list of conditions and the following
 | 
			
		||||
 *        disclaimer in the documentation and/or other materials
 | 
			
		||||
 *        provided with the distribution.
 | 
			
		||||
 *
 | 
			
		||||
 *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 | 
			
		||||
 *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 | 
			
		||||
 *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
			
		||||
 *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
 *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 | 
			
		||||
 *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
 *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 | 
			
		||||
 *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
 *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
			
		||||
 *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 | 
			
		||||
 *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 | 
			
		||||
 *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
#include "libfdt_env.h"
 | 
			
		||||
 | 
			
		||||
#include <fdt.h>
 | 
			
		||||
#include <libfdt.h>
 | 
			
		||||
 | 
			
		||||
#include "libfdt_internal.h"
 | 
			
		||||
 | 
			
		||||
int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
 | 
			
		||||
			const void *val, int len)
 | 
			
		||||
{
 | 
			
		||||
	void *propval;
 | 
			
		||||
	int proplen;
 | 
			
		||||
 | 
			
		||||
	propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen);
 | 
			
		||||
	if (! propval)
 | 
			
		||||
		return proplen;
 | 
			
		||||
 | 
			
		||||
	if (proplen != len)
 | 
			
		||||
		return -FDT_ERR_NOSPACE;
 | 
			
		||||
 | 
			
		||||
	memcpy(propval, val, len);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void nop_region(void *start, int len)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t *p;
 | 
			
		||||
 | 
			
		||||
	for (p = start; (void *)p < (start + len); p++)
 | 
			
		||||
		*p = cpu_to_fdt32(FDT_NOP);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
 | 
			
		||||
{
 | 
			
		||||
	struct fdt_property *prop;
 | 
			
		||||
	int len;
 | 
			
		||||
 | 
			
		||||
	prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
 | 
			
		||||
	if (! prop)
 | 
			
		||||
		return len;
 | 
			
		||||
 | 
			
		||||
	nop_region(prop, len + sizeof(*prop));
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int _fdt_node_end_offset(void *fdt, int nodeoffset)
 | 
			
		||||
{
 | 
			
		||||
	int level = 0;
 | 
			
		||||
	uint32_t tag;
 | 
			
		||||
	int offset, nextoffset;
 | 
			
		||||
 | 
			
		||||
	tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
 | 
			
		||||
	if (tag != FDT_BEGIN_NODE)
 | 
			
		||||
		return -FDT_ERR_BADOFFSET;
 | 
			
		||||
	do {
 | 
			
		||||
		offset = nextoffset;
 | 
			
		||||
		tag = fdt_next_tag(fdt, offset, &nextoffset);
 | 
			
		||||
 | 
			
		||||
		switch (tag) {
 | 
			
		||||
		case FDT_END:
 | 
			
		||||
			return offset;
 | 
			
		||||
 | 
			
		||||
		case FDT_BEGIN_NODE:
 | 
			
		||||
			level++;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case FDT_END_NODE:
 | 
			
		||||
			level--;
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		case FDT_PROP:
 | 
			
		||||
		case FDT_NOP:
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		default:
 | 
			
		||||
			return -FDT_ERR_BADSTRUCTURE;
 | 
			
		||||
		}
 | 
			
		||||
	} while (level >= 0);
 | 
			
		||||
 | 
			
		||||
	return nextoffset;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fdt_nop_node(void *fdt, int nodeoffset)
 | 
			
		||||
{
 | 
			
		||||
	int endoffset;
 | 
			
		||||
 | 
			
		||||
	endoffset = _fdt_node_end_offset(fdt, nodeoffset);
 | 
			
		||||
	if (endoffset < 0)
 | 
			
		||||
		return endoffset;
 | 
			
		||||
 | 
			
		||||
	nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0), endoffset - nodeoffset);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1076
									
								
								kvm/libfdt/libfdt.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1076
									
								
								kvm/libfdt/libfdt.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										22
									
								
								kvm/libfdt/libfdt_env.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								kvm/libfdt/libfdt_env.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
#ifndef _LIBFDT_ENV_H
 | 
			
		||||
#define _LIBFDT_ENV_H
 | 
			
		||||
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <endian.h>
 | 
			
		||||
#include <byteswap.h>
 | 
			
		||||
 | 
			
		||||
#if __BYTE_ORDER == __BIG_ENDIAN
 | 
			
		||||
#define fdt32_to_cpu(x)		(x)
 | 
			
		||||
#define cpu_to_fdt32(x)		(x)
 | 
			
		||||
#define fdt64_to_cpu(x)		(x)
 | 
			
		||||
#define cpu_to_fdt64(x)		(x)
 | 
			
		||||
#else
 | 
			
		||||
#define fdt32_to_cpu(x)		(bswap_32((x)))
 | 
			
		||||
#define cpu_to_fdt32(x)		(bswap_32((x)))
 | 
			
		||||
#define fdt64_to_cpu(x)		(bswap_64((x)))
 | 
			
		||||
#define cpu_to_fdt64(x)		(bswap_64((x)))
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* _LIBFDT_ENV_H */
 | 
			
		||||
							
								
								
									
										96
									
								
								kvm/libfdt/libfdt_internal.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								kvm/libfdt/libfdt_internal.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,96 @@
 | 
			
		||||
#ifndef _LIBFDT_INTERNAL_H
 | 
			
		||||
#define _LIBFDT_INTERNAL_H
 | 
			
		||||
/*
 | 
			
		||||
 * libfdt - Flat Device Tree manipulation
 | 
			
		||||
 * Copyright (C) 2006 David Gibson, IBM Corporation.
 | 
			
		||||
 *
 | 
			
		||||
 * libfdt is dual licensed: you can use it either under the terms of
 | 
			
		||||
 * the GPL, or the BSD license, at your option.
 | 
			
		||||
 *
 | 
			
		||||
 *  a) This library is free software; you can redistribute it and/or
 | 
			
		||||
 *     modify it under the terms of the GNU General Public License as
 | 
			
		||||
 *     published by the Free Software Foundation; either version 2 of the
 | 
			
		||||
 *     License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 *     This library is distributed in the hope that it will be useful,
 | 
			
		||||
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 *     GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 *     You should have received a copy of the GNU General Public
 | 
			
		||||
 *     License along with this library; if not, write to the Free
 | 
			
		||||
 *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
 | 
			
		||||
 *     MA 02110-1301 USA
 | 
			
		||||
 *
 | 
			
		||||
 * Alternatively,
 | 
			
		||||
 *
 | 
			
		||||
 *  b) Redistribution and use in source and binary forms, with or
 | 
			
		||||
 *     without modification, are permitted provided that the following
 | 
			
		||||
 *     conditions are met:
 | 
			
		||||
 *
 | 
			
		||||
 *     1. Redistributions of source code must retain the above
 | 
			
		||||
 *        copyright notice, this list of conditions and the following
 | 
			
		||||
 *        disclaimer.
 | 
			
		||||
 *     2. Redistributions in binary form must reproduce the above
 | 
			
		||||
 *        copyright notice, this list of conditions and the following
 | 
			
		||||
 *        disclaimer in the documentation and/or other materials
 | 
			
		||||
 *        provided with the distribution.
 | 
			
		||||
 *
 | 
			
		||||
 *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 | 
			
		||||
 *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 | 
			
		||||
 *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
			
		||||
 *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 | 
			
		||||
 *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 | 
			
		||||
 *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | 
			
		||||
 *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 | 
			
		||||
 *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 | 
			
		||||
 *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
			
		||||
 *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 | 
			
		||||
 *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 | 
			
		||||
 *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 | 
			
		||||
 *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
#include <fdt.h>
 | 
			
		||||
 | 
			
		||||
#define ALIGN(x, a)	(((x) + (a) - 1) & ~((a) - 1))
 | 
			
		||||
#define PALIGN(p, a)	((void *)ALIGN((unsigned long)(p), (a)))
 | 
			
		||||
 | 
			
		||||
#define memeq(p, q, n)	(memcmp((p), (q), (n)) == 0)
 | 
			
		||||
#define streq(p, q)	(strcmp((p), (q)) == 0)
 | 
			
		||||
 | 
			
		||||
#define CHECK_HEADER(fdt) \
 | 
			
		||||
	{ \
 | 
			
		||||
		int err; \
 | 
			
		||||
		if ((err = fdt_check_header(fdt)) != 0) \
 | 
			
		||||
			return err; \
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset);
 | 
			
		||||
const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
 | 
			
		||||
int _fdt_node_end_offset(void *fdt, int nodeoffset);
 | 
			
		||||
 | 
			
		||||
static inline const void *_fdt_offset_ptr(const void *fdt, int offset)
 | 
			
		||||
{
 | 
			
		||||
	return fdt + fdt_off_dt_struct(fdt) + offset;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void *_fdt_offset_ptr_w(void *fdt, int offset)
 | 
			
		||||
{
 | 
			
		||||
	return (void *)_fdt_offset_ptr(fdt, offset);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n)
 | 
			
		||||
{
 | 
			
		||||
	const struct fdt_reserve_entry *rsv_table =
 | 
			
		||||
		fdt + fdt_off_mem_rsvmap(fdt);
 | 
			
		||||
 | 
			
		||||
	return rsv_table + n;
 | 
			
		||||
}
 | 
			
		||||
static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n)
 | 
			
		||||
{
 | 
			
		||||
	return (void *)_fdt_mem_rsv(fdt, n);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define SW_MAGIC		(~FDT_MAGIC)
 | 
			
		||||
 | 
			
		||||
#endif /* _LIBFDT_INTERNAL_H */
 | 
			
		||||
							
								
								
									
										54
									
								
								kvm/libkvm/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								kvm/libkvm/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
all: libkvm.a
 | 
			
		||||
 | 
			
		||||
include ../../config-host.mak
 | 
			
		||||
ifneq ($(VPATH),)
 | 
			
		||||
srcdir=$(VPATH)/kvm/libkvm
 | 
			
		||||
else
 | 
			
		||||
srcdir=.
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
include $(srcdir)/config-$(ARCH).mak
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# libkvm is not -Wredundant-decls friendly yet
 | 
			
		||||
CFLAGS += -Wno-redundant-decls
 | 
			
		||||
 | 
			
		||||
# cc-option
 | 
			
		||||
# Usage: OP_CFLAGS+=$(call cc-option, -falign-functions=0, -malign-functions=0)
 | 
			
		||||
cc-option = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null \
 | 
			
		||||
              > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
 | 
			
		||||
 | 
			
		||||
CFLAGS += $(autodepend-flags) -g -fomit-frame-pointer -Wall
 | 
			
		||||
CFLAGS += $(call cc-option, -fno-stack-protector, "")
 | 
			
		||||
CFLAGS += $(call cc-option, -fno-stack-protector-all, "")
 | 
			
		||||
CFLAGS += $(KVM_CFLAGS)
 | 
			
		||||
 | 
			
		||||
LDFLAGS += $(CFLAGS)
 | 
			
		||||
 | 
			
		||||
CXXFLAGS = $(autodepend-flags)
 | 
			
		||||
 | 
			
		||||
VPATH:=$(VPATH)/kvm/libkvm
 | 
			
		||||
 | 
			
		||||
autodepend-flags = -MMD -MF $(dir $*).$(notdir $*).d
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
libkvm.a: libkvm.o $(libkvm-$(ARCH)-objs)
 | 
			
		||||
	$(AR) rcs $@ $^
 | 
			
		||||
 | 
			
		||||
install:
 | 
			
		||||
	@echo skipping libkvm install
 | 
			
		||||
 | 
			
		||||
install-libkvm:
 | 
			
		||||
	install -D libkvm.h $(DESTDIR)/$(PREFIX)/include/libkvm.h
 | 
			
		||||
	install -D libkvm.a $(DESTDIR)/$(PREFIX)/$(LIBDIR)/libkvm.a
 | 
			
		||||
 | 
			
		||||
install-kernel-headers:
 | 
			
		||||
	install -D $(LIBKVM_KERNELDIR)/include/linux/kvm.h \
 | 
			
		||||
		$(DESTDIR)/$(PREFIX)/include/linux/kvm.h
 | 
			
		||||
	install -D $(LIBKVM_KERNELDIR)/include/linux/kvm_para.h \
 | 
			
		||||
		$(DESTDIR)/$(PREFIX)/include/linux/kvm_para.h
 | 
			
		||||
 | 
			
		||||
-include .*.d
 | 
			
		||||
 | 
			
		||||
clean:
 | 
			
		||||
	$(RM) *.o *.a .*.d
 | 
			
		||||
							
								
								
									
										6
									
								
								kvm/libkvm/config-i386.mak
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								kvm/libkvm/config-i386.mak
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
 | 
			
		||||
LIBDIR := /lib
 | 
			
		||||
CFLAGS += -m32
 | 
			
		||||
CFLAGS += -D__i386__
 | 
			
		||||
 | 
			
		||||
libkvm-$(ARCH)-objs := libkvm-x86.o
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user