diff --git a/.hgignore b/.hgignore index 95b03e6db2..4a3636cab5 100644 --- a/.hgignore +++ b/.hgignore @@ -107,6 +107,7 @@ ^tools/firmware/rombios/BIOS-bochs-[^/]*$ ^tools/firmware/rombios/_rombios[^/]*_\.c$ ^tools/firmware/rombios/rombios[^/]*\.s$ +^tools/firmware/rombios/32bit/32bitbios_flat\.h$ ^tools/firmware/vmxassist/gen$ ^tools/firmware/vmxassist/offsets\.h$ ^tools/firmware/vmxassist/vmxassist$ @@ -137,6 +138,7 @@ ^tools/misc/miniterm/miniterm$ ^tools/misc/xc_shadow$ ^tools/misc/xen_cpuperf$ +^tools/misc/xen-detect$ ^tools/misc/xenperf$ ^tools/pygrub/build/.*$ ^tools/python/build/.*$ diff --git a/buildconfigs/linux-defconfig_xen0_ia64 b/buildconfigs/linux-defconfig_xen0_ia64 index 84fa7c7abb..9869aab066 100644 --- a/buildconfigs/linux-defconfig_xen0_ia64 +++ b/buildconfigs/linux-defconfig_xen0_ia64 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16.29-xen0 -# Tue Nov 14 10:39:09 2006 +# Linux kernel version: 2.6.18-xen0 +# Mon Jan 29 10:16:18 2007 # # @@ -21,14 +21,16 @@ CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_BSD_PROCESS_ACCT=y # CONFIG_BSD_PROCESS_ACCT_V3 is not set -CONFIG_SYSCTL=y +# CONFIG_TASKSTATS is not set # CONFIG_AUDIT is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_CPUSETS is not set +# CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_EMBEDDED is not set +CONFIG_SYSCTL=y CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y CONFIG_KALLSYMS_EXTRA_PASS=y @@ -40,11 +42,9 @@ CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 # CONFIG_SLOB is not set @@ -55,7 +55,6 @@ CONFIG_BASE_SMALL=0 CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y @@ -64,6 +63,7 @@ CONFIG_STOP_MACHINE=y # # Block layer # +# CONFIG_BLK_DEV_IO_TRACE is not set # # IO Schedulers @@ -86,8 +86,10 @@ CONFIG_64BIT=y CONFIG_MMU=y CONFIG_SWIOTLB=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_TIME_INTERPOLATION=y +CONFIG_DMI=y CONFIG_EFI=y CONFIG_GENERIC_IOMAP=y CONFIG_XEN=y @@ -96,6 +98,7 @@ CONFIG_XEN_IA64_EXPOSE_P2M=y CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y CONFIG_DMA_IS_DMA32=y +CONFIG_AUDIT_ARCH=y # CONFIG_IA64_GENERIC is not set CONFIG_IA64_DIG=y # CONFIG_IA64_HP_ZX1 is not set @@ -123,6 +126,7 @@ CONFIG_NR_CPUS=16 CONFIG_HOTPLUG_CPU=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y # CONFIG_SCHED_SMT is not set +# CONFIG_PERMIT_BSP_REMOVE is not set # CONFIG_PREEMPT is not set CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y @@ -132,6 +136,7 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_RESOURCES_64BIT=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_DISCONTIGMEM_ENABLE=y CONFIG_ARCH_FLATMEM_ENABLE=y @@ -163,6 +168,7 @@ CONFIG_PM_LEGACY=y CONFIG_ACPI=y CONFIG_ACPI_BUTTON=y CONFIG_ACPI_FAN=y +# CONFIG_ACPI_DOCK is not set CONFIG_ACPI_PROCESSOR=y CONFIG_ACPI_HOTPLUG_CPU=y CONFIG_ACPI_THERMAL=y @@ -185,7 +191,7 @@ CONFIG_PCI=y CONFIG_PCI_DOMAINS=y CONFIG_XEN_PCIDEV_FRONTEND=y # CONFIG_XEN_PCIDEV_FE_DEBUG is not set -CONFIG_PCI_LEGACY_PROC=y +# CONFIG_PCIEPORTBUS is not set # CONFIG_PCI_DEBUG is not set # @@ -215,6 +221,8 @@ CONFIG_NET=y CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set # CONFIG_NET_KEY is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y @@ -229,7 +237,10 @@ CONFIG_SYN_COOKIES=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set @@ -240,6 +251,9 @@ CONFIG_TCP_CONG_BIC=y # # CONFIG_IP_VS is not set # CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set CONFIG_BRIDGE_NETFILTER=y @@ -280,12 +294,12 @@ CONFIG_BRIDGE_NETFILTER=y CONFIG_BRIDGE=y # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set +CONFIG_LLC=y # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -314,6 +328,7 @@ CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=y # CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set # # Connector - unified userspace <-> kernelspace linker @@ -352,6 +367,7 @@ CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 CONFIG_BLK_DEV_INITRD=y # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set @@ -463,6 +479,7 @@ CONFIG_SCSI_SAS_ATTRS=y # CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_SAS is not set # CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_HPTIOP is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_IPS is not set @@ -472,10 +489,8 @@ CONFIG_SCSI_SYM53C8XX_2=y CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 -# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +CONFIG_SCSI_SYM53C8XX_MMIO=y # CONFIG_SCSI_IPR is not set -CONFIG_SCSI_QLOGIC_FC=y -# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set CONFIG_SCSI_QLOGIC_1280=y # CONFIG_SCSI_QLA_FC is not set # CONFIG_SCSI_LPFC is not set @@ -488,7 +503,13 @@ CONFIG_SCSI_QLOGIC_1280=y # CONFIG_MD=y # CONFIG_BLK_DEV_MD is not set -# CONFIG_BLK_DEV_DM is not set +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m # # Fusion MPT device support @@ -607,6 +628,7 @@ CONFIG_TIGON3=y # CONFIG_CHELSIO_T1 is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set # # Token Ring devices @@ -709,6 +731,7 @@ CONFIG_GAMEPORT=y CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set CONFIG_SERIAL_NONSTANDARD=y # CONFIG_COMPUTONE is not set # CONFIG_ROCKETPORT is not set @@ -722,6 +745,7 @@ CONFIG_SERIAL_NONSTANDARD=y # CONFIG_N_HDLC is not set # CONFIG_SPECIALIX is not set # CONFIG_SX is not set +# CONFIG_RIO is not set # CONFIG_STALDRV is not set # @@ -755,6 +779,8 @@ CONFIG_EFI_RTC=y # Ftape, the floppy tape device driver # CONFIG_AGP=y +# CONFIG_AGP_SIS is not set +# CONFIG_AGP_VIA is not set CONFIG_AGP_I460=y CONFIG_DRM=y # CONFIG_DRM_TDFX is not set @@ -799,10 +825,10 @@ CONFIG_I2C_ALGOPCF=y # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_OCORES is not set # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PROSAVAGE is not set # CONFIG_I2C_SAVAGE4 is not set -# CONFIG_SCx200_ACB is not set # CONFIG_I2C_SIS5595 is not set # CONFIG_I2C_SIS630 is not set # CONFIG_I2C_SIS96X is not set @@ -821,9 +847,7 @@ CONFIG_I2C_ALGOPCF=y # CONFIG_SENSORS_PCF8574 is not set # CONFIG_SENSORS_PCA9539 is not set # CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set # CONFIG_SENSORS_MAX6875 is not set -# CONFIG_RTC_X1205_I2C is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set @@ -838,13 +862,13 @@ CONFIG_I2C_ALGOPCF=y # # Dallas's 1-wire bus # -# CONFIG_W1 is not set # # Hardware Monitoring support # CONFIG_HWMON=y # CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set @@ -873,10 +897,12 @@ CONFIG_HWMON=y # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set # CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_VT8231 is not set # CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set # CONFIG_SENSORS_W83792D is not set # CONFIG_SENSORS_W83L785TS is not set # CONFIG_SENSORS_W83627HF is not set @@ -887,25 +913,26 @@ CONFIG_HWMON=y # Misc devices # -# -# Multimedia Capabilities Port drivers -# - # # Multimedia devices # CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=y # -# Video For Linux +# Video Capture Adapters # # -# Video Adapters +# Video Capture Adapters # # CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_VIVI is not set # CONFIG_VIDEO_BT848 is not set # CONFIG_VIDEO_CPIA is not set +# CONFIG_VIDEO_CPIA2 is not set # CONFIG_VIDEO_SAA5246A is not set # CONFIG_VIDEO_SAA5249 is not set # CONFIG_TUNER_3036 is not set @@ -917,10 +944,40 @@ CONFIG_VIDEO_DEV=y # CONFIG_VIDEO_HEXIUM_ORION is not set # CONFIG_VIDEO_HEXIUM_GEMINI is not set # CONFIG_VIDEO_CX88 is not set + +# +# Encoders and Decoders +# +# CONFIG_VIDEO_MSP3400 is not set +# CONFIG_VIDEO_CS53L32A is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +# CONFIG_VIDEO_WM8775 is not set +# CONFIG_VIDEO_WM8739 is not set +# CONFIG_VIDEO_CX2341X is not set +# CONFIG_VIDEO_CX25840 is not set +# CONFIG_VIDEO_SAA711X is not set +# CONFIG_VIDEO_SAA7127 is not set +# CONFIG_VIDEO_UPD64031A is not set +# CONFIG_VIDEO_UPD64083 is not set + +# +# V4L USB devices +# +# CONFIG_VIDEO_PVRUSB2 is not set # CONFIG_VIDEO_EM28XX is not set +# CONFIG_USB_VICAM is not set +# CONFIG_USB_IBMCAM is not set +# CONFIG_USB_KONICAWC is not set +# CONFIG_USB_QUICKCAM_MESSENGER is not set +# CONFIG_USB_ET61X251 is not set # CONFIG_VIDEO_OVCAMCHIP is not set -# CONFIG_VIDEO_AUDIO_DECODER is not set -# CONFIG_VIDEO_DECODER is not set +# CONFIG_USB_W9968CF is not set +# CONFIG_USB_OV511 is not set +# CONFIG_USB_SE401 is not set +# CONFIG_USB_SN9C102 is not set +# CONFIG_USB_STV680 is not set +# CONFIG_USB_ZC0301 is not set +# CONFIG_USB_PWC is not set # # Radio Adapters @@ -928,20 +985,24 @@ CONFIG_VIDEO_DEV=y # CONFIG_RADIO_GEMTEK_PCI is not set # CONFIG_RADIO_MAXIRADIO is not set # CONFIG_RADIO_MAESTRO is not set +# CONFIG_USB_DSBR is not set # # Digital Video Broadcasting Devices # # CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set # # Graphics support # +CONFIG_FIRMWARE_EDID=y CONFIG_FB=y CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set CONFIG_FB_MODE_HELPERS=y # CONFIG_FB_TILEBLITTING is not set # CONFIG_FB_CIRRUS is not set @@ -953,7 +1014,6 @@ CONFIG_FB_MODE_HELPERS=y # CONFIG_FB_NVIDIA is not set # CONFIG_FB_RIVA is not set # CONFIG_FB_MATROX is not set -# CONFIG_FB_RADEON_OLD is not set CONFIG_FB_RADEON=y CONFIG_FB_RADEON_I2C=y CONFIG_FB_RADEON_DEBUG=y @@ -972,6 +1032,7 @@ CONFIG_FB_RADEON_DEBUG=y # Console display driver support # CONFIG_VGA_CONSOLE=y +# CONFIG_VGACON_SOFT_SCROLLBACK is not set CONFIG_DUMMY_CONSOLE=y # CONFIG_FRAMEBUFFER_CONSOLE is not set @@ -1002,9 +1063,11 @@ CONFIG_SND_SEQ_DUMMY=y CONFIG_SND_OSSEMUL=y CONFIG_SND_MIXER_OSS=y CONFIG_SND_PCM_OSS=y +CONFIG_SND_PCM_OSS_PLUGINS=y CONFIG_SND_SEQUENCER_OSS=y # CONFIG_SND_DYNAMIC_MINORS is not set CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set @@ -1025,6 +1088,7 @@ CONFIG_SND_MPU401=y # PCI devices # # CONFIG_SND_AD1889 is not set +# CONFIG_SND_ALS300 is not set # CONFIG_SND_ALI5451 is not set CONFIG_SND_ATIIXP=y # CONFIG_SND_ATIIXP_MODEM is not set @@ -1037,6 +1101,18 @@ CONFIG_SND_ATIIXP=y # CONFIG_SND_CMIPCI is not set # CONFIG_SND_CS4281 is not set # CONFIG_SND_CS46XX is not set +# CONFIG_SND_DARLA20 is not set +# CONFIG_SND_GINA20 is not set +# CONFIG_SND_LAYLA20 is not set +# CONFIG_SND_DARLA24 is not set +# CONFIG_SND_GINA24 is not set +# CONFIG_SND_LAYLA24 is not set +# CONFIG_SND_MONA is not set +# CONFIG_SND_MIA is not set +# CONFIG_SND_ECHO3G is not set +# CONFIG_SND_INDIGO is not set +# CONFIG_SND_INDIGOIO is not set +# CONFIG_SND_INDIGODJ is not set # CONFIG_SND_EMU10K1 is not set # CONFIG_SND_EMU10K1X is not set # CONFIG_SND_ENS1370 is not set @@ -1057,6 +1133,7 @@ CONFIG_SND_FM801=y # CONFIG_SND_MIXART is not set # CONFIG_SND_NM256 is not set # CONFIG_SND_PCXHR is not set +# CONFIG_SND_RIPTIDE is not set # CONFIG_SND_RME32 is not set # CONFIG_SND_RME96 is not set # CONFIG_SND_RME9652 is not set @@ -1076,12 +1153,14 @@ CONFIG_SND_FM801=y # Open Sound System # CONFIG_SOUND_PRIME=y -# CONFIG_OBSOLETE_OSS_DRIVER is not set -# CONFIG_SOUND_FUSION is not set +# CONFIG_OSS_OBSOLETE_DRIVER is not set +# CONFIG_SOUND_BT878 is not set +# CONFIG_SOUND_ES1371 is not set # CONFIG_SOUND_ICH is not set # CONFIG_SOUND_TRIDENT is not set # CONFIG_SOUND_MSNDCLAS is not set # CONFIG_SOUND_MSNDPIN is not set +# CONFIG_SOUND_VIA82CXXX is not set # CONFIG_SOUND_TVMIXER is not set # @@ -1089,6 +1168,7 @@ CONFIG_SOUND_PRIME=y # CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y CONFIG_USB=y # CONFIG_USB_DEBUG is not set @@ -1107,6 +1187,7 @@ CONFIG_USB_BANDWIDTH=y CONFIG_USB_EHCI_HCD=y # CONFIG_USB_EHCI_SPLIT_ISO is not set # CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EHCI_TT_NEWSCHED is not set # CONFIG_USB_ISP116X_HCD is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_BIG_ENDIAN is not set @@ -1117,7 +1198,6 @@ CONFIG_USB_UHCI_HCD=y # # USB Device Class drivers # -# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set # CONFIG_USB_ACM is not set # CONFIG_USB_PRINTER is not set @@ -1154,9 +1234,7 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_ACECAD is not set # CONFIG_USB_KBTAB is not set # CONFIG_USB_POWERMATE is not set -# CONFIG_USB_MTOUCH is not set -# CONFIG_USB_ITMTOUCH is not set -# CONFIG_USB_EGALAX is not set +# CONFIG_USB_TOUCHSCREEN is not set # CONFIG_USB_YEALINK is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set @@ -1170,21 +1248,6 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set -# -# USB Multimedia devices -# -# CONFIG_USB_DABUSB is not set -# CONFIG_USB_VICAM is not set -# CONFIG_USB_DSBR is not set -# CONFIG_USB_ET61X251 is not set -# CONFIG_USB_IBMCAM is not set -# CONFIG_USB_KONICAWC is not set -# CONFIG_USB_OV511 is not set -# CONFIG_USB_SE401 is not set -# CONFIG_USB_SN9C102 is not set -# CONFIG_USB_STV680 is not set -# CONFIG_USB_PWC is not set - # # USB Network Adapters # @@ -1214,10 +1277,12 @@ CONFIG_USB_MON=y # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set # CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set # CONFIG_USB_PHIDGETKIT is not set # CONFIG_USB_PHIDGETSERVO is not set # CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set # CONFIG_USB_TEST is not set @@ -1236,6 +1301,19 @@ CONFIG_USB_MON=y # # CONFIG_MMC is not set +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + # # InfiniBand support # @@ -1245,6 +1323,24 @@ CONFIG_USB_MON=y # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) # +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + # # File systems # @@ -1269,7 +1365,6 @@ CONFIG_REISERFS_FS_SECURITY=y # CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y CONFIG_XFS_FS=y -CONFIG_XFS_EXPORT=y # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_SECURITY is not set # CONFIG_XFS_POSIX_ACL is not set @@ -1278,6 +1373,7 @@ CONFIG_XFS_EXPORT=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=y @@ -1312,7 +1408,6 @@ CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y -# CONFIG_RELAYFS_FS is not set # CONFIG_CONFIGFS_FS is not set # @@ -1358,7 +1453,9 @@ CONFIG_SMB_NLS_DEFAULT=y CONFIG_SMB_NLS_REMOTE="cp437" CONFIG_CIFS=y # CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_WEAK_PW_HASH is not set # CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_DEBUG2 is not set # CONFIG_CIFS_EXPERIMENTAL is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1437,9 +1534,11 @@ CONFIG_NLS_UTF8=y # CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_PENDING_IRQ=y +CONFIG_IRQ_PER_CPU=y # # Instrumentation Support @@ -1452,14 +1551,19 @@ CONFIG_GENERIC_PENDING_IRQ=y # # CONFIG_PRINTK_TIME is not set CONFIG_MAGIC_SYSRQ=y +CONFIG_UNUSED_SYMBOLS=y CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=20 CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set -CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_RWSEMS is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_FS is not set @@ -1513,7 +1617,6 @@ CONFIG_CRYPTO_DES=y # # CONFIG_XEN_UTIL is not set CONFIG_XEN_BALLOON=y -# CONFIG_XEN_DEVMEM is not set CONFIG_XEN_REBOOT=y # CONFIG_XEN_SMPBOOT is not set CONFIG_XEN_INTERFACE_VERSION=0x00030203 @@ -1539,6 +1642,7 @@ CONFIG_XEN_PCIDEV_BACKEND_SLOT=y CONFIG_XEN_TPMDEV_BACKEND=m CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_XEN_NETDEV_FRONTEND=y +# CONFIG_XEN_FRAMEBUFFER is not set # CONFIG_XEN_SCRUB_PAGES is not set CONFIG_XEN_DISABLE_SERIAL=y CONFIG_XEN_SYSFS=y @@ -1547,3 +1651,4 @@ CONFIG_XEN_COMPAT_030002_AND_LATER=y CONFIG_XEN_COMPAT_030002=y CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y CONFIG_NO_IDLE_HZ=y +CONFIG_XEN_DEVMEM=y diff --git a/buildconfigs/linux-defconfig_xenU_ia64 b/buildconfigs/linux-defconfig_xenU_ia64 index 537fd311a9..ed518155e7 100644 --- a/buildconfigs/linux-defconfig_xenU_ia64 +++ b/buildconfigs/linux-defconfig_xenU_ia64 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16.29-xenU -# Wed Oct 4 12:54:26 2006 +# Linux kernel version: 2.6.18-xenU +# Mon Jan 29 10:26:51 2007 # # @@ -21,13 +21,15 @@ CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set CONFIG_BSD_PROCESS_ACCT=y # CONFIG_BSD_PROCESS_ACCT_V3 is not set -CONFIG_SYSCTL=y +# CONFIG_TASKSTATS is not set # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set # CONFIG_CPUSETS is not set +# CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_EMBEDDED is not set +CONFIG_SYSCTL=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set @@ -39,11 +41,9 @@ CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 # CONFIG_SLOB is not set @@ -53,7 +53,6 @@ CONFIG_BASE_SMALL=0 # CONFIG_MODULES=y # CONFIG_MODULE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set # CONFIG_KMOD is not set @@ -61,6 +60,7 @@ CONFIG_OBSOLETE_MODPARM=y # # Block layer # +# CONFIG_BLK_DEV_IO_TRACE is not set # # IO Schedulers @@ -83,8 +83,10 @@ CONFIG_64BIT=y CONFIG_MMU=y CONFIG_SWIOTLB=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_TIME_INTERPOLATION=y +CONFIG_DMI=y CONFIG_EFI=y CONFIG_GENERIC_IOMAP=y CONFIG_XEN=y @@ -93,6 +95,7 @@ CONFIG_XEN_IA64_EXPOSE_P2M=y CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y CONFIG_DMA_IS_DMA32=y +CONFIG_AUDIT_ARCH=y # CONFIG_IA64_GENERIC is not set CONFIG_IA64_DIG=y # CONFIG_IA64_HP_ZX1 is not set @@ -117,9 +120,10 @@ CONFIG_IOSAPIC=y CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_SMP=y CONFIG_NR_CPUS=16 -# CONFIG_HOTPLUG_CPU is not set +CONFIG_HOTPLUG_CPU=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y # CONFIG_SCHED_SMT is not set +# CONFIG_PERMIT_BSP_REMOVE is not set # CONFIG_PREEMPT is not set CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y @@ -129,6 +133,7 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_RESOURCES_64BIT=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_DISCONTIGMEM_ENABLE=y CONFIG_ARCH_FLATMEM_ENABLE=y @@ -161,7 +166,9 @@ CONFIG_PM_LEGACY=y CONFIG_ACPI=y CONFIG_ACPI_BUTTON=y CONFIG_ACPI_FAN=y +# CONFIG_ACPI_DOCK is not set CONFIG_ACPI_PROCESSOR=y +CONFIG_ACPI_HOTPLUG_CPU=y CONFIG_ACPI_THERMAL=y CONFIG_ACPI_BLACKLIST_YEAR=0 # CONFIG_ACPI_DEBUG is not set @@ -182,7 +189,7 @@ CONFIG_PCI=y CONFIG_PCI_DOMAINS=y CONFIG_XEN_PCIDEV_FRONTEND=y # CONFIG_XEN_PCIDEV_FE_DEBUG is not set -CONFIG_PCI_LEGACY_PROC=y +# CONFIG_PCIEPORTBUS is not set # CONFIG_PCI_DEBUG is not set # @@ -212,6 +219,8 @@ CONFIG_NET=y CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set # CONFIG_NET_KEY is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y @@ -226,7 +235,10 @@ CONFIG_IP_FIB_HASH=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set @@ -237,6 +249,9 @@ CONFIG_TCP_CONG_BIC=y # # CONFIG_IP_VS is not set # CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -276,7 +291,6 @@ CONFIG_NETFILTER=y # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -305,6 +319,7 @@ CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set # CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set # # Connector - unified userspace <-> kernelspace linker @@ -342,6 +357,7 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 CONFIG_BLK_DEV_INITRD=y # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set @@ -399,6 +415,7 @@ CONFIG_SCSI_SAS_ATTRS=y # CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_SAS is not set # CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_HPTIOP is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_IPS is not set @@ -408,9 +425,8 @@ CONFIG_SCSI_SYM53C8XX_2=y CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 -# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +CONFIG_SCSI_SYM53C8XX_MMIO=y # CONFIG_SCSI_IPR is not set -# CONFIG_SCSI_QLOGIC_FC is not set CONFIG_SCSI_QLOGIC_1280=y # CONFIG_SCSI_QLA_FC is not set # CONFIG_SCSI_LPFC is not set @@ -532,6 +548,7 @@ CONFIG_TIGON3=y # CONFIG_CHELSIO_T1 is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set # # Token Ring devices @@ -609,6 +626,7 @@ CONFIG_SERIO=y CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set # CONFIG_SERIAL_NONSTANDARD is not set # @@ -616,7 +634,7 @@ CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_ACPI=y +CONFIG_SERIAL_8250_PCI=y CONFIG_SERIAL_8250_NR_UARTS=8 CONFIG_SERIAL_8250_RUNTIME_UARTS=4 CONFIG_SERIAL_8250_EXTENDED=y @@ -653,6 +671,8 @@ CONFIG_EFI_RTC=y # Ftape, the floppy tape device driver # CONFIG_AGP=y +# CONFIG_AGP_SIS is not set +# CONFIG_AGP_VIA is not set # CONFIG_AGP_I460 is not set CONFIG_DRM=y # CONFIG_DRM_TDFX is not set @@ -697,10 +717,10 @@ CONFIG_I2C_ALGOPCF=y # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_OCORES is not set # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PROSAVAGE is not set # CONFIG_I2C_SAVAGE4 is not set -# CONFIG_SCx200_ACB is not set # CONFIG_I2C_SIS5595 is not set # CONFIG_I2C_SIS630 is not set # CONFIG_I2C_SIS96X is not set @@ -719,9 +739,7 @@ CONFIG_I2C_ALGOPCF=y # CONFIG_SENSORS_PCF8574 is not set # CONFIG_SENSORS_PCA9539 is not set # CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set # CONFIG_SENSORS_MAX6875 is not set -# CONFIG_RTC_X1205_I2C is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set @@ -736,13 +754,13 @@ CONFIG_I2C_ALGOPCF=y # # Dallas's 1-wire bus # -# CONFIG_W1 is not set # # Hardware Monitoring support # CONFIG_HWMON=y # CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set @@ -771,10 +789,12 @@ CONFIG_HWMON=y # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set # CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_VT8231 is not set # CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set # CONFIG_SENSORS_W83792D is not set # CONFIG_SENSORS_W83L785TS is not set # CONFIG_SENSORS_W83627HF is not set @@ -785,25 +805,26 @@ CONFIG_HWMON=y # Misc devices # -# -# Multimedia Capabilities Port drivers -# - # # Multimedia devices # CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=y # -# Video For Linux +# Video Capture Adapters # # -# Video Adapters +# Video Capture Adapters # # CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_VIVI is not set # CONFIG_VIDEO_BT848 is not set # CONFIG_VIDEO_CPIA is not set +# CONFIG_VIDEO_CPIA2 is not set # CONFIG_VIDEO_SAA5246A is not set # CONFIG_VIDEO_SAA5249 is not set # CONFIG_TUNER_3036 is not set @@ -815,10 +836,40 @@ CONFIG_VIDEO_DEV=y # CONFIG_VIDEO_HEXIUM_ORION is not set # CONFIG_VIDEO_HEXIUM_GEMINI is not set # CONFIG_VIDEO_CX88 is not set + +# +# Encoders and Decoders +# +# CONFIG_VIDEO_MSP3400 is not set +# CONFIG_VIDEO_CS53L32A is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +# CONFIG_VIDEO_WM8775 is not set +# CONFIG_VIDEO_WM8739 is not set +# CONFIG_VIDEO_CX2341X is not set +# CONFIG_VIDEO_CX25840 is not set +# CONFIG_VIDEO_SAA711X is not set +# CONFIG_VIDEO_SAA7127 is not set +# CONFIG_VIDEO_UPD64031A is not set +# CONFIG_VIDEO_UPD64083 is not set + +# +# V4L USB devices +# +# CONFIG_VIDEO_PVRUSB2 is not set # CONFIG_VIDEO_EM28XX is not set +# CONFIG_USB_VICAM is not set +# CONFIG_USB_IBMCAM is not set +# CONFIG_USB_KONICAWC is not set +# CONFIG_USB_QUICKCAM_MESSENGER is not set +# CONFIG_USB_ET61X251 is not set # CONFIG_VIDEO_OVCAMCHIP is not set -# CONFIG_VIDEO_AUDIO_DECODER is not set -# CONFIG_VIDEO_DECODER is not set +# CONFIG_USB_W9968CF is not set +# CONFIG_USB_OV511 is not set +# CONFIG_USB_SE401 is not set +# CONFIG_USB_SN9C102 is not set +# CONFIG_USB_STV680 is not set +# CONFIG_USB_ZC0301 is not set +# CONFIG_USB_PWC is not set # # Radio Adapters @@ -826,20 +877,24 @@ CONFIG_VIDEO_DEV=y # CONFIG_RADIO_GEMTEK_PCI is not set # CONFIG_RADIO_MAXIRADIO is not set # CONFIG_RADIO_MAESTRO is not set +# CONFIG_USB_DSBR is not set # # Digital Video Broadcasting Devices # # CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set # # Graphics support # +CONFIG_FIRMWARE_EDID=y CONFIG_FB=y CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set CONFIG_FB_MODE_HELPERS=y # CONFIG_FB_TILEBLITTING is not set # CONFIG_FB_CIRRUS is not set @@ -851,7 +906,6 @@ CONFIG_FB_MODE_HELPERS=y # CONFIG_FB_NVIDIA is not set # CONFIG_FB_RIVA is not set # CONFIG_FB_MATROX is not set -# CONFIG_FB_RADEON_OLD is not set CONFIG_FB_RADEON=y CONFIG_FB_RADEON_I2C=y CONFIG_FB_RADEON_DEBUG=y @@ -870,6 +924,7 @@ CONFIG_FB_RADEON_DEBUG=y # Console display driver support # CONFIG_VGA_CONSOLE=y +# CONFIG_VGACON_SOFT_SCROLLBACK is not set CONFIG_DUMMY_CONSOLE=y # CONFIG_FRAMEBUFFER_CONSOLE is not set @@ -900,9 +955,11 @@ CONFIG_SND_SEQUENCER=y CONFIG_SND_OSSEMUL=y CONFIG_SND_MIXER_OSS=y CONFIG_SND_PCM_OSS=y +CONFIG_SND_PCM_OSS_PLUGINS=y CONFIG_SND_SEQUENCER_OSS=y # CONFIG_SND_DYNAMIC_MINORS is not set CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set @@ -923,6 +980,7 @@ CONFIG_SND_AC97_BUS=y # PCI devices # # CONFIG_SND_AD1889 is not set +# CONFIG_SND_ALS300 is not set # CONFIG_SND_ALI5451 is not set # CONFIG_SND_ATIIXP is not set # CONFIG_SND_ATIIXP_MODEM is not set @@ -980,6 +1038,7 @@ CONFIG_SND_FM801=y # CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y CONFIG_USB=y # CONFIG_USB_DEBUG is not set @@ -998,6 +1057,7 @@ CONFIG_USB_BANDWIDTH=y CONFIG_USB_EHCI_HCD=y # CONFIG_USB_EHCI_SPLIT_ISO is not set # CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EHCI_TT_NEWSCHED is not set # CONFIG_USB_ISP116X_HCD is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_BIG_ENDIAN is not set @@ -1008,7 +1068,6 @@ CONFIG_USB_UHCI_HCD=y # # USB Device Class drivers # -# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set # CONFIG_USB_ACM is not set # CONFIG_USB_PRINTER is not set @@ -1044,9 +1103,7 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_ACECAD is not set # CONFIG_USB_KBTAB is not set # CONFIG_USB_POWERMATE is not set -# CONFIG_USB_MTOUCH is not set -# CONFIG_USB_ITMTOUCH is not set -# CONFIG_USB_EGALAX is not set +# CONFIG_USB_TOUCHSCREEN is not set # CONFIG_USB_YEALINK is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set @@ -1060,21 +1117,6 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set -# -# USB Multimedia devices -# -# CONFIG_USB_DABUSB is not set -# CONFIG_USB_VICAM is not set -# CONFIG_USB_DSBR is not set -# CONFIG_USB_ET61X251 is not set -# CONFIG_USB_IBMCAM is not set -# CONFIG_USB_KONICAWC is not set -# CONFIG_USB_OV511 is not set -# CONFIG_USB_SE401 is not set -# CONFIG_USB_SN9C102 is not set -# CONFIG_USB_STV680 is not set -# CONFIG_USB_PWC is not set - # # USB Network Adapters # @@ -1104,10 +1146,12 @@ CONFIG_USB_MON=y # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set # CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set # CONFIG_USB_PHIDGETKIT is not set # CONFIG_USB_PHIDGETSERVO is not set # CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set @@ -1125,6 +1169,19 @@ CONFIG_USB_MON=y # # CONFIG_MMC is not set +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + # # InfiniBand support # @@ -1134,6 +1191,24 @@ CONFIG_USB_MON=y # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) # +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + # # File systems # @@ -1157,6 +1232,7 @@ CONFIG_FS_MBCACHE=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=y @@ -1191,7 +1267,6 @@ CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y -# CONFIG_RELAYFS_FS is not set # CONFIG_CONFIGFS_FS is not set # @@ -1311,9 +1386,11 @@ CONFIG_NLS_UTF8=y # CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_PENDING_IRQ=y +CONFIG_IRQ_PER_CPU=y # # Instrumentation Support @@ -1326,14 +1403,19 @@ CONFIG_GENERIC_PENDING_IRQ=y # # CONFIG_PRINTK_TIME is not set CONFIG_MAGIC_SYSRQ=y +CONFIG_UNUSED_SYMBOLS=y CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=17 CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set -CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_RWSEMS is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_FS is not set @@ -1387,7 +1469,6 @@ CONFIG_CRYPTO_DES=y # # CONFIG_XEN_UTIL is not set CONFIG_XEN_BALLOON=y -# CONFIG_XEN_DEVMEM is not set CONFIG_XEN_REBOOT=y # CONFIG_XEN_SMPBOOT is not set CONFIG_XEN_INTERFACE_VERSION=0x00030203 @@ -1402,6 +1483,8 @@ CONFIG_XEN_XENBUS_DEV=y # CONFIG_XEN_BACKEND is not set CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_XEN_NETDEV_FRONTEND=y +CONFIG_XEN_FRAMEBUFFER=y +CONFIG_XEN_KEYBOARD=y # CONFIG_XEN_SCRUB_PAGES is not set # CONFIG_XEN_DISABLE_SERIAL is not set CONFIG_XEN_SYSFS=y @@ -1410,3 +1493,4 @@ CONFIG_XEN_COMPAT_030002_AND_LATER=y CONFIG_XEN_COMPAT_030002=y CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y CONFIG_NO_IDLE_HZ=y +CONFIG_XEN_DEVMEM=y diff --git a/buildconfigs/linux-defconfig_xen_ia64 b/buildconfigs/linux-defconfig_xen_ia64 index 3d8453e815..25253bc891 100644 --- a/buildconfigs/linux-defconfig_xen_ia64 +++ b/buildconfigs/linux-defconfig_xen_ia64 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16.29-xen -# Tue Nov 14 10:38:50 2006 +# Linux kernel version: 2.6.18-xen +# Mon Jan 29 10:01:13 2007 # # @@ -21,14 +21,16 @@ CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_BSD_PROCESS_ACCT=y # CONFIG_BSD_PROCESS_ACCT_V3 is not set -CONFIG_SYSCTL=y +# CONFIG_TASKSTATS is not set # CONFIG_AUDIT is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_CPUSETS is not set +# CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_EMBEDDED is not set +CONFIG_SYSCTL=y CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y CONFIG_KALLSYMS_EXTRA_PASS=y @@ -40,11 +42,9 @@ CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 # CONFIG_SLOB is not set @@ -55,7 +55,6 @@ CONFIG_BASE_SMALL=0 CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y @@ -64,6 +63,7 @@ CONFIG_STOP_MACHINE=y # # Block layer # +# CONFIG_BLK_DEV_IO_TRACE is not set # # IO Schedulers @@ -86,8 +86,10 @@ CONFIG_64BIT=y CONFIG_MMU=y CONFIG_SWIOTLB=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_TIME_INTERPOLATION=y +CONFIG_DMI=y CONFIG_EFI=y CONFIG_GENERIC_IOMAP=y CONFIG_XEN=y @@ -96,6 +98,7 @@ CONFIG_XEN_IA64_EXPOSE_P2M=y CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y CONFIG_DMA_IS_DMA32=y +CONFIG_AUDIT_ARCH=y # CONFIG_IA64_GENERIC is not set CONFIG_IA64_DIG=y # CONFIG_IA64_HP_ZX1 is not set @@ -123,6 +126,7 @@ CONFIG_NR_CPUS=16 CONFIG_HOTPLUG_CPU=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y # CONFIG_SCHED_SMT is not set +# CONFIG_PERMIT_BSP_REMOVE is not set # CONFIG_PREEMPT is not set CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y @@ -132,6 +136,7 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_RESOURCES_64BIT=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_DISCONTIGMEM_ENABLE=y CONFIG_ARCH_FLATMEM_ENABLE=y @@ -163,6 +168,7 @@ CONFIG_PM_LEGACY=y CONFIG_ACPI=y CONFIG_ACPI_BUTTON=y CONFIG_ACPI_FAN=y +# CONFIG_ACPI_DOCK is not set CONFIG_ACPI_PROCESSOR=y CONFIG_ACPI_HOTPLUG_CPU=y CONFIG_ACPI_THERMAL=y @@ -185,7 +191,7 @@ CONFIG_PCI=y CONFIG_PCI_DOMAINS=y CONFIG_XEN_PCIDEV_FRONTEND=y # CONFIG_XEN_PCIDEV_FE_DEBUG is not set -CONFIG_PCI_LEGACY_PROC=y +# CONFIG_PCIEPORTBUS is not set # CONFIG_PCI_DEBUG is not set # @@ -215,6 +221,8 @@ CONFIG_NET=y CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set # CONFIG_NET_KEY is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y @@ -229,7 +237,10 @@ CONFIG_SYN_COOKIES=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set @@ -240,6 +251,9 @@ CONFIG_TCP_CONG_BIC=y # # CONFIG_IP_VS is not set # CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set CONFIG_BRIDGE_NETFILTER=y @@ -280,12 +294,12 @@ CONFIG_BRIDGE_NETFILTER=y CONFIG_BRIDGE=y # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set +CONFIG_LLC=y # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -314,6 +328,7 @@ CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=y # CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set # # Connector - unified userspace <-> kernelspace linker @@ -352,6 +367,7 @@ CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 CONFIG_BLK_DEV_INITRD=y # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set @@ -463,6 +479,7 @@ CONFIG_SCSI_SAS_ATTRS=y # CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_SAS is not set # CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_HPTIOP is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_IPS is not set @@ -472,10 +489,8 @@ CONFIG_SCSI_SYM53C8XX_2=y CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 -# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +CONFIG_SCSI_SYM53C8XX_MMIO=y # CONFIG_SCSI_IPR is not set -CONFIG_SCSI_QLOGIC_FC=y -# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set CONFIG_SCSI_QLOGIC_1280=y # CONFIG_SCSI_QLA_FC is not set # CONFIG_SCSI_LPFC is not set @@ -613,6 +628,7 @@ CONFIG_TIGON3=y # CONFIG_CHELSIO_T1 is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set # # Token Ring devices @@ -715,6 +731,7 @@ CONFIG_GAMEPORT=y CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set CONFIG_SERIAL_NONSTANDARD=y # CONFIG_COMPUTONE is not set # CONFIG_ROCKETPORT is not set @@ -728,6 +745,7 @@ CONFIG_SERIAL_NONSTANDARD=y # CONFIG_N_HDLC is not set # CONFIG_SPECIALIX is not set # CONFIG_SX is not set +# CONFIG_RIO is not set # CONFIG_STALDRV is not set # @@ -761,6 +779,8 @@ CONFIG_EFI_RTC=y # Ftape, the floppy tape device driver # CONFIG_AGP=y +# CONFIG_AGP_SIS is not set +# CONFIG_AGP_VIA is not set CONFIG_AGP_I460=y CONFIG_DRM=y # CONFIG_DRM_TDFX is not set @@ -805,10 +825,10 @@ CONFIG_I2C_ALGOPCF=y # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_OCORES is not set # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PROSAVAGE is not set # CONFIG_I2C_SAVAGE4 is not set -# CONFIG_SCx200_ACB is not set # CONFIG_I2C_SIS5595 is not set # CONFIG_I2C_SIS630 is not set # CONFIG_I2C_SIS96X is not set @@ -827,9 +847,7 @@ CONFIG_I2C_ALGOPCF=y # CONFIG_SENSORS_PCF8574 is not set # CONFIG_SENSORS_PCA9539 is not set # CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set # CONFIG_SENSORS_MAX6875 is not set -# CONFIG_RTC_X1205_I2C is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set @@ -844,13 +862,13 @@ CONFIG_I2C_ALGOPCF=y # # Dallas's 1-wire bus # -# CONFIG_W1 is not set # # Hardware Monitoring support # CONFIG_HWMON=y # CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set @@ -879,10 +897,12 @@ CONFIG_HWMON=y # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set # CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_VT8231 is not set # CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set # CONFIG_SENSORS_W83792D is not set # CONFIG_SENSORS_W83L785TS is not set # CONFIG_SENSORS_W83627HF is not set @@ -893,25 +913,26 @@ CONFIG_HWMON=y # Misc devices # -# -# Multimedia Capabilities Port drivers -# - # # Multimedia devices # CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=y # -# Video For Linux +# Video Capture Adapters # # -# Video Adapters +# Video Capture Adapters # # CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_VIVI is not set # CONFIG_VIDEO_BT848 is not set # CONFIG_VIDEO_CPIA is not set +# CONFIG_VIDEO_CPIA2 is not set # CONFIG_VIDEO_SAA5246A is not set # CONFIG_VIDEO_SAA5249 is not set # CONFIG_TUNER_3036 is not set @@ -923,10 +944,40 @@ CONFIG_VIDEO_DEV=y # CONFIG_VIDEO_HEXIUM_ORION is not set # CONFIG_VIDEO_HEXIUM_GEMINI is not set # CONFIG_VIDEO_CX88 is not set + +# +# Encoders and Decoders +# +# CONFIG_VIDEO_MSP3400 is not set +# CONFIG_VIDEO_CS53L32A is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +# CONFIG_VIDEO_WM8775 is not set +# CONFIG_VIDEO_WM8739 is not set +# CONFIG_VIDEO_CX2341X is not set +# CONFIG_VIDEO_CX25840 is not set +# CONFIG_VIDEO_SAA711X is not set +# CONFIG_VIDEO_SAA7127 is not set +# CONFIG_VIDEO_UPD64031A is not set +# CONFIG_VIDEO_UPD64083 is not set + +# +# V4L USB devices +# +# CONFIG_VIDEO_PVRUSB2 is not set # CONFIG_VIDEO_EM28XX is not set +# CONFIG_USB_VICAM is not set +# CONFIG_USB_IBMCAM is not set +# CONFIG_USB_KONICAWC is not set +# CONFIG_USB_QUICKCAM_MESSENGER is not set +# CONFIG_USB_ET61X251 is not set # CONFIG_VIDEO_OVCAMCHIP is not set -# CONFIG_VIDEO_AUDIO_DECODER is not set -# CONFIG_VIDEO_DECODER is not set +# CONFIG_USB_W9968CF is not set +# CONFIG_USB_OV511 is not set +# CONFIG_USB_SE401 is not set +# CONFIG_USB_SN9C102 is not set +# CONFIG_USB_STV680 is not set +# CONFIG_USB_ZC0301 is not set +# CONFIG_USB_PWC is not set # # Radio Adapters @@ -934,20 +985,24 @@ CONFIG_VIDEO_DEV=y # CONFIG_RADIO_GEMTEK_PCI is not set # CONFIG_RADIO_MAXIRADIO is not set # CONFIG_RADIO_MAESTRO is not set +# CONFIG_USB_DSBR is not set # # Digital Video Broadcasting Devices # # CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set # # Graphics support # +CONFIG_FIRMWARE_EDID=y CONFIG_FB=y CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set CONFIG_FB_MODE_HELPERS=y # CONFIG_FB_TILEBLITTING is not set # CONFIG_FB_CIRRUS is not set @@ -959,7 +1014,6 @@ CONFIG_FB_MODE_HELPERS=y # CONFIG_FB_NVIDIA is not set # CONFIG_FB_RIVA is not set # CONFIG_FB_MATROX is not set -# CONFIG_FB_RADEON_OLD is not set CONFIG_FB_RADEON=y CONFIG_FB_RADEON_I2C=y CONFIG_FB_RADEON_DEBUG=y @@ -978,6 +1032,7 @@ CONFIG_FB_RADEON_DEBUG=y # Console display driver support # CONFIG_VGA_CONSOLE=y +# CONFIG_VGACON_SOFT_SCROLLBACK is not set CONFIG_DUMMY_CONSOLE=y # CONFIG_FRAMEBUFFER_CONSOLE is not set @@ -1008,9 +1063,11 @@ CONFIG_SND_SEQ_DUMMY=y CONFIG_SND_OSSEMUL=y CONFIG_SND_MIXER_OSS=y CONFIG_SND_PCM_OSS=y +CONFIG_SND_PCM_OSS_PLUGINS=y CONFIG_SND_SEQUENCER_OSS=y # CONFIG_SND_DYNAMIC_MINORS is not set CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set @@ -1031,6 +1088,7 @@ CONFIG_SND_MPU401=y # PCI devices # # CONFIG_SND_AD1889 is not set +# CONFIG_SND_ALS300 is not set # CONFIG_SND_ALI5451 is not set CONFIG_SND_ATIIXP=y # CONFIG_SND_ATIIXP_MODEM is not set @@ -1043,6 +1101,18 @@ CONFIG_SND_ATIIXP=y # CONFIG_SND_CMIPCI is not set # CONFIG_SND_CS4281 is not set # CONFIG_SND_CS46XX is not set +# CONFIG_SND_DARLA20 is not set +# CONFIG_SND_GINA20 is not set +# CONFIG_SND_LAYLA20 is not set +# CONFIG_SND_DARLA24 is not set +# CONFIG_SND_GINA24 is not set +# CONFIG_SND_LAYLA24 is not set +# CONFIG_SND_MONA is not set +# CONFIG_SND_MIA is not set +# CONFIG_SND_ECHO3G is not set +# CONFIG_SND_INDIGO is not set +# CONFIG_SND_INDIGOIO is not set +# CONFIG_SND_INDIGODJ is not set # CONFIG_SND_EMU10K1 is not set # CONFIG_SND_EMU10K1X is not set # CONFIG_SND_ENS1370 is not set @@ -1063,6 +1133,7 @@ CONFIG_SND_FM801=y # CONFIG_SND_MIXART is not set # CONFIG_SND_NM256 is not set # CONFIG_SND_PCXHR is not set +# CONFIG_SND_RIPTIDE is not set # CONFIG_SND_RME32 is not set # CONFIG_SND_RME96 is not set # CONFIG_SND_RME9652 is not set @@ -1082,12 +1153,14 @@ CONFIG_SND_FM801=y # Open Sound System # CONFIG_SOUND_PRIME=y -# CONFIG_OBSOLETE_OSS_DRIVER is not set -# CONFIG_SOUND_FUSION is not set +# CONFIG_OSS_OBSOLETE_DRIVER is not set +# CONFIG_SOUND_BT878 is not set +# CONFIG_SOUND_ES1371 is not set # CONFIG_SOUND_ICH is not set # CONFIG_SOUND_TRIDENT is not set # CONFIG_SOUND_MSNDCLAS is not set # CONFIG_SOUND_MSNDPIN is not set +# CONFIG_SOUND_VIA82CXXX is not set # CONFIG_SOUND_TVMIXER is not set # @@ -1095,6 +1168,7 @@ CONFIG_SOUND_PRIME=y # CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y CONFIG_USB=y # CONFIG_USB_DEBUG is not set @@ -1113,6 +1187,7 @@ CONFIG_USB_BANDWIDTH=y CONFIG_USB_EHCI_HCD=y # CONFIG_USB_EHCI_SPLIT_ISO is not set # CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EHCI_TT_NEWSCHED is not set # CONFIG_USB_ISP116X_HCD is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_BIG_ENDIAN is not set @@ -1123,7 +1198,6 @@ CONFIG_USB_UHCI_HCD=y # # USB Device Class drivers # -# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set # CONFIG_USB_ACM is not set # CONFIG_USB_PRINTER is not set @@ -1160,9 +1234,7 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_ACECAD is not set # CONFIG_USB_KBTAB is not set # CONFIG_USB_POWERMATE is not set -# CONFIG_USB_MTOUCH is not set -# CONFIG_USB_ITMTOUCH is not set -# CONFIG_USB_EGALAX is not set +# CONFIG_USB_TOUCHSCREEN is not set # CONFIG_USB_YEALINK is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set @@ -1176,21 +1248,6 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set -# -# USB Multimedia devices -# -# CONFIG_USB_DABUSB is not set -# CONFIG_USB_VICAM is not set -# CONFIG_USB_DSBR is not set -# CONFIG_USB_ET61X251 is not set -# CONFIG_USB_IBMCAM is not set -# CONFIG_USB_KONICAWC is not set -# CONFIG_USB_OV511 is not set -# CONFIG_USB_SE401 is not set -# CONFIG_USB_SN9C102 is not set -# CONFIG_USB_STV680 is not set -# CONFIG_USB_PWC is not set - # # USB Network Adapters # @@ -1220,10 +1277,12 @@ CONFIG_USB_MON=y # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set # CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set # CONFIG_USB_PHIDGETKIT is not set # CONFIG_USB_PHIDGETSERVO is not set # CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set # CONFIG_USB_TEST is not set @@ -1242,6 +1301,19 @@ CONFIG_USB_MON=y # # CONFIG_MMC is not set +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + # # InfiniBand support # @@ -1251,6 +1323,24 @@ CONFIG_USB_MON=y # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) # +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + # # File systems # @@ -1275,7 +1365,6 @@ CONFIG_REISERFS_FS_SECURITY=y # CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y CONFIG_XFS_FS=y -CONFIG_XFS_EXPORT=y # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_SECURITY is not set # CONFIG_XFS_POSIX_ACL is not set @@ -1284,6 +1373,7 @@ CONFIG_XFS_EXPORT=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=y @@ -1318,7 +1408,6 @@ CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y -# CONFIG_RELAYFS_FS is not set # CONFIG_CONFIGFS_FS is not set # @@ -1364,7 +1453,9 @@ CONFIG_SMB_NLS_DEFAULT=y CONFIG_SMB_NLS_REMOTE="cp437" CONFIG_CIFS=y # CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_WEAK_PW_HASH is not set # CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_DEBUG2 is not set # CONFIG_CIFS_EXPERIMENTAL is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1443,9 +1534,11 @@ CONFIG_NLS_UTF8=y # CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_PENDING_IRQ=y +CONFIG_IRQ_PER_CPU=y # # Instrumentation Support @@ -1458,14 +1551,19 @@ CONFIG_GENERIC_PENDING_IRQ=y # # CONFIG_PRINTK_TIME is not set CONFIG_MAGIC_SYSRQ=y +CONFIG_UNUSED_SYMBOLS=y CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=20 CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set -CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_RWSEMS is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_FS is not set @@ -1519,7 +1617,6 @@ CONFIG_CRYPTO_DES=y # # CONFIG_XEN_UTIL is not set CONFIG_XEN_BALLOON=y -# CONFIG_XEN_DEVMEM is not set CONFIG_XEN_REBOOT=y # CONFIG_XEN_SMPBOOT is not set CONFIG_XEN_INTERFACE_VERSION=0x00030203 @@ -1555,3 +1652,4 @@ CONFIG_XEN_COMPAT_030002_AND_LATER=y CONFIG_XEN_COMPAT_030002=y CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y CONFIG_NO_IDLE_HZ=y +CONFIG_XEN_DEVMEM=y diff --git a/extras/mini-os/gnttab.c b/extras/mini-os/gnttab.c index da92fc33c9..4d75897a98 100644 --- a/extras/mini-os/gnttab.c +++ b/extras/mini-os/gnttab.c @@ -21,7 +21,12 @@ #define NR_RESERVED_ENTRIES 8 +/* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */ +#ifdef __ia64__ +#define NR_GRANT_FRAMES 1 +#else #define NR_GRANT_FRAMES 4 +#endif #define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t)) static grant_entry_t *gnttab_table; diff --git a/extras/mini-os/netfront.c b/extras/mini-os/netfront.c index 4c10dc8770..088f67a3bb 100644 --- a/extras/mini-os/netfront.c +++ b/extras/mini-os/netfront.c @@ -349,7 +349,9 @@ done: init_rx_buffers(); unsigned char rawmac[6]; - sscanf(mac,"%x:%x:%x:%x:%x:%x", + /* Special conversion specifier 'hh' needed for __ia64__. Without + this mini-os panics with 'Unaligned reference'. */ + sscanf(mac,"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &rawmac[0], &rawmac[1], &rawmac[2], diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S b/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S index 9d10f5c573..ab569d974b 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S +++ b/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S @@ -747,7 +747,7 @@ ENTRY(hypervisor_callback) jb 11f cmpl $sysexit_ecrit,%eax ja 11f - addl $0x34,%esp # Remove cs...ebx from stack frame. + addl $OLDESP,%esp # Remove eflags...ebx from stack frame. 11: push %esp call evtchn_do_upcall add $4,%esp @@ -777,18 +777,13 @@ ecrit: /**** END OF CRITICAL REGION ****/ # provides the number of bytes which have already been popped from the # interrupted stack frame. critical_region_fixup: - addl $critical_fixup_table-scrit,%eax - movzbl (%eax),%eax # %eax contains num bytes popped - cmpb $0xff,%al # 0xff => vcpu_info critical region + movzbl critical_fixup_table-scrit(%eax),%ecx # %eax contains num bytes popped + cmpb $0xff,%cl # 0xff => vcpu_info critical region jne 15f - GET_THREAD_INFO(%ebp) - xorl %eax,%eax -15: mov %esp,%esi - add %eax,%esi # %esi points at end of src region - mov %esp,%edi - add $0x34,%edi # %edi points at end of dst region - mov %eax,%ecx - shr $2,%ecx # convert words to bytes + xorl %ecx,%ecx +15: leal (%esp,%ecx),%esi # %esi points at end of src region + leal OLDESP(%esp),%edi # %edi points at end of dst region + shrl $2,%ecx # convert words to bytes je 17f # skip loop if nothing to copy 16: subl $4,%esi # pre-decrementing copy loop subl $4,%edi @@ -798,6 +793,7 @@ critical_region_fixup: 17: movl %edi,%esp # final %edi is top of merged stack jmp 11b +.section .rodata,"a" critical_fixup_table: .byte 0xff,0xff,0xff # testb $0xff,(%esi) = __TEST_PENDING .byte 0xff,0xff # jnz 14f @@ -814,6 +810,7 @@ critical_fixup_table: .byte 0x28 # iret .byte 0xff,0xff,0xff,0xff # movb $1,1(%esi) .byte 0x00,0x00 # jmp 11b +.previous # Hypervisor uses this for application faults while it executes. # We get here for two reasons: @@ -1194,6 +1191,7 @@ ENTRY(fixup_4gb_segment) jmp error_code .section .rodata,"a" +.align 4 #include "syscall_table.S" syscall_table_size=(.-sys_call_table) diff --git a/linux-2.6-xen-sparse/arch/ia64/kernel/irq_ia64.c b/linux-2.6-xen-sparse/arch/ia64/kernel/irq_ia64.c index 954a462eea..8524560326 100644 --- a/linux-2.6-xen-sparse/arch/ia64/kernel/irq_ia64.c +++ b/linux-2.6-xen-sparse/arch/ia64/kernel/irq_ia64.c @@ -319,81 +319,85 @@ static struct irqaction resched_irqaction = { * required. */ static void -xen_register_percpu_irq (unsigned int irq, struct irqaction *action, int save) +xen_register_percpu_irq (unsigned int vec, struct irqaction *action, int save) { unsigned int cpu = smp_processor_id(); - int ret = 0; + irq_desc_t *desc; + int irq = 0; if (xen_slab_ready) { - switch (irq) { + switch (vec) { case IA64_TIMER_VECTOR: sprintf(timer_name[cpu], "%s%d", action->name, cpu); - ret = bind_virq_to_irqhandler(VIRQ_ITC, cpu, + irq = bind_virq_to_irqhandler(VIRQ_ITC, cpu, action->handler, action->flags, timer_name[cpu], action->dev_id); - per_cpu(timer_irq,cpu) = ret; - printk(KERN_INFO "register VIRQ_ITC (%s) to xen irq (%d)\n", timer_name[cpu], ret); + per_cpu(timer_irq,cpu) = irq; break; case IA64_IPI_RESCHEDULE: sprintf(resched_name[cpu], "%s%d", action->name, cpu); - ret = bind_ipi_to_irqhandler(RESCHEDULE_VECTOR, cpu, + irq = bind_ipi_to_irqhandler(RESCHEDULE_VECTOR, cpu, action->handler, action->flags, resched_name[cpu], action->dev_id); - per_cpu(resched_irq,cpu) = ret; - printk(KERN_INFO "register RESCHEDULE_VECTOR (%s) to xen irq (%d)\n", resched_name[cpu], ret); + per_cpu(resched_irq,cpu) = irq; break; case IA64_IPI_VECTOR: sprintf(ipi_name[cpu], "%s%d", action->name, cpu); - ret = bind_ipi_to_irqhandler(IPI_VECTOR, cpu, + irq = bind_ipi_to_irqhandler(IPI_VECTOR, cpu, action->handler, action->flags, ipi_name[cpu], action->dev_id); - per_cpu(ipi_irq,cpu) = ret; - printk(KERN_INFO "register IPI_VECTOR (%s) to xen irq (%d)\n", ipi_name[cpu], ret); - break; - case IA64_SPURIOUS_INT_VECTOR: + per_cpu(ipi_irq,cpu) = irq; break; case IA64_CMC_VECTOR: sprintf(cmc_name[cpu], "%s%d", action->name, cpu); - ret = bind_virq_to_irqhandler(VIRQ_MCA_CMC, cpu, + irq = bind_virq_to_irqhandler(VIRQ_MCA_CMC, cpu, action->handler, action->flags, cmc_name[cpu], action->dev_id); - per_cpu(cmc_irq,cpu) = ret; - printk(KERN_INFO "register VIRQ_MCA_CMC (%s) to xen " - "irq (%d)\n", cmc_name[cpu], ret); + per_cpu(cmc_irq,cpu) = irq; break; case IA64_CMCP_VECTOR: sprintf(cmcp_name[cpu], "%s%d", action->name, cpu); - ret = bind_ipi_to_irqhandler(CMCP_VECTOR, cpu, + irq = bind_ipi_to_irqhandler(CMCP_VECTOR, cpu, action->handler, action->flags, cmcp_name[cpu], action->dev_id); - per_cpu(cmcp_irq,cpu) = ret; - printk(KERN_INFO "register CMCP_VECTOR (%s) to xen " - "irq (%d)\n", cmcp_name[cpu], ret); + per_cpu(cmcp_irq,cpu) = irq; break; case IA64_CPEP_VECTOR: sprintf(cpep_name[cpu], "%s%d", action->name, cpu); - ret = bind_ipi_to_irqhandler(CPEP_VECTOR, cpu, + irq = bind_ipi_to_irqhandler(CPEP_VECTOR, cpu, action->handler, action->flags, cpep_name[cpu], action->dev_id); - per_cpu(cpep_irq,cpu) = ret; - printk(KERN_INFO "register CPEP_VECTOR (%s) to xen " - "irq (%d)\n", cpep_name[cpu], ret); + per_cpu(cpep_irq,cpu) = irq; break; case IA64_CPE_VECTOR: - printk(KERN_WARNING "register IA64_CPE_VECTOR " - "IGNORED\n"); + case IA64_MCA_RENDEZ_VECTOR: + case IA64_PERFMON_VECTOR: + case IA64_MCA_WAKEUP_VECTOR: + case IA64_SPURIOUS_INT_VECTOR: + /* No need to complain, these aren't supported. */ break; default: - printk(KERN_WARNING "Percpu irq %d is unsupported by xen!\n", irq); + printk(KERN_WARNING "Percpu irq %d is unsupported " + "by xen!\n", vec); break; } - BUG_ON(ret < 0); + BUG_ON(irq < 0); + + if (irq > 0) { + /* + * Mark percpu. Without this, migrate_irqs() will + * mark the interrupt for migrations and trigger it + * on cpu hotplug. + */ + desc = irq_desc + irq; + desc->status |= IRQ_PER_CPU; + } } /* For BSP, we cache registered percpu irqs, and then re-walk @@ -401,7 +405,7 @@ xen_register_percpu_irq (unsigned int irq, struct irqaction *action, int save) */ if (!cpu && save) { BUG_ON(saved_irq_cnt == MAX_LATE_IRQ); - saved_percpu_irqs[saved_irq_cnt].irq = irq; + saved_percpu_irqs[saved_irq_cnt].irq = vec; saved_percpu_irqs[saved_irq_cnt].action = action; saved_irq_cnt++; if (!xen_slab_ready) @@ -588,7 +592,8 @@ ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect) irq = per_cpu(ipi_to_irq, cpu)[CPEP_VECTOR]; break; default: - printk(KERN_WARNING"Unsupported IPI type 0x%x\n", vector); + printk(KERN_WARNING "Unsupported IPI type 0x%x\n", + vector); irq = 0; break; } diff --git a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c index c2699f43e1..1fd352463c 100644 --- a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c +++ b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c @@ -63,6 +63,7 @@ #ifdef CONFIG_XEN #include #include +#include #endif #include @@ -95,6 +96,12 @@ xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr) static struct notifier_block xen_panic_block = { xen_panic_event, NULL, 0 /* try to go last */ }; + +void xen_pm_power_off(void) +{ + local_irq_disable(); + HYPERVISOR_shutdown(SHUTDOWN_poweroff); +} #endif extern void ia64_setup_printk_clock(void); @@ -454,7 +461,9 @@ setup_arch (char **cmdline_p) setup_xen_features(); /* Register a call for panic conditions. */ - notifier_chain_register(&panic_notifier_list, &xen_panic_block); + atomic_notifier_chain_register(&panic_notifier_list, + &xen_panic_block); + pm_power_off = xen_pm_power_off; } #endif diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c b/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c index f65cf94ee1..695dc3bce5 100644 --- a/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c +++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c @@ -416,12 +416,6 @@ HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count) } EXPORT_SYMBOL(HYPERVISOR_grant_table_op); -/////////////////////////////////////////////////////////////////////////// -// PageForeign(), SetPageForeign(), ClearPageForeign() - -struct address_space xen_ia64_foreign_dummy_mapping; -EXPORT_SYMBOL(xen_ia64_foreign_dummy_mapping); - /////////////////////////////////////////////////////////////////////////// // foreign mapping #include diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/xenentry.S b/linux-2.6-xen-sparse/arch/ia64/xen/xenentry.S index f0a75468fa..08bd970460 100644 --- a/linux-2.6-xen-sparse/arch/ia64/xen/xenentry.S +++ b/linux-2.6-xen-sparse/arch/ia64/xen/xenentry.S @@ -124,6 +124,8 @@ GLOBAL_ENTRY(ia64_switch_to) ;; itr.d dtr[r25]=r23 // wire in new mapping... #ifdef CONFIG_XEN + ;; + srlz.d mov r9=1 movl r8=XSI_PSR_IC ;; @@ -875,9 +877,6 @@ skip_rbs_switch: st8 [r2]=r8 st8 [r3]=r10 .work_pending: - tbit.nz p6,p0=r31,TIF_SIGDELAYED // signal delayed from MCA/INIT/NMI/PMI context? -(p6) br.cond.sptk.few .sigdelayed - ;; tbit.z p6,p0=r31,TIF_NEED_RESCHED // current_thread_info()->need_resched==0? (p6) br.cond.sptk.few .notify #ifdef CONFIG_PREEMPT @@ -913,17 +912,6 @@ skip_rbs_switch: (pLvSys)br.cond.sptk.few .work_pending_syscall_end br.cond.sptk.many .work_processed_kernel // don't re-check -// There is a delayed signal that was detected in MCA/INIT/NMI/PMI context where -// it could not be delivered. Deliver it now. The signal might be for us and -// may set TIF_SIGPENDING, so redrive ia64_leave_* after processing the delayed -// signal. - -.sigdelayed: - br.call.sptk.many rp=do_sigdelayed - cmp.eq p6,p0=r0,r0 // p6 <- 1, always re-check -(pLvSys)br.cond.sptk.few .work_pending_syscall_end - br.cond.sptk.many .work_processed_kernel // re-check - .work_pending_syscall_end: adds r2=PT(R8)+16,r12 adds r3=PT(R10)+16,r12 diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c index 0d9b5e34b4..3c89453030 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c @@ -344,7 +344,7 @@ static void frontend_changed(struct xenbus_device *dev, switch (frontend_state) { case XenbusStateInitialising: if (dev->state == XenbusStateClosed) { - printk("%s: %s: prepare for reconnect\n", + printk(KERN_INFO "%s: %s: prepare for reconnect\n", __FUNCTION__, dev->nodename); xenbus_switch_state(dev, XenbusStateInitWait); } @@ -488,7 +488,8 @@ static int connect_ring(struct backend_info *be) xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol); return -1; } - printk("blkback: ring-ref %ld, event-channel %d, protocol %d (%s)\n", + printk(KERN_INFO + "blkback: ring-ref %ld, event-channel %d, protocol %d (%s)\n", ring_ref, evtchn, be->blkif->blk_protocol, protocol); /* Map the shared frame, irq etc. */ diff --git a/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c index 58a79e7e4d..3f3344b3bd 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c @@ -272,7 +272,7 @@ static void tap_frontend_changed(struct xenbus_device *dev, switch (frontend_state) { case XenbusStateInitialising: if (dev->state == XenbusStateClosed) { - printk("%s: %s: prepare for reconnect\n", + printk(KERN_INFO "%s: %s: prepare for reconnect\n", __FUNCTION__, dev->nodename); xenbus_switch_state(dev, XenbusStateInitWait); } @@ -369,7 +369,8 @@ static int connect_ring(struct backend_info *be) xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol); return -1; } - printk("blktap: ring-ref %ld, event-channel %d, protocol %d (%s)\n", + printk(KERN_INFO + "blktap: ring-ref %ld, event-channel %d, protocol %d (%s)\n", ring_ref, evtchn, be->blkif->blk_protocol, protocol); /* Map the shared frame, irq etc. */ diff --git a/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c b/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c index 51436b69cc..3e66f3be45 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c @@ -424,7 +424,7 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) static void unbind_from_irq(unsigned int irq) { struct evtchn_close close; - int evtchn = evtchn_from_irq(irq); + int cpu, evtchn = evtchn_from_irq(irq); spin_lock(&irq_mapping_update_lock); @@ -452,6 +452,10 @@ static void unbind_from_irq(unsigned int irq) evtchn_to_irq[evtchn] = -1; irq_info[irq] = IRQ_UNBOUND; + + /* Zap stats across IRQ changes of use. */ + for_each_possible_cpu(cpu) + kstat_cpu(cpu).irqs[irq] = 0; } spin_unlock(&irq_mapping_update_lock); diff --git a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c index af3fe3a15c..aab244a738 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c @@ -100,6 +100,7 @@ static void __shutdown_handler(void *unused) static void shutdown_handler(struct xenbus_watch *watch, const char **vec, unsigned int len) { + extern void ctrl_alt_del(void); char *str; struct xenbus_transaction xbt; int err; @@ -129,7 +130,7 @@ static void shutdown_handler(struct xenbus_watch *watch, if (strcmp(str, "poweroff") == 0) shutting_down = SHUTDOWN_POWEROFF; else if (strcmp(str, "reboot") == 0) - kill_proc(1, SIGINT, 1); /* interrupt init */ + ctrl_alt_del(); else if (strcmp(str, "suspend") == 0) shutting_down = SHUTDOWN_SUSPEND; else if (strcmp(str, "halt") == 0) diff --git a/linux-2.6-xen-sparse/drivers/xen/fbfront/xenkbd.c b/linux-2.6-xen-sparse/drivers/xen/fbfront/xenkbd.c index e4debd83d3..a34beafcda 100644 --- a/linux-2.6-xen-sparse/drivers/xen/fbfront/xenkbd.c +++ b/linux-2.6-xen-sparse/drivers/xen/fbfront/xenkbd.c @@ -29,10 +29,12 @@ struct xenkbd_info { - struct input_dev *dev; + struct input_dev *kbd; + struct input_dev *ptr; struct xenkbd_page *page; int irq; struct xenbus_device *xbdev; + char phys[32]; }; static int xenkbd_remove(struct xenbus_device *); @@ -56,23 +58,36 @@ static irqreturn_t input_handler(int rq, void *dev_id, struct pt_regs *regs) rmb(); /* ensure we see ring contents up to prod */ for (cons = page->in_cons; cons != prod; cons++) { union xenkbd_in_event *event; + struct input_dev *dev; event = &XENKBD_IN_RING_REF(page, cons); + dev = info->ptr; switch (event->type) { case XENKBD_TYPE_MOTION: - input_report_rel(info->dev, REL_X, event->motion.rel_x); - input_report_rel(info->dev, REL_Y, event->motion.rel_y); + input_report_rel(dev, REL_X, event->motion.rel_x); + input_report_rel(dev, REL_Y, event->motion.rel_y); break; case XENKBD_TYPE_KEY: - input_report_key(info->dev, event->key.keycode, event->key.pressed); + dev = NULL; + if (test_bit(event->key.keycode, info->kbd->keybit)) + dev = info->kbd; + if (test_bit(event->key.keycode, info->ptr->keybit)) + dev = info->ptr; + if (dev) + input_report_key(dev, event->key.keycode, + event->key.pressed); + else + printk("xenkbd: unhandled keycode 0x%x\n", + event->key.keycode); break; case XENKBD_TYPE_POS: - input_report_abs(info->dev, ABS_X, event->pos.abs_x); - input_report_abs(info->dev, ABS_Y, event->pos.abs_y); + input_report_abs(dev, ABS_X, event->pos.abs_x); + input_report_abs(dev, ABS_Y, event->pos.abs_y); break; } + if (dev) + input_sync(dev); } - input_sync(info->dev); mb(); /* ensure we got ring contents */ page->in_cons = cons; notify_remote_via_irq(info->irq); @@ -85,7 +100,7 @@ int __devinit xenkbd_probe(struct xenbus_device *dev, { int ret, i; struct xenkbd_info *info; - struct input_dev *input_dev; + struct input_dev *kbd, *ptr; info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) { @@ -94,6 +109,7 @@ int __devinit xenkbd_probe(struct xenbus_device *dev, } dev->dev.driver_data = info; info->xbdev = dev; + snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename); info->page = (void *)__get_free_page(GFP_KERNEL); if (!info->page) @@ -101,32 +117,52 @@ int __devinit xenkbd_probe(struct xenbus_device *dev, info->page->in_cons = info->page->in_prod = 0; info->page->out_cons = info->page->out_prod = 0; - input_dev = input_allocate_device(); - if (!input_dev) + /* keyboard */ + kbd = input_allocate_device(); + if (!kbd) goto error_nomem; + kbd->name = "Xen Virtual Keyboard"; + kbd->phys = info->phys; + kbd->id.bustype = BUS_PCI; + kbd->id.vendor = 0x5853; + kbd->id.product = 0xffff; + kbd->evbit[0] = BIT(EV_KEY); + for (i = KEY_ESC; i < KEY_UNKNOWN; i++) + set_bit(i, kbd->keybit); + for (i = KEY_OK; i < KEY_MAX; i++) + set_bit(i, kbd->keybit); - input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS); - input_dev->keybit[LONG(BTN_MOUSE)] - = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); - /* TODO additional buttons */ - input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y); - - /* FIXME not sure this is quite right */ - for (i = 0; i < 256; i++) - set_bit(i, input_dev->keybit); - - input_dev->name = "Xen Virtual Keyboard/Mouse"; - - input_set_abs_params(input_dev, ABS_X, 0, XENFB_WIDTH, 0, 0); - input_set_abs_params(input_dev, ABS_Y, 0, XENFB_HEIGHT, 0, 0); - - ret = input_register_device(input_dev); + ret = input_register_device(kbd); if (ret) { - input_free_device(input_dev); - xenbus_dev_fatal(dev, ret, "input_register_device"); + input_free_device(kbd); + xenbus_dev_fatal(dev, ret, "input_register_device(kbd)"); goto error; } - info->dev = input_dev; + info->kbd = kbd; + + /* pointing device */ + ptr = input_allocate_device(); + if (!ptr) + goto error_nomem; + ptr->name = "Xen Virtual Pointer"; + ptr->phys = info->phys; + ptr->id.bustype = BUS_PCI; + ptr->id.vendor = 0x5853; + ptr->id.product = 0xfffe; + ptr->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS); + for (i = BTN_LEFT; i <= BTN_TASK; i++) + set_bit(i, ptr->keybit); + ptr->relbit[0] = BIT(REL_X) | BIT(REL_Y); + input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0); + input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0); + + ret = input_register_device(ptr); + if (ret) { + input_free_device(ptr); + xenbus_dev_fatal(dev, ret, "input_register_device(ptr)"); + goto error; + } + info->ptr = ptr; ret = xenkbd_connect_backend(dev, info); if (ret < 0) @@ -155,7 +191,8 @@ static int xenkbd_remove(struct xenbus_device *dev) struct xenkbd_info *info = dev->dev.driver_data; xenkbd_disconnect_backend(info); - input_unregister_device(info->dev); + input_unregister_device(info->kbd); + input_unregister_device(info->ptr); free_page((unsigned long)info->page); kfree(info); return 0; diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c index 7d301965f4..12a3dc26f8 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c @@ -217,7 +217,7 @@ static void frontend_changed(struct xenbus_device *dev, switch (frontend_state) { case XenbusStateInitialising: if (dev->state == XenbusStateClosed) { - printk("%s: %s: prepare for reconnect\n", + printk(KERN_INFO "%s: %s: prepare for reconnect\n", __FUNCTION__, dev->nodename); if (be->netif) { netif_disconnect(be->netif); diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c index bd86948fed..80d1a3e995 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c @@ -1505,7 +1505,7 @@ static void netif_release_rx_bufs(struct netfront_info *np) int id, ref; if (np->copying_receiver) { - printk("%s: fix me for copying receiver.\n", __FUNCTION__); + WPRINTK("%s: fix me for copying receiver.\n", __FUNCTION__); return; } @@ -1555,8 +1555,8 @@ static void netif_release_rx_bufs(struct netfront_info *np) xfer++; } - printk("%s: %d xfer, %d noxfer, %d unused\n", - __FUNCTION__, xfer, noxfer, unused); + IPRINTK("%s: %d xfer, %d noxfer, %d unused\n", + __FUNCTION__, xfer, noxfer, unused); if (xfer) { /* Some pages are no longer absent... */ diff --git a/linux-2.6-xen-sparse/include/asm-i386/a.out.h b/linux-2.6-xen-sparse/include/asm-i386/a.out.h deleted file mode 100644 index 66db22938f..0000000000 --- a/linux-2.6-xen-sparse/include/asm-i386/a.out.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef __I386_A_OUT_H__ -#define __I386_A_OUT_H__ - -struct exec -{ - unsigned long a_info; /* Use macros N_MAGIC, etc for access */ - unsigned a_text; /* length of text, in bytes */ - unsigned a_data; /* length of data, in bytes */ - unsigned a_bss; /* length of uninitialized data area for file, in bytes */ - unsigned a_syms; /* length of symbol table data in file, in bytes */ - unsigned a_entry; /* start address */ - unsigned a_trsize; /* length of relocation info for text, in bytes */ - unsigned a_drsize; /* length of relocation info for data, in bytes */ -}; - -#define N_TRSIZE(a) ((a).a_trsize) -#define N_DRSIZE(a) ((a).a_drsize) -#define N_SYMSIZE(a) ((a).a_syms) - -#ifdef __KERNEL__ - -#define STACK_TOP (TASK_SIZE - 3*PAGE_SIZE) - -#endif - -#endif /* __A_OUT_GNU_H__ */ diff --git a/linux-2.6-xen-sparse/include/asm-ia64/hw_irq.h b/linux-2.6-xen-sparse/include/asm-ia64/hw_irq.h index 6369480485..922184d514 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/hw_irq.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/hw_irq.h @@ -104,10 +104,9 @@ extern void register_percpu_irq (ia64_vector vec, struct irqaction *action); static inline void ia64_resend_irq(unsigned int vector) { #ifdef CONFIG_XEN - extern void resend_irq_on_evtchn(struct hw_interrupt_type *h, - unsigned int i); + extern int resend_irq_on_evtchn(unsigned int i); if (is_running_on_xen()) - resend_irq_on_evtchn(h, vector); + resend_irq_on_evtchn(vector); else #endif /* CONFIG_XEN */ platform_send_ipi(smp_processor_id(), vector, IA64_IPI_DM_INT, 0); diff --git a/linux-2.6-xen-sparse/include/asm-ia64/maddr.h b/linux-2.6-xen-sparse/include/asm-ia64/maddr.h index cacad452d8..c43348f26a 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/maddr.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/maddr.h @@ -84,9 +84,6 @@ mfn_to_local_pfn(unsigned long mfn) #endif /* !CONFIG_XEN */ -/* XXX to compile set_phys_to_machine(vaddr, FOREIGN_FRAME(m)) */ -#define FOREIGN_FRAME(m) (INVALID_P2M_ENTRY) - #define mfn_to_pfn(mfn) (mfn) #define pfn_to_mfn(pfn) (pfn) diff --git a/linux-2.6-xen-sparse/include/asm-ia64/page.h b/linux-2.6-xen-sparse/include/asm-ia64/page.h index e8ad9ec4ee..c4b69c9e8e 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/page.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/page.h @@ -236,46 +236,17 @@ get_order (unsigned long size) #include #include #include // to compile netback, netfront +#include -/* - * XXX hack! - * Linux/IA64 uses PG_arch_1. - * This hack will be removed once PG_foreign bit is taken. - * #include - */ -#ifdef __ASM_XEN_FOREIGN_PAGE_H__ -# error "don't include include/xen/foreign_page.h!" -#endif - -extern struct address_space xen_ia64_foreign_dummy_mapping; -#define PageForeign(page) \ - ((page)->mapping == &xen_ia64_foreign_dummy_mapping) - -#define SetPageForeign(page, dtor) do { \ - set_page_private((page), (unsigned long)(dtor)); \ - (page)->mapping = &xen_ia64_foreign_dummy_mapping; \ - smp_rmb(); \ -} while (0) - -#define ClearPageForeign(page) do { \ - (page)->mapping = NULL; \ - smp_rmb(); \ - set_page_private((page), 0); \ -} while (0) - -#define PageForeignDestructor(page) \ - ( (void (*) (struct page *)) page_private(page) ) - -#define arch_free_page(_page,_order) \ -({ int foreign = PageForeign(_page); \ - if (foreign) \ - (PageForeignDestructor(_page))(_page); \ - foreign; \ +#define arch_free_page(_page, _order) \ +({ \ + int foreign = PageForeign(_page); \ + if (foreign) \ + PageForeignDestructor(_page); \ + foreign; \ }) #define HAVE_ARCH_FREE_PAGE -#include - #endif /* CONFIG_XEN */ #endif /* __ASSEMBLY__ */ diff --git a/linux-2.6-xen-sparse/net/core/skbuff.c b/linux-2.6-xen-sparse/net/core/skbuff.c index e7bbe91b8f..c8e7259cc0 100644 --- a/linux-2.6-xen-sparse/net/core/skbuff.c +++ b/linux-2.6-xen-sparse/net/core/skbuff.c @@ -1896,6 +1896,29 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb, return 0; } +/** + * skb_pull_rcsum - pull skb and update receive checksum + * @skb: buffer to update + * @start: start of data before pull + * @len: length of data pulled + * + * This function performs an skb_pull on the packet and updates + * update the CHECKSUM_HW checksum. It should be used on receive + * path processing instead of skb_pull unless you know that the + * checksum difference is zero (e.g., a valid IP header) or you + * are setting ip_summed to CHECKSUM_NONE. + */ +unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len) +{ + BUG_ON(len > skb->len); + skb->len -= len; + BUG_ON(skb->len < skb->data_len); + skb_postpull_rcsum(skb, skb->data, len); + return skb->data += len; +} + +EXPORT_SYMBOL_GPL(skb_pull_rcsum); + /** * skb_segment - Perform protocol segmentation on skb. * @skb: buffer to segment @@ -2022,29 +2045,6 @@ err: EXPORT_SYMBOL_GPL(skb_segment); -/** - * skb_pull_rcsum - pull skb and update receive checksum - * @skb: buffer to update - * @start: start of data before pull - * @len: length of data pulled - * - * This function performs an skb_pull on the packet and updates - * update the CHECKSUM_HW checksum. It should be used on receive - * path processing instead of skb_pull unless you know that the - * checksum difference is zero (e.g., a valid IP header) or you - * are setting ip_summed to CHECKSUM_NONE. - */ -unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len) -{ - BUG_ON(len > skb->len); - skb->len -= len; - BUG_ON(skb->len < skb->data_len); - skb_postpull_rcsum(skb, skb->data, len); - return skb->data += len; -} - -EXPORT_SYMBOL_GPL(skb_pull_rcsum); - void __init skb_init(void) { skbuff_head_cache = kmem_cache_create("skbuff_head_cache", diff --git a/patches/linux-2.6.18/series b/patches/linux-2.6.18/series index 62b3e0e0d7..85bbae63e4 100644 --- a/patches/linux-2.6.18/series +++ b/patches/linux-2.6.18/series @@ -18,3 +18,4 @@ git-dbaab49f92ff6ae6255762a948375e4036cbdbd2.patch x86-elfnote-as-preprocessor-macro.patch fixaddr-top.patch git-c06cb8b1c4d25e5b4d7a2d7c2462619de1e0dbc4.patch +softlockup-no-idle-hz.patch diff --git a/patches/linux-2.6.18/softlockup-no-idle-hz.patch b/patches/linux-2.6.18/softlockup-no-idle-hz.patch new file mode 100644 index 0000000000..6799bfc4bf --- /dev/null +++ b/patches/linux-2.6.18/softlockup-no-idle-hz.patch @@ -0,0 +1,56 @@ +diff -pruN ../orig-linux-2.6.18/include/linux/sched.h ./include/linux/sched.h +--- ../orig-linux-2.6.18/include/linux/sched.h 2006-09-20 04:42:06.000000000 +0100 ++++ ./include/linux/sched.h 2007-02-07 01:10:24.000000000 +0000 +@@ -211,10 +211,15 @@ extern void update_process_times(int use + extern void scheduler_tick(void); + + #ifdef CONFIG_DETECT_SOFTLOCKUP ++extern unsigned long softlockup_get_next_event(void); + extern void softlockup_tick(void); + extern void spawn_softlockup_task(void); + extern void touch_softlockup_watchdog(void); + #else ++static inline unsigned long softlockup_get_next_event(void) ++{ ++ return MAX_JIFFY_OFFSET; ++} + static inline void softlockup_tick(void) + { + } +diff -pruN ../orig-linux-2.6.18/kernel/softlockup.c ./kernel/softlockup.c +--- ../orig-linux-2.6.18/kernel/softlockup.c 2006-09-20 04:42:06.000000000 +0100 ++++ ./kernel/softlockup.c 2007-02-07 01:53:22.000000000 +0000 +@@ -40,6 +40,19 @@ void touch_softlockup_watchdog(void) + } + EXPORT_SYMBOL(touch_softlockup_watchdog); + ++unsigned long softlockup_get_next_event(void) ++{ ++ int this_cpu = smp_processor_id(); ++ unsigned long touch_timestamp = per_cpu(touch_timestamp, this_cpu); ++ ++ if (per_cpu(print_timestamp, this_cpu) == touch_timestamp || ++ did_panic || ++ !per_cpu(watchdog_task, this_cpu)) ++ return MAX_JIFFY_OFFSET; ++ ++ return min_t(long, 0, touch_timestamp + HZ - jiffies); ++} ++ + /* + * This callback runs from the timer interrupt, and checks + * whether the watchdog thread has hung or not: +diff -pruN ../orig-linux-2.6.18/kernel/timer.c ./kernel/timer.c +--- ../orig-linux-2.6.18/kernel/timer.c 2006-09-20 04:42:06.000000000 +0100 ++++ ./kernel/timer.c 2007-02-07 01:29:34.000000000 +0000 +@@ -485,7 +485,9 @@ unsigned long next_timer_interrupt(void) + if (hr_expires < 3) + return hr_expires + jiffies; + } +- hr_expires += jiffies; ++ hr_expires = min_t(unsigned long, ++ softlockup_get_next_event(), ++ hr_expires) + jiffies; + + base = __get_cpu_var(tvec_bases); + spin_lock(&base->lock); diff --git a/tools/examples/block b/tools/examples/block index ac4313ecd9..2b6b991125 100644 --- a/tools/examples/block +++ b/tools/examples/block @@ -367,13 +367,7 @@ mount it read-write in a guest domain." fatal 'Failed to find an unused loop device' fi - cmode=`canonicalise_mode $mode` - if [ "$cmode" == 'r' ] - then - do_or_die losetup -r "$loopdev" "$file" - else - do_or_die losetup "$loopdev" "$file" - fi + do_or_die losetup "$loopdev" "$file" xenstore_write "$XENBUS_PATH/node" "$loopdev" write_dev "$loopdev" release_lock "block" diff --git a/tools/examples/vif-bridge b/tools/examples/vif-bridge index 0935ad2fae..6bee562c4b 100755 --- a/tools/examples/vif-bridge +++ b/tools/examples/vif-bridge @@ -46,6 +46,13 @@ then fi fi +RET=0 +ip link show $bridge 1>/dev/null 2>&1 || RET=1 +if [ "$RET" -eq 1 ] +then + fatal "Could not find bridge device $bridge" +fi + case "$command" in online) setup_bridge_port "$vif" diff --git a/tools/examples/xen-hotplug-common.sh b/tools/examples/xen-hotplug-common.sh index c825dae593..980a62704e 100644 --- a/tools/examples/xen-hotplug-common.sh +++ b/tools/examples/xen-hotplug-common.sh @@ -28,14 +28,15 @@ export LANG="POSIX" unset $(set | grep ^LC_ | cut -d= -f1) fatal() { - xenstore_write "$XENBUS_PATH"/hotplug-status error + xenstore_write "$XENBUS_PATH/hotplug-error" "$*" \ + "$XENBUS_PATH/hotplug-status" error log err "$@" exit 1 } success() { # Tell DevController that backend is "connected" - xenstore_write "$XENBUS_PATH"/hotplug-status connected + xenstore_write "$XENBUS_PATH/hotplug-status" connected } do_or_die() { diff --git a/tools/firmware/rombios/32bit/tcgbios/tcgbios.c b/tools/firmware/rombios/32bit/tcgbios/tcgbios.c index 07d91d2f36..dc1a9e0d51 100644 --- a/tools/firmware/rombios/32bit/tcgbios/tcgbios.c +++ b/tools/firmware/rombios/32bit/tcgbios/tcgbios.c @@ -146,7 +146,7 @@ static tcpa_acpi_t tcpa_acpi; static int tpm_driver_to_use = TPM_INVALID_DRIVER; static -uint32_t MA_IsTPMPresent() +uint32_t MA_IsTPMPresent(void) { uint32_t rc = 0; unsigned int i; @@ -263,11 +263,11 @@ void tcpa_acpi_init(void) { struct acpi_20_rsdt *rsdt; uint32_t length; - struct acpi_20_tcpa *tcpa; + struct acpi_20_tcpa *tcpa = (void *)0; uint16_t found = 0; uint16_t rsdp_off; uint16_t off; - struct acpi_20_rsdp *rsdp; + struct acpi_20_rsdp *rsdp = (void *)0; if (MA_IsTPMPresent() == 0) { return; @@ -732,8 +732,8 @@ void tcpa_ipl(Bit32u seg) void tcpa_measure_post(Bit32u from, Bit32u to) { struct pcpes pcpes; /* PCClientPCREventStruc */ - memset(&pcpes, 0x0, sizeof(pcpes)); int len = to - from; + memset(&pcpes, 0x0, sizeof(pcpes)); if (len > 0) { sha1((unsigned char *)from, @@ -986,7 +986,7 @@ uint32_t PassThroughToTPM32(struct pttti *pttti, { uint32_t rc = 0; uint8_t *cmd32; - uint32_t resbuflen; + uint32_t resbuflen = 0; if (TCG_IsShutdownPreBootInterface() != 0) { rc = (TCG_PC_TPMERROR | @@ -1277,9 +1277,7 @@ typedef struct _sha1_ctx { } sha1_ctx; -static inline uint32_t rol(val, rol) - uint32_t val; - uint16_t rol; +static inline uint32_t rol(uint32_t val, uint16_t rol) { return (val << rol) | (val >> (32 - rol)); } diff --git a/tools/firmware/rombios/32bit/tcgbios/tpm_drivers.c b/tools/firmware/rombios/32bit/tcgbios/tpm_drivers.c index 7534b32992..5a49b0038c 100644 --- a/tools/firmware/rombios/32bit/tcgbios/tpm_drivers.c +++ b/tools/firmware/rombios/32bit/tcgbios/tpm_drivers.c @@ -27,12 +27,27 @@ #include "tpm_drivers.h" #include "tcgbios.h" +#define STS_VALID (1 << 7) /* 0x80 */ +#define STS_COMMAND_READY (1 << 6) /* 0x40 */ +#define STS_TPM_GO (1 << 5) /* 0x20 */ +#define STS_DATA_AVAILABLE (1 << 4) /* 0x10 */ +#define STS_EXPECT (1 << 3) /* 0x08 */ +#define STS_RESPONSE_RETRY (1 << 1) /* 0x02 */ + +#define ACCESS_TPM_REG_VALID_STS (1 << 7) /* 0x80 */ +#define ACCESS_ACTIVE_LOCALITY (1 << 5) /* 0x20 */ +#define ACCESS_BEEN_SEIZED (1 << 4) /* 0x10 */ +#define ACCESS_SEIZE (1 << 3) /* 0x08 */ +#define ACCESS_PENDING_REQUEST (1 << 2) /* 0x04 */ +#define ACCESS_REQUEST_USE (1 << 1) /* 0x02 */ +#define ACCESS_TPM_ESTABLISHMENT (1 << 0) /* 0x01 */ + static uint32_t tis_wait_sts(uint8_t *addr, uint32_t time, uint8_t mask, uint8_t expect) { uint32_t rc = 0; while (time > 0) { - uint8_t sts = addr[TPM_STS]; + uint8_t sts = mmio_readb(&addr[TPM_STS]); if ((sts & mask) == expect) { rc = 1; break; @@ -45,16 +60,17 @@ static uint32_t tis_wait_sts(uint8_t *addr, uint32_t time, static uint32_t tis_activate(uint32_t baseaddr) { - uint32_t rc = 0; + uint32_t rc = 1; uint8_t *tis_addr = (uint8_t*)baseaddr; uint8_t acc; /* request access to locality */ - tis_addr[TPM_ACCESS] = 0x2; + tis_addr[TPM_ACCESS] = ACCESS_REQUEST_USE; - acc = tis_addr[TPM_ACCESS]; - if ((acc & 0x20) != 0) { - tis_addr[TPM_STS] = 0x40; - rc = tis_wait_sts(tis_addr, 100, 0x40, 0x40); + acc = mmio_readb(&tis_addr[TPM_ACCESS]); + if ((acc & ACCESS_ACTIVE_LOCALITY) != 0) { + tis_addr[TPM_STS] = STS_COMMAND_READY; + rc = tis_wait_sts(tis_addr, 100, + STS_COMMAND_READY, STS_COMMAND_READY); } return rc; } @@ -64,8 +80,8 @@ uint32_t tis_ready(uint32_t baseaddr) uint32_t rc = 0; uint8_t *tis_addr = (uint8_t*)baseaddr; - tis_addr[TPM_STS] = 0x40; - rc = tis_wait_sts(tis_addr, 100, 0x40, 0x40); + tis_addr[TPM_STS] = STS_COMMAND_READY; + rc = tis_wait_sts(tis_addr, 100, STS_COMMAND_READY, STS_COMMAND_READY); return rc; } @@ -81,8 +97,7 @@ uint32_t tis_senddata(uint32_t baseaddr, unsigned char *data, uint32_t len) uint16_t burst = 0; uint32_t ctr = 0; while (burst == 0 && ctr < 2000) { - burst = (((uint16_t)tis_addr[TPM_STS+1]) ) + - (((uint16_t)tis_addr[TPM_STS+2]) << 8); + burst = mmio_readw((uint16_t *)&tis_addr[TPM_STS+1]); if (burst == 0) { mssleep(1); ctr++; @@ -120,11 +135,11 @@ uint32_t tis_readresp(uint32_t baseaddr, unsigned char *buffer, uint32_t len) uint32_t sts; while (offset < len) { - buffer[offset] = tis_addr[TPM_DATA_FIFO]; + buffer[offset] = mmio_readb(&tis_addr[TPM_DATA_FIFO]); offset++; - sts = tis_addr[TPM_STS]; + sts = mmio_readb(&tis_addr[TPM_STS]); /* data left ? */ - if ((sts & 0x10) == 0) { + if ((sts & STS_DATA_AVAILABLE) == 0) { break; } } @@ -136,7 +151,7 @@ uint32_t tis_waitdatavalid(uint32_t baseaddr) { uint8_t *tis_addr = (uint8_t*)baseaddr; uint32_t rc = 0; - if (tis_wait_sts(tis_addr, 1000, 0x80, 0x80) == 0) { + if (tis_wait_sts(tis_addr, 1000, STS_VALID, STS_VALID) == 0) { rc = TCG_NO_RESPONSE; } return rc; @@ -146,8 +161,9 @@ uint32_t tis_waitrespready(uint32_t baseaddr, uint32_t timeout) { uint32_t rc = 0; uint8_t *tis_addr = (uint8_t*)baseaddr; - tis_addr[TPM_STS] = 0x20; - if (tis_wait_sts(tis_addr, timeout, 0x10, 0x10) == 0) { + tis_addr[TPM_STS] = STS_TPM_GO; + if (tis_wait_sts(tis_addr, timeout, + STS_DATA_AVAILABLE, STS_DATA_AVAILABLE) == 0) { rc = TCG_NO_RESPONSE; } return rc; @@ -158,7 +174,7 @@ uint32_t tis_probe(uint32_t baseaddr) { uint32_t rc = 0; uint8_t *tis_addr = (uint8_t*)baseaddr; - uint32_t didvid = *(uint32_t*)&tis_addr[TPM_DID_VID]; + uint32_t didvid = mmio_readl((uint32_t *)&tis_addr[TPM_DID_VID]); if ((didvid != 0) && (didvid != 0xffffffff)) { rc = 1; } diff --git a/tools/firmware/rombios/32bit/util.h b/tools/firmware/rombios/32bit/util.h index 1a29a8cbe1..6d05b502d5 100644 --- a/tools/firmware/rombios/32bit/util.h +++ b/tools/firmware/rombios/32bit/util.h @@ -24,5 +24,20 @@ void byte_to_hex(char *digits, uint8_t byte); void uuid_to_string(char *dest, uint8_t *uuid); int printf(const char *fmt, ...); +static inline uint8_t mmio_readb(uint8_t *addr) +{ + return *(volatile uint8_t *)addr; +} + +static inline uint16_t mmio_readw(uint16_t *addr) +{ + return *(volatile uint16_t *)addr; +} + +static inline uint32_t mmio_readl(uint32_t *addr) +{ + return *(volatile uint32_t *)addr; +} + #endif diff --git a/tools/firmware/rombios/rombios.c b/tools/firmware/rombios/rombios.c index a874b23d15..414a2ec252 100644 --- a/tools/firmware/rombios/rombios.c +++ b/tools/firmware/rombios/rombios.c @@ -5722,9 +5722,6 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS) goto int13_fail; } -#if BX_TCGBIOS - tcpa_ipl((Bit32u)bootseg); /* specs: 8.2.3 steps 4 and 5 */ -#endif switch (GET_AH()) { @@ -7741,6 +7738,10 @@ ASM_END } } +#if BX_TCGBIOS + tcpa_add_bootdevice((Bit32u)0L, (Bit32u)bootdrv); +#endif + /* Canonicalize bootseg:bootip */ bootip = (bootseg & 0x0fff) << 4; bootseg &= 0xf000; @@ -7760,6 +7761,9 @@ ASM_END bootdrv = (Bit8u)(status>>8); bootseg = read_word(ebda_seg,&EbdaData->cdemu.load_segment); /* Canonicalize bootseg:bootip */ +#if BX_TCGBIOS + tcpa_add_bootdevice((Bit32u)1L, (Bit32u)0L); +#endif bootip = (bootseg & 0x0fff) << 4; bootseg &= 0xf000; break; @@ -7773,6 +7777,9 @@ ASM_END default: return; } +#if BX_TCGBIOS + tcpa_ipl((Bit32u)bootseg); /* specs: 8.2.3 steps 4 and 5 */ +#endif /* Debugging info */ printf("Booting from %x:%x\n", bootseg, bootip); diff --git a/tools/ioemu/hw/cirrus_vga.c b/tools/ioemu/hw/cirrus_vga.c index 3c316d6dc9..292673ae6a 100644 --- a/tools/ioemu/hw/cirrus_vga.c +++ b/tools/ioemu/hw/cirrus_vga.c @@ -3339,6 +3339,10 @@ void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, pci_conf[0x0a] = PCI_CLASS_SUB_VGA; pci_conf[0x0b] = PCI_CLASS_BASE_DISPLAY; pci_conf[0x0e] = PCI_CLASS_HEADERTYPE_00h; + pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */ + pci_conf[0x2d] = 0x58; + pci_conf[0x2e] = 0x01; /* subsystem device */ + pci_conf[0x2f] = 0x00; /* setup VGA */ s = &d->cirrus_vga; diff --git a/tools/ioemu/hw/ide.c b/tools/ioemu/hw/ide.c index ef203a2f8a..3bf2c7d594 100644 --- a/tools/ioemu/hw/ide.c +++ b/tools/ioemu/hw/ide.c @@ -2502,6 +2502,10 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn) pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage pci_conf[0x0e] = 0x00; // header_type + pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */ + pci_conf[0x2d] = 0x58; + pci_conf[0x2e] = 0x01; /* subsystem device */ + pci_conf[0x2f] = 0x00; pci_register_io_region((PCIDevice *)d, 4, 0x10, PCI_ADDRESS_SPACE_IO, bmdma_map); diff --git a/tools/ioemu/hw/rtl8139.c b/tools/ioemu/hw/rtl8139.c index 77e3c6d9fb..e4ba40dfe3 100644 --- a/tools/ioemu/hw/rtl8139.c +++ b/tools/ioemu/hw/rtl8139.c @@ -3423,8 +3423,10 @@ void pci_rtl8139_init(PCIBus *bus, NICInfo *nd) pci_conf[0x0e] = 0x00; /* header_type */ pci_conf[0x3d] = 1; /* interrupt pin 0 */ pci_conf[0x34] = 0xdc; - pci_conf[0x2c] = pci_conf[0x00]; // same as Vendor ID - pci_conf[0x2d] = pci_conf[0x01]; + pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */ + pci_conf[0x2d] = 0x58; + pci_conf[0x2e] = 0x01; /* subsystem device */ + pci_conf[0x2f] = 0x00; s = &d->rtl8139; diff --git a/tools/ioemu/hw/tpm_tis.c b/tools/ioemu/hw/tpm_tis.c index ace469f1ec..452516c182 100644 --- a/tools/ioemu/hw/tpm_tis.c +++ b/tools/ioemu/hw/tpm_tis.c @@ -517,7 +517,7 @@ static uint32_t tis_mem_readl(void *opaque, target_phys_addr_t addr) #ifdef DEBUG_TPM fprintf(logfile," read(%08x) = %08x\n", - addr, + (int)addr, val); #endif @@ -538,7 +538,7 @@ static void tis_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) #ifdef DEBUG_TPM fprintf(logfile,"write(%08x) = %08x\n", - addr, + (int)addr, val); #endif @@ -757,10 +757,11 @@ static CPUWriteMemoryFunc *tis_writefn[3]={ static void tpm_save(QEMUFile* f,void* opaque) { tpmState* s=(tpmState*)opaque; + uint8_t locty = s->active_loc; int c; /* need to wait for outstanding requests to complete */ - if (IS_COMM_WITH_VTPM(s)) { + if (s->loc[locty].state == STATE_EXECUTION) { int repeats = 30; /* 30 seconds; really should be infty */ while (repeats > 0 && !(s->loc[s->active_loc].sts & STS_DATA_AVAILABLE)) { @@ -777,6 +778,10 @@ static void tpm_save(QEMUFile* f,void* opaque) } } + if (IS_COMM_WITH_VTPM(s)) { + close_vtpm_channel(s, 1); + } + qemu_put_be32s(f,&s->offset); qemu_put_buffer(f, s->buffer.buf, TPM_MAX_PKT); qemu_put_8s(f, &s->active_loc); @@ -993,7 +998,7 @@ static int TPM_Receive(tpmState *s, tpmBuffer *buffer) uint32_t size = tpm_get_size_from_buffer(buffer->buf); if (size + sizeof(buffer->instance) != off) { fprintf(logfile,"TPM: Packet size is bad! %d != %d\n", - size + sizeof(buffer->instance), + (int)(size + sizeof(buffer->instance)), off); } else { uint32_t ret; diff --git a/tools/ioemu/xenstore.c b/tools/ioemu/xenstore.c index 21a8ed08b7..6b1036bcbf 100644 --- a/tools/ioemu/xenstore.c +++ b/tools/ioemu/xenstore.c @@ -10,6 +10,7 @@ #include "vl.h" #include "block_int.h" +#include static struct xs_handle *xsh = NULL; static char *hd_filename[MAX_DISKS]; @@ -52,11 +53,40 @@ void xenstore_check_new_media_present(int timeout) qemu_mod_timer(insert_timer, qemu_get_clock(rt_clock) + timeout); } +static int waitForDevice(char *path, char *field, char *desired) +{ + char *buf = NULL, *stat = NULL; + unsigned int len; + int val = 1; + + /* loop until we find a value in xenstore, return + * if it was what we wanted, or not + */ + while (1) { + if (pasprintf(&buf, "%s/%s", path, field) == -1) + goto done; + free(stat); + stat = xs_read(xsh, XBT_NULL, buf, &len); + if (stat == NULL) { + usleep(100000); /* 1/10th second, no path found */ + } else { + val = strcmp(stat, desired); + goto done; + } + } + +done: + free(stat); + free(buf); + return val; +} + void xenstore_parse_domain_config(int domid) { char **e = NULL; char *buf = NULL, *path; - char *bpath = NULL, *dev = NULL, *params = NULL, *type = NULL; + char *fpath = NULL, *bpath = NULL, + *dev = NULL, *params = NULL, *type = NULL; int i; unsigned int len, num, hd_index; @@ -120,7 +150,35 @@ void xenstore_parse_domain_config(int domid) hd_filename[hd_index] = params; /* strdup() */ params = NULL; /* don't free params on re-use */ } + /* + * check if device has a phantom vbd; the phantom is hooked + * to the frontend device (for ease of cleanup), so lookup + * the frontend device, and see if there is a phantom_vbd + * if there is, we will use resolution as the filename + */ + if (pasprintf(&buf, "%s/device/vbd/%s/phantom_vbd", path, e[i]) == -1) + continue; + free(fpath); + fpath = xs_read(xsh, XBT_NULL, buf, &len); + if (fpath != NULL) { + + if (waitForDevice(fpath, "hotplug-status", "connected")) { + continue; + } + + if (pasprintf(&buf, "%s/dev", fpath) == -1) + continue; + params = xs_read(xsh, XBT_NULL, buf , &len); + if (params != NULL) { + free(hd_filename[hd_index]); + hd_filename[hd_index] = params; + params = NULL; /* don't free params on re-use */ + } + } bs_table[hd_index] = bdrv_new(dev); + /* re-establish buf */ + if (pasprintf(&buf, "%s/params", bpath) == -1) + continue; /* check if it is a cdrom */ if (type && !strcmp(type, "cdrom")) { bdrv_set_type_hint(bs_table[hd_index], BDRV_TYPE_CDROM); diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c index e557f43f13..73d229dc61 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -252,12 +252,14 @@ int xc_domain_hvm_getcontext(int xc_handle, domctl.u.hvmcontext.size = size; set_xen_guest_handle(domctl.u.hvmcontext.buffer, ctxt_buf); - if ( (ret = lock_pages(ctxt_buf, size)) != 0 ) - return ret; + if ( ctxt_buf ) + if ( (ret = lock_pages(ctxt_buf, size)) != 0 ) + return ret; ret = do_domctl(xc_handle, &domctl); - unlock_pages(ctxt_buf, size); + if ( ctxt_buf ) + unlock_pages(ctxt_buf, size); return (ret < 0 ? -1 : domctl.u.hvmcontext.size); } diff --git a/tools/libxc/xc_hvm_restore.c b/tools/libxc/xc_hvm_restore.c index 6622b49f79..ec3eeb8999 100644 --- a/tools/libxc/xc_hvm_restore.c +++ b/tools/libxc/xc_hvm_restore.c @@ -41,11 +41,8 @@ static unsigned long hvirt_start; /* #levels of page tables used by the currrent guest */ static unsigned int pt_levels; -/* total number of pages used by the current guest */ -static unsigned long max_pfn; - -/* A table mapping each PFN to its new MFN. */ -static xen_pfn_t *p2m = NULL; +/* A list of PFNs that exist, used when allocating memory to the guest */ +static xen_pfn_t *pfns = NULL; static ssize_t read_exact(int fd, void *buf, size_t count) @@ -67,9 +64,8 @@ read_exact(int fd, void *buf, size_t count) } int xc_hvm_restore(int xc_handle, int io_fd, - uint32_t dom, unsigned long nr_pfns, + uint32_t dom, unsigned long max_pfn, unsigned int store_evtchn, unsigned long *store_mfn, - unsigned int console_evtchn, unsigned long *console_mfn, unsigned int pae, unsigned int apic) { DECLARE_DOMCTL; @@ -91,7 +87,7 @@ int xc_hvm_restore(int xc_handle, int io_fd, unsigned long long v_end, memsize; unsigned long shared_page_nr; - unsigned long mfn, pfn; + unsigned long pfn; unsigned int prev_pc, this_pc; int verify = 0; @@ -100,22 +96,26 @@ int xc_hvm_restore(int xc_handle, int io_fd, struct xen_add_to_physmap xatp; + /* Number of pages of memory the guest has. *Not* the same as max_pfn. */ + unsigned long nr_pages; + /* hvm guest mem size (Mb) */ memsize = (unsigned long long)*store_mfn; v_end = memsize << 20; + nr_pages = (unsigned long) memsize << (20 - PAGE_SHIFT); - DPRINTF("xc_hvm_restore:dom=%d, nr_pfns=0x%lx, store_evtchn=%d, *store_mfn=%ld, console_evtchn=%d, *console_mfn=%ld, pae=%u, apic=%u.\n", - dom, nr_pfns, store_evtchn, *store_mfn, console_evtchn, *console_mfn, pae, apic); - - max_pfn = nr_pfns; + DPRINTF("xc_hvm_restore:dom=%d, nr_pages=0x%lx, store_evtchn=%d, *store_mfn=%ld, pae=%u, apic=%u.\n", + dom, nr_pages, store_evtchn, *store_mfn, pae, apic); + if(!get_platform_info(xc_handle, dom, &max_mfn, &hvirt_start, &pt_levels)) { ERROR("Unable to get platform info."); return 1; } - DPRINTF("xc_hvm_restore start: max_pfn = %lx, max_mfn = %lx, hvirt_start=%lx, pt_levels=%d\n", + DPRINTF("xc_hvm_restore start: nr_pages = %lx, max_pfn = %lx, max_mfn = %lx, hvirt_start=%lx, pt_levels=%d\n", + nr_pages, max_pfn, max_mfn, hvirt_start, @@ -128,30 +128,30 @@ int xc_hvm_restore(int xc_handle, int io_fd, } - p2m = malloc(max_pfn * sizeof(xen_pfn_t)); - if (p2m == NULL) { + pfns = malloc(max_pfn * sizeof(xen_pfn_t)); + if (pfns == NULL) { ERROR("memory alloc failed"); errno = ENOMEM; goto out; } - if(xc_domain_setmaxmem(xc_handle, dom, PFN_TO_KB(max_pfn)) != 0) { + if(xc_domain_setmaxmem(xc_handle, dom, PFN_TO_KB(nr_pages)) != 0) { errno = ENOMEM; goto out; } for ( i = 0; i < max_pfn; i++ ) - p2m[i] = i; + pfns[i] = i; for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < max_pfn; i++ ) - p2m[i] += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT; + pfns[i] += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT; /* Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. */ rc = xc_domain_memory_populate_physmap( - xc_handle, dom, (max_pfn > 0xa0) ? 0xa0 : max_pfn, - 0, 0, &p2m[0x00]); - if ( (rc == 0) && (max_pfn > 0xc0) ) + xc_handle, dom, (nr_pages > 0xa0) ? 0xa0 : nr_pages, + 0, 0, &pfns[0x00]); + if ( (rc == 0) && (nr_pages > 0xc0) ) rc = xc_domain_memory_populate_physmap( - xc_handle, dom, max_pfn - 0xc0, 0, 0, &p2m[0xc0]); + xc_handle, dom, nr_pages - 0xc0, 0, 0, &pfns[0xc0]); if ( rc != 0 ) { PERROR("Could not allocate memory for HVM guest.\n"); @@ -172,9 +172,6 @@ int xc_hvm_restore(int xc_handle, int io_fd, goto out; } - for ( i = 0; i < max_pfn; i++) - p2m[i] = i; - prev_pc = 0; n = 0; @@ -182,7 +179,7 @@ int xc_hvm_restore(int xc_handle, int io_fd, int j; - this_pc = (n * 100) / max_pfn; + this_pc = (n * 100) / nr_pages; if ( (this_pc - prev_pc) >= 5 ) { PPRINTF("\b\b\b\b%3d%%", this_pc); @@ -235,8 +232,6 @@ int xc_hvm_restore(int xc_handle, int io_fd, } - mfn = p2m[pfn]; - /* In verify mode, we use a copy; otherwise we work in place */ page = verify ? (void *)buf : (region_base + i*PAGE_SIZE); @@ -253,8 +248,8 @@ int xc_hvm_restore(int xc_handle, int io_fd, int v; - DPRINTF("************** pfn=%lx mfn=%lx gotcs=%08lx " - "actualcs=%08lx\n", pfn, p2m[pfn], + DPRINTF("************** pfn=%lx gotcs=%08lx " + "actualcs=%08lx\n", pfn, csum_page(region_base + i*PAGE_SIZE), csum_page(buf)); @@ -362,7 +357,7 @@ int xc_hvm_restore(int xc_handle, int io_fd, out: if ( (rc != 0) && (dom != 0) ) xc_domain_destroy(xc_handle, dom); - free(p2m); + free(pfns); free(hvm_buf); DPRINTF("Restore exit with rc=%d\n", rc); diff --git a/tools/libxc/xc_hvm_save.c b/tools/libxc/xc_hvm_save.c index d9cca58d07..fdd2799743 100644 --- a/tools/libxc/xc_hvm_save.c +++ b/tools/libxc/xc_hvm_save.c @@ -27,17 +27,12 @@ #include #include #include +#include #include "xc_private.h" #include "xg_private.h" #include "xg_save_restore.h" -/* - * Size of a buffer big enough to take the HVM state of a domain. - * Ought to calculate this a bit more carefully, or maybe ask Xen. - */ -#define HVM_CTXT_SIZE 8192 - /* ** Default values for important tuning parameters. Can override by passing ** non-zero replacement values to xc_hvm_save(). @@ -281,11 +276,11 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, /* A copy of the CPU context of the guest. */ vcpu_guest_context_t ctxt; - /* A table containg the type of each PFN (/not/ MFN!). */ - unsigned long *pfn_type = NULL; - unsigned long *pfn_batch = NULL; + /* A table containg the PFNs (/not/ MFN!) to map. */ + xen_pfn_t *pfn_batch = NULL; /* A copy of hvm domain context buffer*/ + uint32_t hvm_buf_size; uint8_t *hvm_buf = NULL; /* Live mapping of shared info structure */ @@ -295,7 +290,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, unsigned char *region_base = NULL; uint32_t nr_pfns, rec_size, nr_vcpus; - unsigned long *page_array = NULL; /* power of 2 order of max_pfn */ int order_nr; @@ -366,18 +360,12 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, goto out; } - max_pfn = live_shinfo->arch.max_pfn; - DPRINTF("saved hvm domain info:max_memkb=0x%lx, max_mfn=0x%lx, nr_pages=0x%lx\n", info.max_memkb, max_mfn, info.nr_pages); - /* nr_pfns: total pages excluding vga acc mem - * max_pfn: nr_pfns + 0x20 vga hole(0xa0~0xc0) - * getdomaininfo.tot_pages: all the allocated pages for this domain - */ if (live) { ERROR("hvm domain doesn't support live migration now.\n"); goto out; - + if (xc_shadow_control(xc_handle, dom, XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY, NULL, 0, NULL, 0, NULL) < 0) { @@ -386,6 +374,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } /* excludes vga acc mem */ + /* XXX will need to check whether acceleration is enabled here! */ nr_pfns = info.nr_pages - 0x800; last_iter = 0; @@ -401,8 +390,8 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, ERROR("HVM Domain appears not to have suspended"); goto out; } - nr_pfns = info.nr_pages; - DPRINTF("after suspend hvm domain nr_pages=0x%x.\n", nr_pfns); + + nr_pfns = info.nr_pages; } DPRINTF("after 1st handle hvm domain nr_pfns=0x%x, nr_pages=0x%lx, max_memkb=0x%lx, live=%d.\n", @@ -411,10 +400,15 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, info.max_memkb, live); - nr_pfns = info.nr_pages; - - /*XXX: caculate the VGA hole*/ - max_pfn = nr_pfns + 0x20; + /* Calculate the highest PFN of "normal" memory: + * HVM memory is sequential except for the VGA and MMIO holes, and + * we have nr_pfns of it (which now excludes the cirrus video RAM) */ + max_pfn = nr_pfns; + /* Skip the VGA hole from 0xa0000 to 0xc0000 */ + max_pfn += 0x20; + /* Skip the MMIO hole: 256MB just below 4GB */ + if ( max_pfn >= (HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT) ) + max_pfn += (HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT); skip_this_iter = 0;/*XXX*/ /* pretend we sent all the pages last iteration */ @@ -429,11 +423,16 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, to_send = malloc(BITMAP_SIZE); to_skip = malloc(BITMAP_SIZE); - page_array = (unsigned long *) malloc( sizeof(unsigned long) * max_pfn); - hvm_buf = malloc(HVM_CTXT_SIZE); + hvm_buf_size = xc_domain_hvm_getcontext(xc_handle, dom, 0, 0); + if ( hvm_buf_size == -1 ) + { + ERROR("Couldn't get HVM context size from Xen"); + goto out; + } + hvm_buf = malloc(hvm_buf_size); - if (!to_send ||!to_skip ||!page_array ||!hvm_buf ) { + if (!to_send ||!to_skip ||!hvm_buf) { ERROR("Couldn't allocate memory"); goto out; } @@ -453,26 +452,16 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, analysis_phase(xc_handle, dom, max_pfn, to_skip, 0); - /* get all the HVM domain pfns */ - for ( i = 0; i < max_pfn; i++) - page_array[i] = i; - /* We want zeroed memory so use calloc rather than malloc. */ - pfn_type = calloc(MAX_BATCH_SIZE, sizeof(*pfn_type)); pfn_batch = calloc(MAX_BATCH_SIZE, sizeof(*pfn_batch)); - if ((pfn_type == NULL) || (pfn_batch == NULL)) { - ERROR("failed to alloc memory for pfn_type and/or pfn_batch arrays"); + if (pfn_batch == NULL) { + ERROR("failed to alloc memory for pfn_batch array"); errno = ENOMEM; goto out; } - if (lock_pages(pfn_type, MAX_BATCH_SIZE * sizeof(*pfn_type))) { - ERROR("Unable to lock"); - goto out; - } - /* Start writing out the saved-domain record. */ if (!write_exact(io_fd, &max_pfn, sizeof(unsigned long))) { ERROR("write: max_pfn"); @@ -510,16 +499,15 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } - /* load pfn_type[] with the mfn of all the pages we're doing in + /* load pfn_batch[] with the mfn of all the pages we're doing in this batch. */ for (batch = 0; batch < MAX_BATCH_SIZE && N < max_pfn ; N++) { int n = permute(N, max_pfn, order_nr); if (debug) { - DPRINTF("%d pfn= %08lx mfn= %08lx %d \n", - iter, (unsigned long)n, page_array[n], - test_bit(n, to_send)); + DPRINTF("%d pfn= %08lx %d \n", + iter, (unsigned long)n, test_bit(n, to_send)); } if (!last_iter && test_bit(n, to_send)&& test_bit(n, to_skip)) @@ -529,10 +517,12 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, (test_bit(n, to_send) && last_iter))) continue; - if (n >= 0xa0 && n < 0xc0) { -/* DPRINTF("get a vga hole pfn= %x.\n", n);*/ + /* Skip PFNs that aren't really there */ + if ((n >= 0xa0 && n < 0xc0) /* VGA hole */ + || (n >= (HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT) + && n < (1ULL << 32) >> PAGE_SHIFT)) /* 4G MMIO hole */ continue; - } + /* ** we get here if: ** 1. page is marked to_send & hasn't already been re-dirtied @@ -540,7 +530,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, */ pfn_batch[batch] = n; - pfn_type[batch] = page_array[n]; batch++; } @@ -572,7 +561,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, goto out; } - sent_this_iter += batch; munmap(region_base, batch*PAGE_SIZE); @@ -661,7 +649,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } if ( (rec_size = xc_domain_hvm_getcontext(xc_handle, dom, hvm_buf, - HVM_CTXT_SIZE)) == -1) { + hvm_buf_size)) == -1) { ERROR("HVM:Could not get hvm buffer"); goto out; } @@ -722,9 +710,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } free(hvm_buf); - free(page_array); - - free(pfn_type); free(pfn_batch); free(to_send); free(to_skip); diff --git a/tools/libxc/xenguest.h b/tools/libxc/xenguest.h index d2005201ce..2f0bb4234d 100644 --- a/tools/libxc/xenguest.h +++ b/tools/libxc/xenguest.h @@ -57,9 +57,8 @@ int xc_linux_restore(int xc_handle, int io_fd, uint32_t dom, * @return 0 on success, -1 on failure */ int xc_hvm_restore(int xc_handle, int io_fd, uint32_t dom, - unsigned long nr_pfns, unsigned int store_evtchn, - unsigned long *store_mfn, unsigned int console_evtchn, - unsigned long *console_mfn, + unsigned long max_pfn, unsigned int store_evtchn, + unsigned long *store_mfn, unsigned int pae, unsigned int apic); /** diff --git a/tools/libxc/xg_private.c b/tools/libxc/xg_private.c index 8d77752957..23d8f8b695 100644 --- a/tools/libxc/xg_private.c +++ b/tools/libxc/xg_private.c @@ -209,9 +209,8 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, __attribute__((weak)) int xc_hvm_restore(int xc_handle, int io_fd, uint32_t dom, - unsigned long nr_pfns, unsigned int store_evtchn, - unsigned long *store_mfn, unsigned int console_evtchn, - unsigned long *console_mfn, + unsigned long max_pfn, unsigned int store_evtchn, + unsigned long *store_mfn, unsigned int pae, unsigned int apic) { errno = ENOSYS; diff --git a/tools/misc/Makefile b/tools/misc/Makefile index 80b52c0063..35abbbf08f 100644 --- a/tools/misc/Makefile +++ b/tools/misc/Makefile @@ -9,7 +9,9 @@ CFLAGS += $(INCLUDES) HDRS = $(wildcard *.h) -TARGETS = xenperf xc_shadow +TARGETS-y := xenperf xc_shadow +TARGETS-$(CONFIG_X86) += xen-detect +TARGETS := $(TARGETS-y) INSTALL_BIN = $(TARGETS) xencons INSTALL_SBIN = netfix xm xen-bugtool xen-python-path xend xenperf @@ -41,5 +43,5 @@ clean: %.o: %.c $(HDRS) Makefile $(CC) -c $(CFLAGS) -o $@ $< -$(TARGETS): %: %.o Makefile +xenperf xc_shadow: %: %.o Makefile $(CC) $(CFLAGS) -o $@ $< -L$(XEN_LIBXC) -lxenctrl diff --git a/tools/misc/xen-detect.c b/tools/misc/xen-detect.c new file mode 100644 index 0000000000..c918945f81 --- /dev/null +++ b/tools/misc/xen-detect.c @@ -0,0 +1,108 @@ +/****************************************************************************** + * xen_detect.c + * + * Simple GNU C / POSIX application to detect execution on Xen VMM platform. + * + * Copyright (c) 2007, XenSource Inc. + * + * 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 +#include +#include +#include +#include +#include +#include + +static int pv_context; + +static void cpuid(uint32_t idx, + uint32_t *eax, + uint32_t *ebx, + uint32_t *ecx, + uint32_t *edx) +{ + asm volatile ( + "test %1,%1 ; jz 1f ; ud2a ; .ascii \"xen\" ; 1: cpuid" + : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) + : "0" (idx), "1" (pv_context) ); +} + +static int check_for_xen(void) +{ + uint32_t eax, ebx, ecx, edx; + char signature[13]; + + cpuid(0x40000000, &eax, &ebx, &ecx, &edx); + *(uint32_t *)(signature + 0) = ebx; + *(uint32_t *)(signature + 4) = ecx; + *(uint32_t *)(signature + 8) = edx; + signature[12] = '\0'; + + if ( strcmp("XenVMMXenVMM", signature) || (eax < 0x40000002) ) + return 0; + + cpuid(0x40000001, &eax, &ebx, &ecx, &edx); + printf("Running in %s context on Xen v%d.%d.\n", + pv_context ? "PV" : "HVM", (uint16_t)(eax >> 16), (uint16_t)eax); + return 1; +} + +int main(void) +{ + pid_t pid; + int status; + uint32_t dummy; + + /* Check for execution in HVM context. */ + if ( check_for_xen() ) + return 0; + + /* Now we check for execution in PV context. */ + pv_context = 1; + + /* + * Fork a child to test the paravirtualised CPUID instruction. + * If executed outside Xen PV context, the extended opcode will fault. + */ + pid = fork(); + switch ( pid ) + { + case 0: + /* Child: test paravirtualised CPUID opcode and then exit cleanly. */ + cpuid(0x40000000, &dummy, &dummy, &dummy, &dummy); + exit(0); + case -1: + fprintf(stderr, "Fork failed.\n"); + return 0; + } + + /* + * Parent waits for child to terminate and checks for clean exit. + * Only if the exit is clean is it safe for us to try the extended CPUID. + */ + waitpid(pid, &status, 0); + if ( WIFEXITED(status) && check_for_xen() ) + return 0; + + printf("Not running on Xen.\n"); + return 0; +} diff --git a/tools/python/xen/xend/XendCheckpoint.py b/tools/python/xen/xend/XendCheckpoint.py index 6eda8edf76..63368bd654 100644 --- a/tools/python/xen/xend/XendCheckpoint.py +++ b/tools/python/xen/xend/XendCheckpoint.py @@ -239,8 +239,11 @@ def restore(xd, fd, dominfo = None, paused = False): forkHelper(cmd, fd, handler.handler, True) - if handler.store_mfn is None or handler.console_mfn is None: - raise XendError('Could not read store/console MFN') + if handler.store_mfn is None: + raise XendError('Could not read store MFN') + + if not is_hvm and handler.console_mfn is None: + raise XendError('Could not read console MFN') dominfo.waitForDevices() # Wait for backends to set up if not paused: diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index 223a90cf6e..fa19165e77 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -1148,6 +1148,47 @@ class XendConfig(dict): # no valid device to add return '' + def phantom_device_add(self, dev_type, cfg_xenapi = None, + target = None): + """Add a phantom tap device configuration in XenAPI struct format. + """ + + if target == None: + target = self + + if dev_type not in XendDevices.valid_devices() and \ + dev_type not in XendDevices.pseudo_devices(): + raise XendConfigError("XendConfig: %s not a valid device type" % + dev_type) + + if cfg_xenapi == None: + raise XendConfigError("XendConfig: device_add requires some " + "config.") + + if cfg_xenapi: + log.debug("XendConfig.phantom_device_add: %s" % str(cfg_xenapi)) + + if cfg_xenapi: + dev_info = {} + if dev_type in ('vbd', 'tap'): + if dev_type == 'vbd': + dev_info['uname'] = cfg_xenapi.get('image', '') + dev_info['dev'] = '%s:disk' % cfg_xenapi.get('device') + elif dev_type == 'tap': + if cfg_xenapi.get('image').find('tap:') == -1: + dev_info['uname'] = 'tap:qcow:%s' % cfg_xenapi.get('image') + dev_info['dev'] = '/dev/%s' % cfg_xenapi.get('device') + dev_info['uname'] = cfg_xenapi.get('image') + dev_info['mode'] = cfg_xenapi.get('mode') + dev_info['backend'] = '0' + dev_uuid = cfg_xenapi.get('uuid', uuid.createString()) + dev_info['uuid'] = dev_uuid + self['devices'][dev_uuid] = (dev_type, dev_info) + self['vbd_refs'].append(dev_uuid) + return dev_uuid + + return '' + def console_add(self, protocol, location, other_config = {}): dev_uuid = uuid.createString() if protocol == 'vt100': diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py index 303a615ad8..0c8cddde48 100644 --- a/tools/python/xen/xend/XendDomain.py +++ b/tools/python/xen/xend/XendDomain.py @@ -800,7 +800,10 @@ class XendDomain: "support.") path = self._managed_check_point_path(dom_uuid) - fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) + oflags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC + if hasattr(os, "O_LARGEFILE"): + oflags |= os.O_LARGEFILE + fd = os.open(path, oflags) try: # For now we don't support 'live checkpoint' XendCheckpoint.save(fd, dominfo, False, False, path) @@ -840,8 +843,11 @@ class XendDomain: # Restore that replaces the existing XendDomainInfo try: log.debug('Current DomainInfo state: %d' % dominfo.state) + oflags = os.O_RDONLY + if hasattr(os, "O_LARGEFILE"): + oflags |= os.O_LARGEFILE XendCheckpoint.restore(self, - os.open(chkpath, os.O_RDONLY), + os.open(chkpath, oflags), dominfo, paused = start_paused) os.unlink(chkpath) @@ -1009,7 +1015,10 @@ class XendDomain: @raise XendError: Failure to restore domain """ try: - fd = os.open(src, os.O_RDONLY) + oflags = os.O_RDONLY + if hasattr(os, "O_LARGEFILE"): + oflags |= os.O_LARGEFILE + fd = os.open(src, oflags) try: return self.domain_restore_fd(fd, paused=paused) finally: @@ -1193,7 +1202,10 @@ class XendDomain: if dominfo.getDomid() == DOM0_ID: raise XendError("Cannot save privileged domain %i" % domid) - fd = os.open(dst, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) + oflags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC + if hasattr(os, "O_LARGEFILE"): + oflags |= os.O_LARGEFILE + fd = os.open(dst, oflags) try: # For now we don't support 'live checkpoint' XendCheckpoint.save(fd, dominfo, False, False, dst) diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index ddc240b96b..6c4a9afcb4 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -1416,7 +1416,7 @@ class XendDomainInfo: self.info['image'], self.info['devices']) - localtime = self.info.get('localtime', False) + localtime = self.info.get('platform_localtime', False) if localtime: xc.domain_set_time_offset(self.domid) @@ -1565,19 +1565,54 @@ class XendDomainInfo: # VM Destroy # + def _prepare_phantom_paths(self): + # get associated devices to destroy + # build list of phantom devices to be removed after normal devices + plist = [] + from xen.xend.xenstore.xstransact import xstransact + t = xstransact("%s/device/vbd" % GetDomainPath(self.domid)) + for dev in t.list(): + backend_phantom_vbd = xstransact.Read("%s/device/vbd/%s/phantom_vbd" \ + % (self.dompath, dev)) + if backend_phantom_vbd is not None: + frontend_phantom_vbd = xstransact.Read("%s/frontend" \ + % backend_phantom_vbd) + plist.append(backend_phantom_vbd) + plist.append(frontend_phantom_vbd) + return plist + + def _cleanup_phantom_devs(self, plist): + # remove phantom devices + if not plist == []: + time.sleep(2) + for paths in plist: + if paths.find('backend') != -1: + from xen.xend.server import DevController + # Modify online status /before/ updating state (latter is watched by + # drivers, so this ordering avoids a race). + xstransact.Write(paths, 'online', "0") + xstransact.Write(paths, 'state', str(DevController.xenbusState['Closing'])) + # force + xstransact.Remove(paths) + def destroy(self): """Cleanup VM and destroy domain. Nothrow guarantee.""" log.debug("XendDomainInfo.destroy: domid=%s", str(self.domid)) + paths = self._prepare_phantom_paths() + self._cleanupVm() if self.dompath is not None: self.destroyDomain() + self._cleanup_phantom_devs(paths) def destroyDomain(self): log.debug("XendDomainInfo.destroyDomain(%s)", str(self.domid)) + paths = self._prepare_phantom_paths() + try: if self.domid is not None: xc.domain_destroy(self.domid) @@ -1591,7 +1626,7 @@ class XendDomainInfo: XendDomain.instance().remove_domain(self) self.cleanupDomain() - + self._cleanup_phantom_devs(paths) def resumeDomain(self): log.debug("XendDomainInfo.resumeDomain(%s)", str(self.domid)) @@ -2211,6 +2246,25 @@ class XendDomainInfo: return dev_uuid + def create_phantom_vbd_with_vdi(self, xenapi_vbd, vdi_image_path): + """Create a VBD using a VDI from XendStorageRepository. + + @param xenapi_vbd: vbd struct from the Xen API + @param vdi_image_path: VDI UUID + @rtype: string + @return: uuid of the device + """ + xenapi_vbd['image'] = vdi_image_path + dev_uuid = self.info.phantom_device_add('tap', cfg_xenapi = xenapi_vbd) + if not dev_uuid: + raise XendError('Failed to create device') + + if self.state == XEN_API_VM_POWER_STATE_RUNNING: + _, config = self.info['devices'][dev_uuid] + config['devid'] = self.getDeviceController('tap').createDevice(config) + + return config['devid'] + def create_vif(self, xenapi_vif): """Create VIF device from the passed struct in Xen API format. diff --git a/tools/python/xen/xend/server/BlktapController.py b/tools/python/xen/xend/server/BlktapController.py index 062769a061..420a4bdbe6 100644 --- a/tools/python/xen/xend/server/BlktapController.py +++ b/tools/python/xen/xend/server/BlktapController.py @@ -2,7 +2,10 @@ from xen.xend.server.blkif import BlkifController +from xen.xend.XendLogging import log +phantomDev = 0; +phantomId = 0; class BlktapController(BlkifController): def __init__(self, vm): @@ -12,3 +15,62 @@ class BlktapController(BlkifController): """@see DevController#frontendRoot""" return "%s/device/vbd" % self.vm.getDomainPath() + + def getDeviceDetails(self, config): + (devid, back, front) = BlkifController.getDeviceDetails(self, config) + + phantomDevid = 0 + wrapped = False + + try: + imagetype = self.vm.info['image']['type'] + except: + imagetype = "" + + if imagetype == 'hvm': + tdevname = back['dev'] + index = ['c', 'd', 'e', 'f', 'g', 'h', 'i', \ + 'j', 'l', 'm', 'n', 'o', 'p'] + while True: + global phantomDev + global phantomId + import os, stat + + phantomId = phantomId + 1 + if phantomId == 16: + if index[phantomDev] == index[-1]: + if wrapped: + raise VmError(" No loopback block \ + devices are available. ") + wrapped = True + phantomDev = 0 + else: + phantomDev = phantomDev + 1 + phantomId = 1 + devname = 'xvd%s%d' % (index[phantomDev], phantomId) + try: + info = os.stat('/dev/%s' % devname) + except: + break + + vbd = { 'mode': 'w', 'device': devname } + fn = 'tap:%s' % back['params'] + + # recurse ... by creating the vbd, then fallthrough + # and finish creating the original device + + from xen.xend import XendDomain + dom0 = XendDomain.instance().privilegedDomain() + phantomDevid = dom0.create_phantom_vbd_with_vdi(vbd, fn) + # we need to wait for this device at a higher level + # the vbd that gets created will have a link to us + # and will let them do it there + + # add a hook to point to the phantom device, + # root path is always the same (dom0 tap) + if phantomDevid != 0: + front['phantom_vbd'] = '/local/domain/0/backend/tap/0/%s' \ + % str(phantomDevid) + + return (devid, back, front) + diff --git a/tools/python/xen/xend/server/DevController.py b/tools/python/xen/xend/server/DevController.py index 8256d2265f..0016ff89a3 100644 --- a/tools/python/xen/xend/server/DevController.py +++ b/tools/python/xen/xend/server/DevController.py @@ -153,9 +153,9 @@ class DevController: log.debug("Waiting for %s.", devid) if not self.hotplug: - return - - status = self.waitForBackend(devid) + return + + (status, err) = self.waitForBackend(devid) if status == Timeout: self.destroyDevice(devid, False) @@ -165,25 +165,22 @@ class DevController: elif status == Error: self.destroyDevice(devid, False) - raise VmError("Device %s (%s) could not be connected. " - "Backend device not found." % - (devid, self.deviceClass)) - + if err is None: + raise VmError("Device %s (%s) could not be connected. " + "Backend device not found." % + (devid, self.deviceClass)) + else: + raise VmError("Device %s (%s) could not be connected. " + "%s" % (devid, self.deviceClass, err)) elif status == Missing: # Don't try to destroy the device; it's already gone away. raise VmError("Device %s (%s) could not be connected. " "Device not found." % (devid, self.deviceClass)) elif status == Busy: - err = None - frontpath = self.frontendPath(devid) - backpath = xstransact.Read(frontpath, "backend") - if backpath: - err = xstransact.Read(backpath, HOTPLUG_ERROR_NODE) - if not err: - err = "Busy." - self.destroyDevice(devid, False) + if err is None: + err = "Busy." raise VmError("Device %s (%s) could not be connected.\n%s" % (devid, self.deviceClass, err)) @@ -476,19 +473,36 @@ class DevController: def waitForBackend(self, devid): frontpath = self.frontendPath(devid) + # lookup a phantom + phantomPath = xstransact.Read(frontpath, 'phantom_vbd') + if phantomPath is not None: + log.debug("Waiting for %s's phantom %s.", devid, phantomPath) + statusPath = phantomPath + '/' + HOTPLUG_STATUS_NODE + ev = Event() + result = { 'status': Timeout } + xswatch(statusPath, hotplugStatusCallback, ev, result) + ev.wait(DEVICE_CREATE_TIMEOUT) + err = xstransact.Read(statusPath, HOTPLUG_ERROR_NODE) + if result['status'] != 'Connected': + return (result['status'], err) + backpath = xstransact.Read(frontpath, "backend") + if backpath: statusPath = backpath + '/' + HOTPLUG_STATUS_NODE ev = Event() result = { 'status': Timeout } - + xswatch(statusPath, hotplugStatusCallback, ev, result) ev.wait(DEVICE_CREATE_TIMEOUT) - return result['status'] + + err = xstransact.Read(backpath, HOTPLUG_ERROR_NODE) + + return (result['status'], err) else: - return Missing + return (Missing, None) def backendPath(self, backdom, devid): diff --git a/tools/xcutils/xc_restore.c b/tools/xcutils/xc_restore.c index 8e26d9bb70..0eaf3210a3 100644 --- a/tools/xcutils/xc_restore.c +++ b/tools/xcutils/xc_restore.c @@ -18,14 +18,14 @@ int main(int argc, char **argv) { - unsigned int xc_fd, io_fd, domid, nr_pfns, store_evtchn, console_evtchn; + unsigned int xc_fd, io_fd, domid, max_pfn, store_evtchn, console_evtchn; unsigned int hvm, pae, apic; int ret; unsigned long store_mfn, console_mfn; if (argc != 9) errx(1, - "usage: %s iofd domid nr_pfns store_evtchn console_evtchn hvm pae apic", + "usage: %s iofd domid max_pfn store_evtchn console_evtchn hvm pae apic", argv[0]); xc_fd = xc_interface_open(); @@ -34,7 +34,7 @@ main(int argc, char **argv) io_fd = atoi(argv[1]); domid = atoi(argv[2]); - nr_pfns = atoi(argv[3]); + max_pfn = atoi(argv[3]); store_evtchn = atoi(argv[4]); console_evtchn = atoi(argv[5]); hvm = atoi(argv[6]); @@ -44,15 +44,16 @@ main(int argc, char **argv) if (hvm) { /* pass the memsize to xc_hvm_restore to find the store_mfn */ store_mfn = hvm; - ret = xc_hvm_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn, - &store_mfn, console_evtchn, &console_mfn, pae, apic); + ret = xc_hvm_restore(xc_fd, io_fd, domid, max_pfn, store_evtchn, + &store_mfn, pae, apic); } else - ret = xc_linux_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn, + ret = xc_linux_restore(xc_fd, io_fd, domid, max_pfn, store_evtchn, &store_mfn, console_evtchn, &console_mfn); if (ret == 0) { printf("store-mfn %li\n", store_mfn); - printf("console-mfn %li\n", console_mfn); + if (!hvm) + printf("console-mfn %li\n", console_mfn); fflush(stdout); } diff --git a/tools/xenfb/vncfb.c b/tools/xenfb/vncfb.c index c2a7e5d02d..1ae06809fc 100644 --- a/tools/xenfb/vncfb.c +++ b/tools/xenfb/vncfb.c @@ -57,7 +57,8 @@ unsigned char keycode_table[512]; static void *kbd_layout; static int btnmap[] = { - BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, BTN_FORWARD, BTN_BACK + BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, BTN_SIDE, + BTN_EXTRA, BTN_FORWARD, BTN_BACK, BTN_TASK }; static void on_kbd_event(rfbBool down, rfbKeySym keycode, rfbClientPtr cl) @@ -73,11 +74,12 @@ static void on_kbd_event(rfbBool down, rfbKeySym keycode, rfbClientPtr cl) */ rfbScreenInfoPtr server = cl->screen; struct xenfb *xenfb = server->screenData; + int scancode; - if( keycode >= 'A' && keycode <= 'Z' ) + if (keycode >= 'A' && keycode <= 'Z') keycode += 'a' - 'A'; - int scancode = keycode_table[keysym2scancode(kbd_layout, keycode)]; + scancode = keycode_table[keysym2scancode(kbd_layout, keycode)]; if (scancode == 0) return; if (xenfb_send_key(xenfb, down, scancode) < 0) diff --git a/tools/xentrace/xentrace_format b/tools/xentrace/xentrace_format index 537785824a..36536c24a6 100644 --- a/tools/xentrace/xentrace_format +++ b/tools/xentrace/xentrace_format @@ -107,6 +107,9 @@ while not interrupted: (tsc, event, d1, d2, d3, d4, d5) = struct.unpack(TRCREC, line) + # Event field is 'uint32_t', not 'long'. + event &= 0xffffffff + #tsc = (tscH<<32) | tscL #print i, tsc diff --git a/unmodified_drivers/linux-2.6/overrides.mk b/unmodified_drivers/linux-2.6/overrides.mk index 81416b2b10..818723a492 100644 --- a/unmodified_drivers/linux-2.6/overrides.mk +++ b/unmodified_drivers/linux-2.6/overrides.mk @@ -6,3 +6,6 @@ # a Xen kernel to find the right headers) EXTRA_CFLAGS += -D__XEN_INTERFACE_VERSION__=0x00030202 EXTRA_CFLAGS += -I$(M)/include -I$(M)/compat-include -DHAVE_XEN_PLATFORM_COMPAT_H +ifeq ($(ARCH),ia64) + EXTRA_CFLAGS += -DCONFIG_VMX_GUEST +endif diff --git a/unmodified_drivers/linux-2.6/platform-pci/platform-compat.c b/unmodified_drivers/linux-2.6/platform-pci/platform-compat.c index 5a0bb9bce8..7e1ad1f169 100644 --- a/unmodified_drivers/linux-2.6/platform-pci/platform-compat.c +++ b/unmodified_drivers/linux-2.6/platform-pci/platform-compat.c @@ -13,6 +13,12 @@ static int system_state = 1; EXPORT_SYMBOL(system_state); #endif +static inline void ctrl_alt_del(void) +{ + kill_proc(1, SIGINT, 1); /* interrupt init */ +} +EXPORT_SYMBOL(ctrl_alt_del); + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) size_t strcspn(const char *s, const char *reject) { diff --git a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c index e6ff4107cb..bb7120b028 100644 --- a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c +++ b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c @@ -118,14 +118,10 @@ unsigned long alloc_xen_mmio(unsigned long len) { unsigned long addr; - addr = 0; - if (platform_mmio_alloc + len <= platform_mmiolen) - { - addr = platform_mmio + platform_mmio_alloc; - platform_mmio_alloc += len; - } else { - panic("ran out of xen mmio space"); - } + addr = platform_mmio + platform_mmio_alloc; + platform_mmio_alloc += len; + BUG_ON(platform_mmio_alloc > platform_mmiolen); + return addr; } @@ -181,23 +177,19 @@ static int get_hypercall_stubs(void) static uint64_t get_callback_via(struct pci_dev *pdev) { + u8 pin; + int irq; + #ifdef __ia64__ - int irq, rid; for (irq = 0; irq < 16; irq++) { if (isa_irq_to_vector(irq) == pdev->irq) - return irq; + return irq; /* ISA IRQ */ } - /* use Requester-ID as callback_irq */ - /* RID: '<#bus(8)><#dev(5)><#func(3)>' (cf. PCI-Express spec) */ - rid = ((pdev->bus->number & 0xff) << 8) | pdev->devfn; - printk(KERN_INFO DRV_NAME ":use Requester-ID(%04x) as callback irq\n", - rid); - return rid | IA64_CALLBACK_IRQ_RID; #else /* !__ia64__ */ - u8 pin; - - if (pdev->irq < 16) - return pdev->irq; /* ISA IRQ */ + irq = pdev->irq; + if (irq < 16) + return irq; /* ISA IRQ */ +#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) pin = pdev->pin; @@ -211,7 +203,6 @@ static uint64_t get_callback_via(struct pci_dev *pdev) ((uint64_t)pdev->bus->number << 16) | ((uint64_t)(pdev->devfn & 0xff) << 8) | ((uint64_t)(pin - 1) & 3)); -#endif } /* Invalidate foreign mappings (e.g., in qemu-based device model). */ diff --git a/unmodified_drivers/linux-2.6/platform-pci/xen_support.c b/unmodified_drivers/linux-2.6/platform-pci/xen_support.c index 423d2f2e24..589d8365ec 100644 --- a/unmodified_drivers/linux-2.6/platform-pci/xen_support.c +++ b/unmodified_drivers/linux-2.6/platform-pci/xen_support.c @@ -30,6 +30,23 @@ #include #endif +#if defined (__ia64__) +unsigned long __hypercall(unsigned long a1, unsigned long a2, + unsigned long a3, unsigned long a4, + unsigned long a5, unsigned long cmd) +{ + unsigned long __res; + __asm__ __volatile__ (";;\n" + "mov r2=%1\n" + "break 0x1000 ;;\n" + "mov %0=r8 ;;\n" + : "=r"(__res) : "r"(cmd) : "r2", "r8", "memory"); + + return __res; +} +EXPORT_SYMBOL(__hypercall); +#endif + void xen_machphys_update(unsigned long mfn, unsigned long pfn) { BUG(); diff --git a/xen/arch/ia64/Rules.mk b/xen/arch/ia64/Rules.mk index e63faf67ef..eefd5fe1ab 100644 --- a/xen/arch/ia64/Rules.mk +++ b/xen/arch/ia64/Rules.mk @@ -4,7 +4,6 @@ HAS_ACPI := y HAS_VGA := y xenoprof := y -VALIDATE_VT ?= n no_warns ?= n xen_ia64_expose_p2m ?= y xen_ia64_pervcpu_vhpt ?= y @@ -37,9 +36,6 @@ CFLAGS += -DIA64 -DXEN -DLINUX_2_6 CFLAGS += -ffixed-r13 -mfixed-range=f2-f5,f12-f127 CFLAGS += -g #CFLAGS += -DVTI_DEBUG -ifeq ($(VALIDATE_VT),y) -CFLAGS += -DVALIDATE_VT -endif ifeq ($(xen_ia64_expose_p2m),y) CFLAGS += -DCONFIG_XEN_IA64_EXPOSE_P2M endif diff --git a/xen/arch/ia64/asm-offsets.c b/xen/arch/ia64/asm-offsets.c index 571f396e96..6105406441 100644 --- a/xen/arch/ia64/asm-offsets.c +++ b/xen/arch/ia64/asm-offsets.c @@ -57,6 +57,7 @@ void foo(void) DEFINE(IA64_VCPU_DOMAIN_OFFSET, offsetof (struct vcpu, domain)); DEFINE(IA64_VCPU_HYPERCALL_CONTINUATION_OFS, offsetof (struct vcpu, arch.hypercall_continuation)); + DEFINE(IA64_VCPU_FP_PSR_OFFSET, offsetof (struct vcpu, arch.fp_psr)); DEFINE(IA64_VCPU_META_RR0_OFFSET, offsetof (struct vcpu, arch.metaphysical_rr0)); DEFINE(IA64_VCPU_META_SAVED_RR0_OFFSET, offsetof (struct vcpu, arch.metaphysical_saved_rr0)); DEFINE(IA64_VCPU_BREAKIMM_OFFSET, offsetof (struct vcpu, arch.breakimm)); @@ -199,6 +200,7 @@ void foo(void) DEFINE(IA64_VPD_BASE_OFFSET, offsetof (struct vcpu, arch.privregs)); DEFINE(IA64_VPD_VIFS_OFFSET, offsetof (mapped_regs_t, ifs)); DEFINE(IA64_VLSAPIC_INSVC_BASE_OFFSET, offsetof (struct vcpu, arch.insvc[0])); + DEFINE(IA64_VPD_VPTA_OFFSET, offsetof (struct mapped_regs, pta)); DEFINE(IA64_VPD_CR_VPTA_OFFSET, offsetof (cr_t, pta)); DEFINE(XXX_THASH_SIZE, sizeof (thash_data_t)); diff --git a/xen/arch/ia64/asm-xsi-offsets.c b/xen/arch/ia64/asm-xsi-offsets.c index e3696909da..4e84d41077 100755 --- a/xen/arch/ia64/asm-xsi-offsets.c +++ b/xen/arch/ia64/asm-xsi-offsets.c @@ -61,6 +61,8 @@ void foo(void) DEFINE_MAPPED_REG_OFS(XSI_ITIR_OFS, itir); DEFINE_MAPPED_REG_OFS(XSI_ITV_OFS, itv); DEFINE_MAPPED_REG_OFS(XSI_PTA_OFS, pta); + DEFINE_MAPPED_REG_OFS(XSI_VPSR_DFH_OFS, vpsr_dfh); + DEFINE_MAPPED_REG_OFS(XSI_HPSR_DFH_OFS, hpsr_dfh); DEFINE_MAPPED_REG_OFS(XSI_PSR_IC_OFS, interrupt_collection_enabled); DEFINE_MAPPED_REG_OFS(XSI_VPSR_PP_OFS, vpsr_pp); DEFINE_MAPPED_REG_OFS(XSI_METAPHYS_OFS, metaphysical_mode); diff --git a/xen/arch/ia64/linux-xen/head.S b/xen/arch/ia64/linux-xen/head.S index 22145109da..5c8c60cbb6 100644 --- a/xen/arch/ia64/linux-xen/head.S +++ b/xen/arch/ia64/linux-xen/head.S @@ -267,13 +267,8 @@ start_ap: /* * Switch into virtual mode: */ -#if defined(XEN) && defined(VALIDATE_VT) - movl r16=(IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH\ - |IA64_PSR_DI) -#else movl r16=(IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN \ |IA64_PSR_DI) -#endif ;; mov cr.ipsr=r16 movl r17=1f @@ -292,11 +287,7 @@ start_ap: ;; // set IVT entry point---can't access I/O ports without it -#if defined(XEN) && defined(VALIDATE_VT) - movl r3=vmx_ia64_ivt -#else movl r3=ia64_ivt -#endif ;; mov cr.iva=r3 movl r2=FPSR_DEFAULT @@ -368,15 +359,8 @@ start_ap: .load_current: // load the "current" pointer (r13) and ar.k6 with the current task -#if defined(XEN) && defined(VALIDATE_VT) - mov r21=r2 - ;; - bsw.1 - ;; -#else mov IA64_KR(CURRENT)=r2 // virtual address mov IA64_KR(CURRENT_STACK)=r16 -#endif mov r13=r2 /* * Reserve space at the top of the stack for "struct pt_regs". Kernel diff --git a/xen/arch/ia64/linux-xen/mca.c b/xen/arch/ia64/linux-xen/mca.c index 8715ef1d5e..5a820973b4 100644 --- a/xen/arch/ia64/linux-xen/mca.c +++ b/xen/arch/ia64/linux-xen/mca.c @@ -84,6 +84,7 @@ #include #include #include +#include #endif #if defined(IA64_MCA_DEBUG_INFO) @@ -684,16 +685,8 @@ fetch_min_state (pal_min_state_area_t *ms, struct pt_regs *pt, struct switch_sta #ifdef XEN static spinlock_t init_dump_lock = SPIN_LOCK_UNLOCKED; static spinlock_t show_stack_lock = SPIN_LOCK_UNLOCKED; - -static void -save_ksp (struct unw_frame_info *info, void *arg) -{ - current->arch._thread.ksp = (__u64)(info->sw) - 16; - wmb(); -} - -/* FIXME */ -int try_crashdump(struct pt_regs *a) { return 0; } +static atomic_t num_stopped_cpus = ATOMIC_INIT(0); +extern void show_stack (struct task_struct *, unsigned long *); #define CPU_FLUSH_RETRY_MAX 5 static void @@ -716,6 +709,35 @@ init_cache_flush (void) } printk("\nPAL cache flush failed. status=%ld\n",rval); } + +static void inline +save_ksp (struct unw_frame_info *info) +{ + current->arch._thread.ksp = (__u64)(info->sw) - 16; + wmb(); + init_cache_flush(); +} + +static void +freeze_cpu_osinit (struct unw_frame_info *info, void *arg) +{ + save_ksp(info); + atomic_inc(&num_stopped_cpus); + printk("%s: CPU%d init handler done\n", + __FUNCTION__, smp_processor_id()); + for (;;) + local_irq_disable(); +} + +/* FIXME */ +static void +try_crashdump(struct unw_frame_info *info, void *arg) +{ + save_ksp(info); + printk("\nINIT dump complete. Please reboot now.\n"); + for (;;) + local_irq_disable(); +} #endif /* XEN */ static void @@ -741,7 +763,8 @@ init_handler_platform (pal_min_state_area_t *ms, show_min_state(ms); #ifdef XEN - printk("Backtrace of current vcpu (vcpu_id %d)\n", current->vcpu_id); + printk("Backtrace of current vcpu (vcpu_id %d of domid %d)\n", + current->vcpu_id, current->domain->domain_id); #else printk("Backtrace of current task (pid %d, %s)\n", current->pid, current->comm); fetch_min_state(ms, pt, sw); @@ -749,20 +772,35 @@ init_handler_platform (pal_min_state_area_t *ms, unw_init_from_interruption(&info, current, pt, sw); ia64_do_show_stack(&info, NULL); #ifdef XEN - unw_init_running(save_ksp, NULL); spin_unlock(&show_stack_lock); - wmb(); - init_cache_flush(); if (spin_trylock(&init_dump_lock)) { + struct domain *d; + struct vcpu *v; #ifdef CONFIG_SMP - udelay(5*1000000); + int other_cpus = num_online_cpus() - 1; + int wait = 1000 * other_cpus; + + while ((atomic_read(&num_stopped_cpus) != other_cpus) && wait--) + udelay(1000); + if (other_cpus && wait < 0) + printk("timeout %d\n", atomic_read(&num_stopped_cpus)); #endif - if (try_crashdump(pt) == 0) - printk("\nINIT dump complete. Please reboot now.\n"); + if (opt_noreboot) { + /* this route is for dump routine */ + unw_init_running(try_crashdump, pt); + } else { + for_each_domain(d) { + for_each_vcpu(d, v) { + printk("Backtrace of current vcpu " + "(vcpu_id %d of domid %d)\n", + v->vcpu_id, d->domain_id); + show_stack(v, NULL); + } + } + } } - printk("%s: CPU%d init handler done\n", - __FUNCTION__, smp_processor_id()); + unw_init_running(freeze_cpu_osinit, NULL); #else /* XEN */ #ifdef CONFIG_SMP /* read_trylock() would be handy... */ diff --git a/xen/arch/ia64/vmx/optvfault.S b/xen/arch/ia64/vmx/optvfault.S index cadf461752..cf827ed98b 100644 --- a/xen/arch/ia64/vmx/optvfault.S +++ b/xen/arch/ia64/vmx/optvfault.S @@ -15,6 +15,7 @@ #include #include #include +#include #define ACCE_MOV_FROM_AR #define ACCE_MOV_FROM_RR @@ -22,6 +23,7 @@ #define ACCE_RSM #define ACCE_SSM #define ACCE_MOV_TO_PSR +#define ACCE_THASH //mov r1=ar3 GLOBAL_ENTRY(vmx_asm_mov_from_ar) @@ -192,6 +194,13 @@ GLOBAL_ENTRY(vmx_asm_rsm) ;; st8 [r17]=r19 and r20=r20,r28 + adds r27=IA64_VCPU_FP_PSR_OFFSET,r21 + ;; + ld8 r27=[r27] + ;; + tbit.nz p8,p0= r27,IA64_PSR_DFH_BIT + ;; + (p8) dep r20=-1,r20,IA64_PSR_DFH_BIT,1 ;; mov cr.ipsr=r20 tbit.nz p6,p0=r23,0 @@ -360,6 +369,14 @@ vmx_asm_mov_to_psr_1: add r20=r19,r20 mov b0=r24 ;; + adds r27=IA64_VCPU_FP_PSR_OFFSET,r21 + ;; + ld8 r27=[r27] + ;; + tbit.nz p8,p0=r27,IA64_PSR_DFH_BIT + ;; + (p8) dep r20=-1,r20,IA64_PSR_DFH_BIT,1 + ;; mov cr.ipsr=r20 cmp.ne p6,p0=r0,r0 ;; @@ -403,6 +420,64 @@ ENTRY(vmx_asm_dispatch_vexirq) br.many vmx_dispatch_vexirq END(vmx_asm_dispatch_vexirq) +// thash +// TODO: add support when pta.vf = 1 +GLOBAL_ENTRY(vmx_asm_thash) +#ifndef ACCE_THASH + br.many vmx_virtualization_fault_back +#endif + extr.u r17=r25,20,7 // get r3 from opcode in r25 + extr.u r18=r25,6,7 // get r1 from opcode in r25 + movl r20=asm_mov_from_reg + ;; + adds r30=vmx_asm_thash_back1-asm_mov_from_reg,r20 + shladd r17=r17,4,r20 // get addr of MOVE_FROM_REG(r17) + adds r16=IA64_VPD_BASE_OFFSET,r21 // get vcpu.arch.priveregs + ;; + mov r24=b0 + ;; + ld8 r16=[r16] // get VPD addr + mov b0=r17 + br.many b0 // r19 return value + ;; +vmx_asm_thash_back1: + shr.u r23=r19,61 // get RR number + adds r25=VCPU_VRR0_OFS,r21 // get vcpu->arch.arch_vmx.vrr[0]'s addr + adds r16=IA64_VPD_VPTA_OFFSET,r16 // get vpta + ;; + shladd r27=r23,3,r25 // get vcpu->arch.arch_vmx.vrr[r23]'s addr + ld8 r17=[r16] // get PTA + mov r26=1 + ;; + extr.u r29=r17,2,6 // get pta.size + ld8 r25=[r27] // get vcpu->arch.arch_vmx.vrr[r23]'s value + ;; + extr.u r25=r25,2,6 // get rr.ps + shl r22=r26,r29 // 1UL << pta.size + ;; + shr.u r23=r19,r25 // vaddr >> rr.ps + adds r26=3,r29 // pta.size + 3 + shl r27=r17,3 // pta << 3 + ;; + shl r23=r23,3 // (vaddr >> rr.ps) << 3 + shr.u r27=r27,r26 // (pta << 3) >> (pta.size+3) + movl r16=VRN_MASK + ;; + adds r22=-1,r22 // (1UL << pta.size) - 1 + shl r27=r27,r29 // ((pta<<3)>>(pta.size+3))<>(pta.size + 3))<pending = 1; - update_last_itc(vtm, VCPU(vcpu, itm)); // update vITC + /* + * "+ 1" is for fixing oops message at timer_interrupt() on VTI guest. + * If oops checking condition changed to timer_after_eq() on VTI guest, + * this parameter should be erased. + */ + update_last_itc(vtm, VCPU(vcpu, itm) + 1); // update vITC } void vtm_init(VCPU *vcpu) diff --git a/xen/arch/ia64/vmx/vmmu.c b/xen/arch/ia64/vmx/vmmu.c index 625bf6dbcf..9d1c26ca05 100644 --- a/xen/arch/ia64/vmx/vmmu.c +++ b/xen/arch/ia64/vmx/vmmu.c @@ -129,13 +129,15 @@ purge_machine_tc_by_domid(domid_t domid) #endif } -static void init_domain_vhpt(struct vcpu *v) +static int init_domain_vhpt(struct vcpu *v) { struct page_info *page; void * vbase; page = alloc_domheap_pages (NULL, VCPU_VHPT_ORDER, 0); if ( page == NULL ) { - panic_domain(vcpu_regs(v),"No enough contiguous memory for init_domain_vhpt\n"); + printk("No enough contiguous memory for init_domain_vhpt\n"); + + return -1; } vbase = page_to_virt(page); memset(vbase, 0, VCPU_VHPT_SIZE); @@ -147,18 +149,36 @@ static void init_domain_vhpt(struct vcpu *v) VHPT(v,cch_sz) = VCPU_VHPT_SIZE - VHPT(v,hash_sz); thash_init(&(v->arch.vhpt),VCPU_VHPT_SHIFT-1); v->arch.arch_vmx.mpta = v->arch.vhpt.pta.val; + + return 0; } +static void free_domain_vhpt(struct vcpu *v) +{ + struct page_info *page; -void init_domain_tlb(struct vcpu *v) + if (v->arch.vhpt.hash) { + page = virt_to_page(v->arch.vhpt.hash); + free_domheap_pages(page, VCPU_VHPT_ORDER); + } + + return; +} + +int init_domain_tlb(struct vcpu *v) { struct page_info *page; void * vbase; - init_domain_vhpt(v); + + if (init_domain_vhpt(v) != 0) + return -1; + page = alloc_domheap_pages (NULL, VCPU_VTLB_ORDER, 0); if ( page == NULL ) { - panic_domain(vcpu_regs(v),"No enough contiguous memory for init_domain_tlb\n"); + printk("No enough contiguous memory for init_domain_tlb\n"); + free_domain_vhpt(v); + return -1; } vbase = page_to_virt(page); memset(vbase, 0, VCPU_VTLB_SIZE); @@ -169,8 +189,11 @@ void init_domain_tlb(struct vcpu *v) VTLB(v,cch_buf) = (void *)((u64)vbase + VTLB(v,hash_sz)); VTLB(v,cch_sz) = VCPU_VTLB_SIZE - VTLB(v,hash_sz); thash_init(&(v->arch.vtlb),VCPU_VTLB_SHIFT-1); + + return 0; } + void free_domain_tlb(struct vcpu *v) { struct page_info *page; @@ -179,10 +202,8 @@ void free_domain_tlb(struct vcpu *v) page = virt_to_page(v->arch.vtlb.hash); free_domheap_pages(page, VCPU_VTLB_ORDER); } - if ( v->arch.vhpt.hash) { - page = virt_to_page(v->arch.vhpt.hash); - free_domheap_pages(page, VCPU_VHPT_ORDER); - } + + free_domain_vhpt(v); } /* @@ -553,7 +574,8 @@ static void ptc_ga_remote_func (void *varg) mpta = ia64_get_pta(); ia64_set_pta(v->arch.arch_vmx.mpta&(~1)); ia64_srlz_d(); - vmx_vcpu_ptc_l(v, REGION_OFFSET(vadr), args->ps); + vadr = PAGEALIGN(vadr, args->ps); + thash_purge_entries_remote(v, vadr, args->ps); VMX(v, vrr[0]) = oldrid; VMX(v, psbits[0]) = oldpsbits; ia64_set_rr(0x0,moldrid); diff --git a/xen/arch/ia64/vmx/vmx_entry.S b/xen/arch/ia64/vmx/vmx_entry.S index fa2a53670f..74bf2ca4d3 100644 --- a/xen/arch/ia64/vmx/vmx_entry.S +++ b/xen/arch/ia64/vmx/vmx_entry.S @@ -190,12 +190,8 @@ GLOBAL_ENTRY(ia64_leave_hypervisor) PT_REGS_UNWIND_INFO(0) rsm psr.i ;; - alloc loc0=ar.pfs,0,1,1,0 - ;; - adds out0=16,r12 br.call.sptk.many b0=leave_hypervisor_tail ;; - mov ar.pfs=loc0 adds r20=PT(PR)+16,r12 adds r8=PT(EML_UNAT)+16,r12 ;; @@ -302,11 +298,9 @@ GLOBAL_ENTRY(ia64_leave_hypervisor) ;; mov ar.fpsr=r19 mov ar.ccv=r18 - ;; -//rbs_switch - shr.u r18=r20,16 ;; +vmx_rbs_switch: movl r19= THIS_CPU(ia64_phys_stacked_size_p8) ;; ld4 r19=[r19] @@ -368,7 +362,7 @@ vmx_rse_clear_invalid: ;; mov cr.ipsr=r31 mov cr.iip=r30 - mov cr.ifs=r29 +(pNonSys) mov cr.ifs=r29 mov ar.pfs=r27 adds r18=IA64_VPD_BASE_OFFSET,r21 ;; @@ -425,148 +419,190 @@ ia64_vmm_entry_out: END(ia64_vmm_entry) -#ifdef XEN_DBL_MAPPING /* will be removed */ - -#define VMX_PURGE_RR7 0 -#define VMX_INSERT_RR7 1 -/* - * in0: old rr7 - * in1: virtual address of xen image - * in2: virtual address of vhpt table - */ -GLOBAL_ENTRY(vmx_purge_double_mapping) - alloc loc1 = ar.pfs,5,9,0,0 - mov loc0 = rp - movl r8 = 1f - ;; - movl loc4 = KERNEL_TR_PAGE_SHIFT - movl loc5 = VCPU_TLB_SHIFT - mov loc6 = psr - movl loc7 = XEN_RR7_SWITCH_STUB - mov loc8 = (1<flags needs to be check for + * extra work. We always check for extra work when returning to user-level. + * With CONFIG_PREEMPT, we also check for extra work when the preempt_count + * is 0. After extra work processing has been completed, execution + * resumes at .work_processed_syscall with p6 set to 1 if the extra-work-check + * needs to be redone. + */ +(pUStk) rsm psr.i + cmp.eq pLvSys,p0=r0,r0 // pLvSys=1: leave from syscall +(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk ;; - tbit.nz p6,p7=loc8, VMX_INSERT_RR7 - mov r8 = rr[loc7] + br.call.sptk.many b0=leave_hypervisor_tail +.work_processed_syscall: + //clean up bank 1 registers + mov r16=r0 + mov r17=r0 + mov r18=r0 + mov r19=r0 + mov r20=r0 + mov r21=r0 + mov r22=r0 + mov r23=r0 + mov r24=r0 + mov r25=r0 + mov r26=r0 + mov r27=r0 + mov r28=r0 + mov r29=r0 + mov r30=r0 + mov r31=r0 + bsw.0 ;; - mov rr[loc7] = in0 -(p6)mov cr.ifa = in1 -(p6)mov cr.itir = loc4 + adds r2=PT(LOADRS)+16,r12 + adds r3=PT(AR_BSPSTORE)+16,r12 +#ifndef XEN + adds r18=TI_FLAGS+IA64_TASK_SIZE,r13 ;; - srlz.i +(p6) ld4 r31=[r18] // load current_thread_info()->flags +#endif ;; -(p6)itr.i itr[loc2] = in3 -(p7)ptr.i in1, loc4 + ld8 r20=[r2],PT(B6)-PT(LOADRS) // load ar.rsc value for "loadrs" + nop.i 0 ;; -(p6)itr.d dtr[loc2] = in3 -(p7)ptr.d in1, loc4 +// mov r16=ar.bsp // M2 get existing backing store pointer + ld8 r18=[r2],PT(R9)-PT(B6) // load b6 +#ifndef XEN +(p6) and r15=TIF_WORK_MASK,r31 // any work other than TIF_SYSCALL_TRACE? +#endif ;; - srlz.i + ld8 r24=[r3],PT(R11)-PT(AR_BSPSTORE) // load ar.bspstore (may be garbage) +#ifndef XEN +(p6) cmp4.ne.unc p6,p0=r15, r0 // any special work pending? +(p6) br.cond.spnt .work_pending_syscall +#endif ;; -(p6)mov cr.ifa = in2 -(p6)mov cr.itir = loc5 + // start restoring the state saved on the kernel stack (struct pt_regs): + ld8 r9=[r2],PT(CR_IPSR)-PT(R9) + ld8 r11=[r3],PT(CR_IIP)-PT(R11) +//(pNonSys) break 0 // bug check: we shouldn't be here if pNonSys is TRUE! ;; -(p6)itr.d dtr[loc3] = in4 -(p7)ptr.d in2, loc5 - ;; - srlz.i - ;; - mov rr[loc7] = r8 - ;; - srlz.i - br.sptk rp -END(vmx_switch_rr7) - .align PAGE_SIZE + invala // M0|1 invalidate ALAT + rsm psr.i | psr.ic // M2 turn off interrupts and interruption collection + cmp.eq p9,p0=r0,r0 // A set p9 to indicate that we should restore cr.ifs + ld8 r31=[r2],32 // M0|1 load cr.ipsr + ld8 r30=[r3],16 // M0|1 load cr.iip + ;; +// ld8 r29=[r2],16 // M0|1 load cr.ifs + ld8 r28=[r3],16 // M0|1 load ar.unat +//(pUStk) add r14=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13 + ;; + ld8 r27=[r2],PT(B0)-PT(AR_PFS) // M0|1 load ar.pfs +(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled + nop 0 + ;; + ld8 r22=[r2],PT(AR_RNAT)-PT(B0) // M0|1 load b0 + ld8 r26=[r3],PT(PR)-PT(AR_RSC) // M0|1 load ar.rsc + mov f6=f0 // F clear f6 + ;; + ld8 r25=[r2],PT(AR_FPSR)-PT(AR_RNAT) // M0|1 load ar.rnat (may be garbage) + ld8 r23=[r3],PT(R1)-PT(PR) // M0|1 load predicates + mov f7=f0 // F clear f7 + ;; + ld8 r20=[r2],PT(R12)-PT(AR_FPSR) // M0|1 load ar.fpsr + ld8.fill r1=[r3],16 // M0|1 load r1 +//(pUStk) mov r17=1 // A + ;; +//(pUStk) st1 [r14]=r17 // M2|3 + ld8.fill r13=[r3],16 // M0|1 + mov f8=f0 // F clear f8 + ;; + ld8.fill r12=[r2] // M0|1 restore r12 (sp) +#ifdef XEN + ld8.fill r2=[r3] // M0|1 +#else + ld8.fill r15=[r3] // M0|1 restore r15 +#endif + mov b6=r18 // I0 restore b6 + mov ar.fpsr=r20 +// addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0 // A + mov f9=f0 // F clear f9 +//(pKStk) br.cond.dpnt.many skip_rbs_switch // B + +// srlz.d // M0 ensure interruption collection is off (for cover) +// shr.u r18=r19,16 // I0|1 get byte size of existing "dirty" partition + mov r3=r21 + cover // B add current frame into dirty partition & set cr.ifs + ;; +//(pUStk) ld4 r17=[r17] // M0|1 r17 = cpu_data->phys_stacked_size_p8 + mov r19=ar.bsp // M2 get new backing store pointer + addl r18=IA64_RBS_OFFSET, r3 + ;; + mov r3=r0 + sub r18=r19,r18 // get byte size of existing "dirty" partition + ;; + shl r20=r18,16 // set rsc.load + mov f10=f0 // F clear f10 +#ifdef XEN + mov r14=r0 #else + movl r14=__kernel_syscall_via_epc // X +#endif + ;; + mov.m ar.csd=r0 // M2 clear ar.csd + mov.m ar.ccv=r0 // M2 clear ar.ccv + mov b7=r14 // I0 clear b7 (hint with __kernel_syscall_via_epc) + + mov.m ar.ssd=r0 // M2 clear ar.ssd + mov f11=f0 // F clear f11 + br.cond.sptk.many vmx_rbs_switch // B +END(ia64_leave_hypercall) + + /* * in0: new rr7 * in1: virtual address of shared_info @@ -707,5 +743,3 @@ GLOBAL_ENTRY(vmx_switch_rr7) srlz.d // seralize restoration of psr.l br.ret.sptk.many rp END(vmx_switch_rr7) -#endif - diff --git a/xen/arch/ia64/vmx/vmx_init.c b/xen/arch/ia64/vmx/vmx_init.c index c4cb0150ea..2ae82ed086 100644 --- a/xen/arch/ia64/vmx/vmx_init.c +++ b/xen/arch/ia64/vmx/vmx_init.c @@ -290,7 +290,7 @@ static void vmx_release_assist_channel(struct vcpu *v) * Initialize VMX envirenment for guest. Only the 1st vp/vcpu * is registered here. */ -void +int vmx_final_setup_guest(struct vcpu *v) { vpd_t *vpd; @@ -305,7 +305,8 @@ vmx_final_setup_guest(struct vcpu *v) * to this solution. Maybe it can be deferred until we know created * one as vmx domain */ #ifndef HASH_VHPT - init_domain_tlb(v); + if (init_domain_tlb(v) != 0) + return -1; #endif vmx_create_event_channels(v); @@ -322,6 +323,8 @@ vmx_final_setup_guest(struct vcpu *v) /* Set up guest 's indicator for VTi domain*/ set_bit(ARCH_VMX_DOMAIN, &v->arch.arch_vmx.flags); + + return 0; } void diff --git a/xen/arch/ia64/vmx/vmx_interrupt.c b/xen/arch/ia64/vmx/vmx_interrupt.c index 211aa93b36..7dc4db744c 100644 --- a/xen/arch/ia64/vmx/vmx_interrupt.c +++ b/xen/arch/ia64/vmx/vmx_interrupt.c @@ -99,7 +99,7 @@ inject_guest_interruption(VCPU *vcpu, u64 vec) pt_isr.ir = 0; VMX(vcpu,cr_isr) = pt_isr.val; collect_interruption(vcpu); - + vmx_ia64_set_dcr(vcpu); vmx_vcpu_get_iva(vcpu,&viva); regs->cr_iip = viva + vec; } diff --git a/xen/arch/ia64/vmx/vmx_ivt.S b/xen/arch/ia64/vmx/vmx_ivt.S index 755539c09c..de2b0ba9eb 100644 --- a/xen/arch/ia64/vmx/vmx_ivt.S +++ b/xen/arch/ia64/vmx/vmx_ivt.S @@ -59,6 +59,14 @@ #include #include #include +#include + +#if 1 +# define PSR_DEFAULT_BITS psr.ac +#else +# define PSR_DEFAULT_BITS 0 +#endif + #ifdef VTI_DEBUG /* @@ -431,17 +439,152 @@ ENTRY(vmx_break_fault) VMX_DBG_FAULT(11) mov r31=pr mov r19=11 - mov r30=cr.iim + mov r17=cr.iim ;; #ifdef VTI_DEBUG // break 0 is already handled in vmx_ia64_handle_break. - cmp.eq p6,p7=r30,r0 + cmp.eq p6,p7=r17,r0 (p6) br.sptk vmx_fault_11 ;; #endif - br.sptk.many vmx_dispatch_break_fault + mov r29=cr.ipsr + adds r22=IA64_VCPU_BREAKIMM_OFFSET, r21 ;; - VMX_FAULT(11); + ld4 r22=[r22] + extr.u r24=r29,IA64_PSR_CPL0_BIT,2 + cmp.eq p0,p6=r0,r0 + ;; + cmp.ne.or p6,p0=r22,r17 + cmp.ne.or p6,p0=r0,r24 +(p6) br.sptk.many vmx_dispatch_break_fault + ;; + /* + * The streamlined system call entry/exit paths only save/restore the initial part + * of pt_regs. This implies that the callers of system-calls must adhere to the + * normal procedure calling conventions. + * + * Registers to be saved & restored: + * CR registers: cr.ipsr, cr.iip, cr.ifs + * AR registers: ar.unat, ar.pfs, ar.rsc, ar.rnat, ar.bspstore, ar.fpsr + * others: pr, b0, b6, loadrs, r1, r11, r12, r13, r15 + * Registers to be restored only: + * r8-r11: output value from the system call. + * + * During system call exit, scratch registers (including r15) are modified/cleared + * to prevent leaking bits from kernel to user level. + */ + +// mov.m r16=IA64_KR(CURRENT) // M2 r16 <- current task (12 cyc) + mov r14=r21 + bsw.1 // B (6 cyc) regs are saved, switch to bank 1 + ;; + mov r29=cr.ipsr // M2 (12 cyc) + mov r31=pr // I0 (2 cyc) + mov r16=r14 + mov r15=r2 + + mov r17=cr.iim // M2 (2 cyc) + mov.m r27=ar.rsc // M2 (12 cyc) +// mov r18=__IA64_BREAK_SYSCALL // A + + mov.m ar.rsc=0 // M2 + mov.m r21=ar.fpsr // M2 (12 cyc) + mov r19=b6 // I0 (2 cyc) + ;; + mov.m r23=ar.bspstore // M2 (12 cyc) + mov.m r24=ar.rnat // M2 (5 cyc) + mov.i r26=ar.pfs // I0 (2 cyc) + + invala // M0|1 + nop.m 0 // M + mov r20=r1 // A save r1 + + nop.m 0 +// movl r30=sys_call_table // X + movl r30=ia64_hypercall_table // X + + mov r28=cr.iip // M2 (2 cyc) +// cmp.eq p0,p7=r18,r17 // I0 is this a system call? +//(p7) br.cond.spnt non_syscall // B no -> + // + // From this point on, we are definitely on the syscall-path + // and we can use (non-banked) scratch registers. + // +/////////////////////////////////////////////////////////////////////// + mov r1=r16 // A move task-pointer to "addl"-addressable reg + mov r2=r16 // A setup r2 for ia64_syscall_setup +// add r9=TI_FLAGS+IA64_TASK_SIZE,r16 // A r9 = ¤t_thread_info()->flags + +// adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16 +// adds r15=-1024,r15 // A subtract 1024 from syscall number +// mov r3=NR_syscalls - 1 + mov r3=NR_hypercalls - 1 + ;; +// ld1.bias r17=[r16] // M0|1 r17 = current->thread.on_ustack flag +// ld4 r9=[r9] // M0|1 r9 = current_thread_info()->flags + mov r9=r0 // force flags = 0 + extr.u r8=r29,41,2 // I0 extract ei field from cr.ipsr + + shladd r30=r15,3,r30 // A r30 = sys_call_table + 8*(syscall-1024) + addl r22=IA64_RBS_OFFSET,r1 // A compute base of RBS + cmp.leu p6,p7=r15,r3 // A syscall number in range? + ;; + + lfetch.fault.excl.nt1 [r22] // M0|1 prefetch RBS +(p6) ld8 r30=[r30] // M0|1 load address of syscall entry point + tnat.nz.or p7,p0=r15 // I0 is syscall nr a NaT? + + mov.m ar.bspstore=r22 // M2 switch to kernel RBS + cmp.eq p8,p9=2,r8 // A isr.ei==2? + ;; + +(p8) mov r8=0 // A clear ei to 0 +//(p7) movl r30=sys_ni_syscall // X +(p7) movl r30=do_ni_hypercall // X + +(p8) adds r28=16,r28 // A switch cr.iip to next bundle +(p9) adds r8=1,r8 // A increment ei to next slot + nop.i 0 + ;; + + mov.m r25=ar.unat // M2 (5 cyc) + dep r29=r8,r29,41,2 // I0 insert new ei into cr.ipsr +// adds r15=1024,r15 // A restore original syscall number + // + // If any of the above loads miss in L1D, we'll stall here until + // the data arrives. + // +/////////////////////////////////////////////////////////////////////// +// st1 [r16]=r0 // M2|3 clear current->thread.on_ustack flag + mov b6=r30 // I0 setup syscall handler branch reg early + cmp.ne pKStk,pUStk=r0,r0 // A were we on kernel stacks already? + +// and r9=_TIF_SYSCALL_TRACEAUDIT,r9 // A mask trace or audit + mov r18=ar.bsp // M2 (12 cyc) + ;; +(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1 // A compute base of memory stack +// cmp.eq p14,p0=r9,r0 // A are syscalls being traced/audited? +// br.call.sptk.many b7=ia64_syscall_setup // B + br.call.sptk.many b7=ia64_hypercall_setup // B +1: + mov ar.rsc=0x3 // M2 set eager mode, pl 0, LE, loadrs=0 +// nop 0 +// bsw.1 // B (6 cyc) regs are saved, switch to bank 1 + ;; + ssm psr.ic | PSR_DEFAULT_BITS // M2 now it's safe to re-enable intr.-collection +// movl r3=ia64_ret_from_syscall // X + movl r3=ia64_leave_hypercall // X + ;; + + srlz.i // M0 ensure interruption collection is on + mov rp=r3 // I0 set the real return addr + //(p10) br.cond.spnt.many ia64_ret_from_syscall // B return if bad call-frame or r15 is a NaT + (p15) ssm psr.i // M2 restore psr.i + //(p14) br.call.sptk.many b6=b6 // B invoke syscall-handker (ignore return addr) + br.call.sptk.many b6=b6 // B invoke syscall-handker (ignore return addr) +// br.cond.spnt.many ia64_trace_syscall // B do syscall-tracing thingamagic + ;; + VMX_FAULT(11) END(vmx_break_fault) .org vmx_ia64_ivt+0x3000 @@ -613,6 +756,146 @@ END(vmx_virtual_exirq) // 0x3800 Entry 14 (size 64 bundles) Reserved VMX_DBG_FAULT(14) VMX_FAULT(14) + // this code segment is from 2.6.16.13 + + /* + * There is no particular reason for this code to be here, other than that + * there happens to be space here that would go unused otherwise. If this + * fault ever gets "unreserved", simply moved the following code to a more + * suitable spot... + * + * ia64_syscall_setup() is a separate subroutine so that it can + * allocate stacked registers so it can safely demine any + * potential NaT values from the input registers. + * + * On entry: + * - executing on bank 0 or bank 1 register set (doesn't matter) + * - r1: stack pointer + * - r2: current task pointer + * - r3: preserved + * - r11: original contents (saved ar.pfs to be saved) + * - r12: original contents (sp to be saved) + * - r13: original contents (tp to be saved) + * - r15: original contents (syscall # to be saved) + * - r18: saved bsp (after switching to kernel stack) + * - r19: saved b6 + * - r20: saved r1 (gp) + * - r21: saved ar.fpsr + * - r22: kernel's register backing store base (krbs_base) + * - r23: saved ar.bspstore + * - r24: saved ar.rnat + * - r25: saved ar.unat + * - r26: saved ar.pfs + * - r27: saved ar.rsc + * - r28: saved cr.iip + * - r29: saved cr.ipsr + * - r31: saved pr + * - b0: original contents (to be saved) + * On exit: + * - p10: TRUE if syscall is invoked with more than 8 out + * registers or r15's Nat is true + * - r1: kernel's gp + * - r3: preserved (same as on entry) + * - r8: -EINVAL if p10 is true + * - r12: points to kernel stack + * - r13: points to current task + * - r14: preserved (same as on entry) + * - p13: preserved + * - p15: TRUE if interrupts need to be re-enabled + * - ar.fpsr: set to kernel settings + * - b6: preserved (same as on entry) + */ +GLOBAL_ENTRY(ia64_hypercall_setup) +#if PT(B6) != 0 +# error This code assumes that b6 is the first field in pt_regs. +#endif + st8 [r1]=r19 // save b6 + add r16=PT(CR_IPSR),r1 // initialize first base pointer + add r17=PT(R11),r1 // initialize second base pointer + ;; + alloc r19=ar.pfs,8,0,0,0 // ensure in0-in7 are writable + st8 [r16]=r29,PT(AR_PFS)-PT(CR_IPSR) // save cr.ipsr + tnat.nz p8,p0=in0 + + st8.spill [r17]=r11,PT(CR_IIP)-PT(R11) // save r11 + tnat.nz p9,p0=in1 +(pKStk) mov r18=r0 // make sure r18 isn't NaT + ;; + + st8 [r16]=r26,PT(CR_IFS)-PT(AR_PFS) // save ar.pfs + st8 [r17]=r28,PT(AR_UNAT)-PT(CR_IIP) // save cr.iip + mov r28=b0 // save b0 (2 cyc) + ;; + + st8 [r17]=r25,PT(AR_RSC)-PT(AR_UNAT) // save ar.unat + dep r19=0,r19,38,26 // clear all bits but 0..37 [I0] +(p8) mov in0=-1 + ;; + + st8 [r16]=r19,PT(AR_RNAT)-PT(CR_IFS) // store ar.pfs.pfm in cr.ifs + extr.u r11=r19,7,7 // I0 // get sol of ar.pfs + and r8=0x7f,r19 // A // get sof of ar.pfs + + st8 [r17]=r27,PT(AR_BSPSTORE)-PT(AR_RSC)// save ar.rsc + tbit.nz p15,p0=r29,IA64_PSR_I_BIT // I0 +(p9) mov in1=-1 + ;; + +(pUStk) sub r18=r18,r22 // r18=RSE.ndirty*8 + tnat.nz p10,p0=in2 + add r11=8,r11 + ;; +(pKStk) adds r16=PT(PR)-PT(AR_RNAT),r16 // skip over ar_rnat field +(pKStk) adds r17=PT(B0)-PT(AR_BSPSTORE),r17 // skip over ar_bspstore field + tnat.nz p11,p0=in3 + ;; +(p10) mov in2=-1 + tnat.nz p12,p0=in4 // [I0] +(p11) mov in3=-1 + ;; +(pUStk) st8 [r16]=r24,PT(PR)-PT(AR_RNAT) // save ar.rnat +(pUStk) st8 [r17]=r23,PT(B0)-PT(AR_BSPSTORE) // save ar.bspstore + shl r18=r18,16 // compute ar.rsc to be used for "loadrs" + ;; + st8 [r16]=r31,PT(LOADRS)-PT(PR) // save predicates + st8 [r17]=r28,PT(R1)-PT(B0) // save b0 + tnat.nz p13,p0=in5 // [I0] + ;; + st8 [r16]=r18,PT(R12)-PT(LOADRS) // save ar.rsc value for "loadrs" + st8.spill [r17]=r20,PT(R13)-PT(R1) // save original r1 +(p12) mov in4=-1 + ;; + +.mem.offset 0,0; st8.spill [r16]=r12,PT(AR_FPSR)-PT(R12) // save r12 +.mem.offset 8,0; st8.spill [r17]=r13,PT(R15)-PT(R13) // save r13 +(p13) mov in5=-1 + ;; + st8 [r16]=r21,PT(R8)-PT(AR_FPSR) // save ar.fpsr + tnat.nz p13,p0=in6 + cmp.lt p10,p9=r11,r8 // frame size can't be more than local+8 + ;; + mov r8=1 +(p9) tnat.nz p10,p0=r15 + adds r12=-16,r1 // switch to kernel memory stack (with 16 bytes of scratch) + + st8.spill [r17]=r15 // save r15 + tnat.nz p8,p0=in7 + nop.i 0 + + mov r13=r2 // establish `current' + movl r1=__gp // establish kernel global pointer + ;; + st8 [r16]=r8 // ensure pt_regs.r8 != 0 (see handle_syscall_error) +(p13) mov in6=-1 +(p8) mov in7=-1 + + cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0 + movl r17=FPSR_DEFAULT + ;; + mov.m ar.fpsr=r17 // set ar.fpsr to kernel default value +(p10) mov r8=-EINVAL + br.ret.sptk.many b7 +END(ia64_hypercall_setup) .org vmx_ia64_ivt+0x3c00 @@ -795,12 +1078,14 @@ ENTRY(vmx_virtualization_fault) cmp.eq p9,p0=EVENT_RSM,r24 cmp.eq p10,p0=EVENT_SSM,r24 cmp.eq p11,p0=EVENT_MOV_TO_PSR,r24 + cmp.eq p12,p0=EVENT_THASH,r24 (p6) br.dptk.many vmx_asm_mov_from_ar (p7) br.dptk.many vmx_asm_mov_from_rr (p8) br.dptk.many vmx_asm_mov_to_rr (p9) br.dptk.many vmx_asm_rsm (p10) br.dptk.many vmx_asm_ssm (p11) br.dptk.many vmx_asm_mov_to_psr + (p12) br.dptk.many vmx_asm_thash ;; vmx_virtualization_fault_back: mov r19=37 diff --git a/xen/arch/ia64/vmx/vmx_minstate.h b/xen/arch/ia64/vmx/vmx_minstate.h index 8ac2c73f92..02a60ec07a 100644 --- a/xen/arch/ia64/vmx/vmx_minstate.h +++ b/xen/arch/ia64/vmx/vmx_minstate.h @@ -174,6 +174,7 @@ ;; \ st8 [r16]=r29,16; /* save b0 */ \ st8 [r17]=r18,16; /* save ar.rsc value for "loadrs" */ \ + cmp.eq pNonSys,pSys=r0,r0 /* initialize pSys=0, pNonSys=1 */ \ ;; \ .mem.offset 0,0; st8.spill [r16]=r20,16; /* save original r1 */ \ .mem.offset 8,0; st8.spill [r17]=r12,16; \ diff --git a/xen/arch/ia64/vmx/vmx_phy_mode.c b/xen/arch/ia64/vmx/vmx_phy_mode.c index ce4fd9036c..b6155aa670 100644 --- a/xen/arch/ia64/vmx/vmx_phy_mode.c +++ b/xen/arch/ia64/vmx/vmx_phy_mode.c @@ -188,7 +188,7 @@ vmx_load_all_rr(VCPU *vcpu) (void *)vcpu->arch.privregs, (void *)vcpu->arch.vhpt.hash, pal_vaddr ); ia64_set_pta(VMX(vcpu, mpta)); - ia64_set_dcr(VMX(vcpu, mdcr)); + vmx_ia64_set_dcr(vcpu); ia64_srlz_d(); ia64_set_psr(psr); diff --git a/xen/arch/ia64/vmx/vmx_process.c b/xen/arch/ia64/vmx/vmx_process.c index acce2c0bf9..308a4de0ba 100644 --- a/xen/arch/ia64/vmx/vmx_process.c +++ b/xen/arch/ia64/vmx/vmx_process.c @@ -79,36 +79,56 @@ static u64 vec2off[68] = {0x0,0x400,0x800,0xc00,0x1000,0x1400,0x1800, void vmx_reflect_interruption(u64 ifa, u64 isr, u64 iim, - u64 vector, REGS *regs) + u64 vec, REGS *regs) { - u64 status; + u64 status, vector; VCPU *vcpu = current; u64 vpsr = VCPU(vcpu, vpsr); - vector=vec2off[vector]; + + vector = vec2off[vec]; if(!(vpsr&IA64_PSR_IC)&&(vector!=IA64_DATA_NESTED_TLB_VECTOR)){ panic_domain(regs, "Guest nested fault vector=%lx!\n", vector); } - else{ // handle fpswa emulation + + switch (vec) { + + case 25: // IA64_DISABLED_FPREG_VECTOR + + if (FP_PSR(vcpu) & IA64_PSR_DFH) { + FP_PSR(vcpu) = IA64_PSR_MFH; + if (__ia64_per_cpu_var(fp_owner) != vcpu) + __ia64_load_fpu(vcpu->arch._thread.fph); + } + if (!(VCPU(vcpu, vpsr) & IA64_PSR_DFH)) { + regs->cr_ipsr &= ~IA64_PSR_DFH; + return; + } + + break; + + case 32: // IA64_FP_FAULT_VECTOR + // handle fpswa emulation // fp fault - if (vector == IA64_FP_FAULT_VECTOR) { - status = handle_fpu_swa(1, regs, isr); - if (!status) { - vcpu_increment_iip(vcpu); - return; - } else if (IA64_RETRY == status) - return; - } + status = handle_fpu_swa(1, regs, isr); + if (!status) { + vcpu_increment_iip(vcpu); + return; + } else if (IA64_RETRY == status) + return; + break; + + case 33: // IA64_FP_TRAP_VECTOR //fp trap - else if (vector == IA64_FP_TRAP_VECTOR) { - status = handle_fpu_swa(0, regs, isr); - if (!status) - return; - else if (IA64_RETRY == status) { - vcpu_decrement_iip(vcpu); - return; - } + status = handle_fpu_swa(0, regs, isr); + if (!status) + return; + else if (IA64_RETRY == status) { + vcpu_decrement_iip(vcpu); + return; } - } + break; + + } VCPU(vcpu,isr)=isr; VCPU(vcpu,iipa) = regs->cr_iip; if (vector == IA64_BREAK_VECTOR || vector == IA64_SPECULATION_VECTOR) @@ -194,7 +214,7 @@ void save_banked_regs_to_vpd(VCPU *v, REGS *regs) // ONLY gets called from ia64_leave_kernel // ONLY call with interrupts disabled?? (else might miss one?) // NEVER successful if already reflecting a trap/fault because psr.i==0 -void leave_hypervisor_tail(struct pt_regs *regs) +void leave_hypervisor_tail(void) { struct domain *d = current->domain; struct vcpu *v = current; @@ -207,17 +227,23 @@ void leave_hypervisor_tail(struct pt_regs *regs) local_irq_disable(); if (v->vcpu_id == 0) { - int callback_irq = + unsigned long callback_irq = d->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ]; + /* + * val[63:56] == 1: val[55:0] is a delivery PCI INTx line: + * Domain = val[47:32], Bus = val[31:16], + * DevFn = val[15: 8], IntX = val[ 1: 0] + * val[63:56] == 0: val[55:0] is a delivery as GSI + */ if (callback_irq != 0 && local_events_need_delivery()) { /* change level for para-device callback irq */ /* use level irq to send discrete event */ - if (callback_irq & IA64_CALLBACK_IRQ_RID) { - /* case of using Requester-ID as callback irq */ - /* RID: '<#bus(8)><#dev(5)><#func(3)>' */ - int dev = (callback_irq >> 3) & 0x1f; - viosapic_set_pci_irq(d, dev, 0, 1); - viosapic_set_pci_irq(d, dev, 0, 0); + if ((uint8_t)(callback_irq >> 56) == 1) { + /* case of using PCI INTx line as callback irq */ + int pdev = (callback_irq >> 11) & 0x1f; + int pintx = callback_irq & 3; + viosapic_set_pci_irq(d, pdev, pintx, 1); + viosapic_set_pci_irq(d, pdev, pintx, 0); } else { /* case of using GSI as callback irq */ viosapic_set_irq(d, callback_irq, 1); @@ -367,7 +393,7 @@ vmx_hpw_miss(u64 vadr , u64 vec, REGS* regs) if (!vpsr.ic) misr.ni = 1; - if(!vhpt_enabled(v, vadr, misr.rs?RSE_REF:DATA_REF)){ + if (!vhpt_enabled(v, vadr, INST_REF)) { vcpu_set_isr(v, misr.val); alt_itlb(v, vadr); return IA64_FAULT; diff --git a/xen/arch/ia64/vmx/vmx_vcpu.c b/xen/arch/ia64/vmx/vmx_vcpu.c index 5c1ab3305f..2dc2114db5 100644 --- a/xen/arch/ia64/vmx/vmx_vcpu.c +++ b/xen/arch/ia64/vmx/vmx_vcpu.c @@ -78,6 +78,22 @@ struct guest_psr_bundle guest_psr_buf[100]; unsigned long guest_psr_index = 0; #endif + +void +vmx_ia64_set_dcr(VCPU *v) +{ + unsigned long dcr_bits = IA64_DEFAULT_DCR_BITS; + + // if guest is runing on cpl > 0, set dcr.dm=1 + // if geust is runing on cpl = 0, set dcr.dm=0 + // because Guest OS may ld.s on tr mapped page. + if (!(VCPU(v, vpsr) & IA64_PSR_CPL)) + dcr_bits &= ~IA64_DCR_DM; + + ia64_set_dcr(dcr_bits); +} + + void vmx_vcpu_set_psr(VCPU *vcpu, unsigned long value) { @@ -141,6 +157,9 @@ vmx_vcpu_set_psr(VCPU *vcpu, unsigned long value) regs->cr_ipsr = (regs->cr_ipsr & mask ) | ( value & (~mask) ); + if (FP_PSR(vcpu) & IA64_PSR_DFH) + regs->cr_ipsr |= IA64_PSR_DFH; + check_mm_mode_switch(vcpu, old_psr, new_psr); return ; } @@ -258,6 +277,7 @@ IA64FAULT vmx_vcpu_rfi(VCPU *vcpu) else vcpu_bsw0(vcpu); vmx_vcpu_set_psr(vcpu,psr); + vmx_ia64_set_dcr(vcpu); ifs=VCPU(vcpu,ifs); if(ifs>>63) regs->cr_ifs = ifs; diff --git a/xen/arch/ia64/vmx/vmx_virt.c b/xen/arch/ia64/vmx/vmx_virt.c index 9926c6ed8f..57e1552971 100644 --- a/xen/arch/ia64/vmx/vmx_virt.c +++ b/xen/arch/ia64/vmx/vmx_virt.c @@ -1234,7 +1234,7 @@ IA64FAULT vmx_emul_mov_to_cr(VCPU *vcpu, INST64 inst) #endif //CHECK_FAULT r2 = cr_igfld_mask(inst.M32.cr3,r2); switch (inst.M32.cr3) { - case 0: return vmx_vcpu_set_dcr(vcpu,r2); + case 0: return vcpu_set_dcr(vcpu,r2); case 1: return vmx_vcpu_set_itm(vcpu,r2); case 2: return vmx_vcpu_set_iva(vcpu,r2); case 8: return vmx_vcpu_set_pta(vcpu,r2); @@ -1299,7 +1299,7 @@ IA64FAULT vmx_emul_mov_from_cr(VCPU *vcpu, INST64 inst) // from_cr_cnt[inst.M33.cr3]++; switch (inst.M33.cr3) { - case 0: return vmx_cr_get(dcr); + case 0: return cr_get(dcr); case 1: return vmx_cr_get(itm); case 2: return vmx_cr_get(iva); case 8: return vmx_cr_get(pta); diff --git a/xen/arch/ia64/vmx/vtlb.c b/xen/arch/ia64/vmx/vtlb.c index f85c9e63b4..7ed628ba66 100644 --- a/xen/arch/ia64/vmx/vtlb.c +++ b/xen/arch/ia64/vmx/vtlb.c @@ -248,6 +248,7 @@ u64 guest_vhpt_lookup(u64 iha, u64 *pte) "tnat.nz p6,p7=r9;;" "(p6) mov %0=1;" "(p6) mov r9=r0;" + "(p7) extr.u r9=r9,0,53;;" "(p7) mov %0=r0;" "(p7) st8 [%2]=r9;;" "ssm psr.ic;;" @@ -261,7 +262,7 @@ u64 guest_vhpt_lookup(u64 iha, u64 *pte) * purge software guest tlb */ -void vtlb_purge(VCPU *v, u64 va, u64 ps) +static void vtlb_purge(VCPU *v, u64 va, u64 ps) { thash_data_t *cur; u64 start, curadr, size, psbits, tag, rr_ps, num; @@ -442,6 +443,15 @@ void thash_purge_entries(VCPU *v, u64 va, u64 ps) vhpt_purge(v, va, ps); } +void thash_purge_entries_remote(VCPU *v, u64 va, u64 ps) +{ + u64 old_va = va; + va = REGION_OFFSET(va); + if (vcpu_quick_region_check(v->arch.tc_regions, old_va)) + vtlb_purge(v, va, ps); + vhpt_purge(v, va, ps); +} + u64 translate_phy_pte(VCPU *v, u64 *pte, u64 itir, u64 va) { u64 ps, ps_mask, paddr, maddr; diff --git a/xen/arch/ia64/xen/dom_fw.c b/xen/arch/ia64/xen/dom_fw.c index a366155046..bc04d21b2a 100644 --- a/xen/arch/ia64/xen/dom_fw.c +++ b/xen/arch/ia64/xen/dom_fw.c @@ -599,7 +599,17 @@ complete_dom0_memmap(struct domain *d, case EFI_UNUSABLE_MEMORY: case EFI_PAL_CODE: - /* Discard. */ + /* + * We don't really need these, but holes in the + * memory map may cause Linux to assume there are + * uncacheable ranges within a granule. + */ + dom_md->type = EFI_UNUSABLE_MEMORY; + dom_md->phys_addr = start; + dom_md->virt_addr = 0; + dom_md->num_pages = (end - start) >> EFI_PAGE_SHIFT; + dom_md->attribute = EFI_MEMORY_WB; + num_mds++; break; default: diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index e62b259c4b..9c21d02949 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +69,8 @@ static void init_switch_stack(struct vcpu *v); DEFINE_PER_CPU(uint8_t *, current_psr_i_addr); DEFINE_PER_CPU(int *, current_psr_ic_addr); +DEFINE_PER_CPU(struct vcpu *, fp_owner); + #include static void @@ -135,12 +138,44 @@ static void flush_vtlb_for_context_switch(struct vcpu* prev, struct vcpu* next) } } +static void lazy_fp_switch(struct vcpu *prev, struct vcpu *next) +{ + /* + * Implement eager save, lazy restore + */ + if (!is_idle_vcpu(prev)) { + if (VMX_DOMAIN(prev)) { + if (FP_PSR(prev) & IA64_PSR_MFH) { + __ia64_save_fpu(prev->arch._thread.fph); + __ia64_per_cpu_var(fp_owner) = prev; + } + } else { + if (PSCB(prev, hpsr_mfh)) { + __ia64_save_fpu(prev->arch._thread.fph); + __ia64_per_cpu_var(fp_owner) = prev; + } + } + } + + if (!is_idle_vcpu(next)) { + if (VMX_DOMAIN(next)) { + FP_PSR(next) = IA64_PSR_DFH; + vcpu_regs(next)->cr_ipsr |= IA64_PSR_DFH; + } else { + PSCB(next, hpsr_dfh) = 1; + PSCB(next, hpsr_mfh) = 0; + vcpu_regs(next)->cr_ipsr |= IA64_PSR_DFH; + } + } +} + void schedule_tail(struct vcpu *prev) { extern char ia64_ivt; - context_saved(prev); + context_saved(prev); ia64_disable_vhpt_walker(); + if (VMX_DOMAIN(current)) { vmx_do_launch(current); migrate_timer(¤t->arch.arch_vmx.vtm.vtm_timer, @@ -148,7 +183,7 @@ void schedule_tail(struct vcpu *prev) } else { ia64_set_iva(&ia64_ivt); load_region_regs(current); - ia64_set_pta(vcpu_pta(current)); + ia64_set_pta(vcpu_pta(current)); vcpu_load_kernel_regs(current); __ia64_per_cpu_var(current_psr_i_addr) = ¤t->domain-> shared_info->vcpu_info[current->vcpu_id].evtchn_upcall_mask; @@ -165,64 +200,65 @@ void context_switch(struct vcpu *prev, struct vcpu *next) local_irq_save(spsr); - if (!is_idle_domain(prev->domain)) - __ia64_save_fpu(prev->arch._thread.fph); - if (!is_idle_domain(next->domain)) - __ia64_load_fpu(next->arch._thread.fph); - if (VMX_DOMAIN(prev)) { - vmx_save_state(prev); - if (!VMX_DOMAIN(next)) { - /* VMX domains can change the physical cr.dcr. - * Restore default to prevent leakage. */ - ia64_setreg(_IA64_REG_CR_DCR, (IA64_DCR_DP | IA64_DCR_DK - | IA64_DCR_DX | IA64_DCR_DR | IA64_DCR_PP - | IA64_DCR_DA | IA64_DCR_DD | IA64_DCR_LC)); - } + vmx_save_state(prev); + if (!VMX_DOMAIN(next)) { + /* VMX domains can change the physical cr.dcr. + * Restore default to prevent leakage. */ + ia64_setreg(_IA64_REG_CR_DCR, IA64_DEFAULT_DCR_BITS); + } } if (VMX_DOMAIN(next)) - vmx_load_state(next); + vmx_load_state(next); ia64_disable_vhpt_walker(); - /*ia64_psr(ia64_task_regs(next))->dfh = !ia64_is_local_fpu_owner(next);*/ + lazy_fp_switch(prev, current); + prev = ia64_switch_to(next); /* Note: ia64_switch_to does not return here at vcpu initialization. */ - //cpu_set(smp_processor_id(), current->domain->domain_dirty_cpumask); - - if (VMX_DOMAIN(current)){ - vmx_load_all_rr(current); - migrate_timer(¤t->arch.arch_vmx.vtm.vtm_timer, - current->processor); + if (VMX_DOMAIN(current)) { + vmx_load_all_rr(current); + migrate_timer(¤t->arch.arch_vmx.vtm.vtm_timer, + current->processor); } else { - struct domain *nd; - extern char ia64_ivt; + struct domain *nd; + extern char ia64_ivt; - ia64_set_iva(&ia64_ivt); + ia64_set_iva(&ia64_ivt); - nd = current->domain; - if (!is_idle_domain(nd)) { - load_region_regs(current); - ia64_set_pta(vcpu_pta(current)); - vcpu_load_kernel_regs(current); - vcpu_set_next_timer(current); - if (vcpu_timer_expired(current)) - vcpu_pend_timer(current); - __ia64_per_cpu_var(current_psr_i_addr) = &nd->shared_info-> - vcpu_info[current->vcpu_id].evtchn_upcall_mask; - __ia64_per_cpu_var(current_psr_ic_addr) = - (int *)(nd->arch.shared_info_va + XSI_PSR_IC_OFS); - } else { - /* When switching to idle domain, only need to disable vhpt - * walker. Then all accesses happen within idle context will - * be handled by TR mapping and identity mapping. - */ - __ia64_per_cpu_var(current_psr_i_addr) = NULL; - __ia64_per_cpu_var(current_psr_ic_addr) = NULL; + nd = current->domain; + if (!is_idle_domain(nd)) { + load_region_regs(current); + ia64_set_pta(vcpu_pta(current)); + vcpu_load_kernel_regs(current); + vcpu_set_next_timer(current); + if (vcpu_timer_expired(current)) + vcpu_pend_timer(current); + __ia64_per_cpu_var(current_psr_i_addr) = &nd->shared_info-> + vcpu_info[current->vcpu_id].evtchn_upcall_mask; + __ia64_per_cpu_var(current_psr_ic_addr) = + (int *)(nd->arch.shared_info_va + XSI_PSR_IC_OFS); + } else { + /* When switching to idle domain, only need to disable vhpt + * walker. Then all accesses happen within idle context will + * be handled by TR mapping and identity mapping. + */ + __ia64_per_cpu_var(current_psr_i_addr) = NULL; + __ia64_per_cpu_var(current_psr_ic_addr) = NULL; } } local_irq_restore(spsr); + + /* lazy fp */ + if (current->processor != current->arch.last_processor) { + unsigned long *addr; + addr = (unsigned long *)per_cpu_addr(fp_owner, + current->arch.last_processor); + ia64_cmpxchg(acq, addr, current, 0, 8); + } + flush_vtlb_for_context_switch(prev, current); context_saved(prev); } @@ -411,9 +447,6 @@ int vcpu_late_initialise(struct vcpu *v) assign_domain_page(d, IA64_XMAPPEDREGS_PADDR(v->vcpu_id) + i, virt_to_maddr(v->arch.privregs + i)); - tlbflush_update_time(&v->arch.tlbflush_timestamp, - tlbflush_current_time()); - return 0; } @@ -519,6 +552,12 @@ void arch_domain_destroy(struct domain *d) deallocate_rid_range(d); } +int arch_vcpu_reset(struct vcpu *v) +{ + /* FIXME: Stub for now */ + return 0; +} + void arch_get_info_guest(struct vcpu *v, vcpu_guest_context_u c) { int i; @@ -542,7 +581,7 @@ void arch_get_info_guest(struct vcpu *v, vcpu_guest_context_u c) er->dtrs[i].rid = v->arch.dtrs[i].rid; } er->event_callback_ip = v->arch.event_callback_ip; - er->dcr = v->arch.dcr; + er->dcr = PSCB(v,dcr); er->iva = v->arch.iva; } @@ -578,16 +617,18 @@ int arch_set_info_guest(struct vcpu *v, vcpu_guest_context_u c) er->dtrs[i].rid); } v->arch.event_callback_ip = er->event_callback_ip; - v->arch.dcr = er->dcr; + PSCB(v,dcr) = er->dcr; v->arch.iva = er->iva; } if (test_bit(_VCPUF_initialised, &v->vcpu_flags)) return 0; - if (d->arch.is_vti) - vmx_final_setup_guest(v); - else { + if (d->arch.is_vti) { + rc = vmx_final_setup_guest(v); + if (rc != 0) + return rc; + } else { rc = vcpu_late_initialise(v); if (rc != 0) return rc; @@ -982,12 +1023,6 @@ int construct_dom0(struct domain *d, unsigned long bp_mpa; struct ia64_boot_param *bp; -#ifdef VALIDATE_VT - unsigned int vmx_dom0 = 0; - unsigned long mfn; - struct page_info *page = NULL; -#endif - //printk("construct_dom0: starting\n"); /* Sanity! */ @@ -1021,23 +1056,6 @@ int construct_dom0(struct domain *d, return -1; } -#ifdef VALIDATE_VT - /* Temp workaround */ - if (running_on_sim) - dsi.xen_section_string = (char *)1; - - /* Check whether dom0 is vti domain */ - if ((!vmx_enabled) && !dsi.xen_section_string) { - printk("Lack of hardware support for unmodified vmx dom0\n"); - panic(""); - } - - if (vmx_enabled && !dsi.xen_section_string) { - printk("Dom0 is vmx domain!\n"); - vmx_dom0 = 1; - } -#endif - p_start = parms.virt_base; pkern_start = parms.virt_kstart; pkern_end = parms.virt_kend; @@ -1131,14 +1149,6 @@ int construct_dom0(struct domain *d, printk("Dom0: 0x%lx\n", (u64)dom0); -#ifdef VALIDATE_VT - /* VMX specific construction for Dom0, if hardware supports VMX - * and Dom0 is unmodified image - */ - if (vmx_dom0) - vmx_final_setup_guest(v); -#endif - set_bit(_VCPUF_initialised, &v->vcpu_flags); /* Build firmware. diff --git a/xen/arch/ia64/xen/faults.c b/xen/arch/ia64/xen/faults.c index 02606b1228..77a4eaa514 100644 --- a/xen/arch/ia64/xen/faults.c +++ b/xen/arch/ia64/xen/faults.c @@ -92,6 +92,9 @@ void reflect_interruption(unsigned long isr, struct pt_regs *regs, regs->cr_iip = ((unsigned long)PSCBX(v, iva) + vector) & ~0xffUL; regs->cr_ipsr = (regs->cr_ipsr & ~DELIVER_PSR_CLR) | DELIVER_PSR_SET; + if (PSCB(v, hpsr_dfh)) + regs->cr_ipsr |= IA64_PSR_DFH; + PSCB(v, vpsr_dfh) = 0; v->vcpu_info->evtchn_upcall_mask = 1; PSCB(v, interrupt_collection_enabled) = 0; @@ -152,6 +155,9 @@ void reflect_event(void) regs->cr_iip = v->arch.event_callback_ip; regs->cr_ipsr = (regs->cr_ipsr & ~DELIVER_PSR_CLR) | DELIVER_PSR_SET; + if (PSCB(v, hpsr_dfh)) + regs->cr_ipsr |= IA64_PSR_DFH; + PSCB(v, vpsr_dfh) = 0; v->vcpu_info->evtchn_upcall_mask = 1; PSCB(v, interrupt_collection_enabled) = 0; } @@ -261,6 +267,10 @@ void ia64_do_page_fault(unsigned long address, unsigned long isr, ((unsigned long)PSCBX(current, iva) + fault) & ~0xffUL; regs->cr_ipsr = (regs->cr_ipsr & ~DELIVER_PSR_CLR) | DELIVER_PSR_SET; + + if (PSCB(current, hpsr_dfh)) + regs->cr_ipsr |= IA64_PSR_DFH; + PSCB(current, vpsr_dfh) = 0; perfc_incra(slow_reflect, fault >> 8); return; } @@ -608,6 +618,16 @@ ia64_handle_reflection(unsigned long ifa, struct pt_regs *regs, vector = IA64_GENEX_VECTOR; break; case 25: + if (PSCB(v, hpsr_dfh)) { + PSCB(v, hpsr_dfh) = 0; + PSCB(v, hpsr_mfh) = 1; + if (__ia64_per_cpu_var(fp_owner) != v) + __ia64_load_fpu(v->arch._thread.fph); + } + if (!PSCB(v, vpsr_dfh)) { + regs->cr_ipsr &= ~IA64_PSR_DFH; + return; + } vector = IA64_DISABLED_FPREG_VECTOR; break; case 26: diff --git a/xen/arch/ia64/xen/flushtlb.c b/xen/arch/ia64/xen/flushtlb.c index 0c77c1b6df..19aabf6c50 100644 --- a/xen/arch/ia64/xen/flushtlb.c +++ b/xen/arch/ia64/xen/flushtlb.c @@ -59,44 +59,18 @@ tlbflush_clock_inc_and_return(void) return t2; } +static void +tlbflush_clock_local_flush(void *unused) +{ + local_vhpt_flush(); + local_flush_tlb_all(); +} + void new_tlbflush_clock_period(void) { - /* - *XXX TODO - * If flushing all vcpu's vhpt takes too long, it can be done backgroundly. - * In such case tlbflush time comparison is done using only 31bit - * similar to linux jiffies comparison. - * vhpt should be flushed gradually before wraping 31bits. - * - * Sample calculation. - * Currently Xen/IA64 can create up to 64 domains at the same time. - * Vhpt size is currently 64KB. (This might be changed later though) - * Suppose each domains have 4 vcpus (or 16 vcpus). - * then the memory size which must be flushed is 16MB (64MB). - */ - struct domain* d; - struct vcpu* v; - /* flush all vhpt of vcpu of all existing domain. */ - read_lock(&domlist_lock); - for_each_domain(d) { - for_each_vcpu(d, v) { - vcpu_purge_tr_entry(&PSCBX(v,dtlb)); - vcpu_purge_tr_entry(&PSCBX(v,itlb)); - } - } - smp_mb(); - for_each_domain(d) { - for_each_vcpu(d, v) { - if (HAS_PERVCPU_VHPT(v->domain)) - vcpu_vhpt_flush(v); - } - } - read_unlock(&domlist_lock); - /* unlock has release semantics */ - /* flush all vhpt of physical cpu and mTLB */ - on_each_cpu((void (*)(void *))local_flush_tlb_all, NULL, 1, 1); + on_each_cpu(tlbflush_clock_local_flush, NULL, 1, 1); /* * if global TLB shootdown is finished, increment tlbflush_time diff --git a/xen/arch/ia64/xen/fw_emul.c b/xen/arch/ia64/xen/fw_emul.c index 2a9f8fcb53..60f955ff79 100644 --- a/xen/arch/ia64/xen/fw_emul.c +++ b/xen/arch/ia64/xen/fw_emul.c @@ -605,9 +605,11 @@ xen_pal_emulator(unsigned long index, u64 in1, u64 in2, u64 in3) printk ("Domain0 halts the machine\n"); console_start_sync(); (*efi.reset_system)(EFI_RESET_SHUTDOWN,0,0,NULL); + } else { + set_bit(_VCPUF_down, ¤t->vcpu_flags); + vcpu_sleep_nosync(current); + status = PAL_STATUS_SUCCESS; } - else - domain_shutdown(current->domain, SHUTDOWN_poweroff); break; case PAL_HALT_LIGHT: if (VMX_DOMAIN(current)) { @@ -623,6 +625,9 @@ xen_pal_emulator(unsigned long index, u64 in1, u64 in2, u64 in3) if (VMX_DOMAIN(current)) status = PAL_STATUS_SUCCESS; break; + case PAL_LOGICAL_TO_PHYSICAL: + /* Optional, no need to complain about being unimplemented */ + break; default: printk("xen_pal_emulator: UNIMPLEMENTED PAL CALL %lu!!!!\n", index); diff --git a/xen/arch/ia64/xen/hyperprivop.S b/xen/arch/ia64/xen/hyperprivop.S index 2b940d0922..5248d671ee 100644 --- a/xen/arch/ia64/xen/hyperprivop.S +++ b/xen/arch/ia64/xen/hyperprivop.S @@ -252,6 +252,10 @@ ENTRY(hyper_ssm_i) movl r27=~DELIVER_PSR_CLR;; or r29=r29,r28;; and r29=r29,r27;; + // set hpsr_dfh to ipsr + adds r28=XSI_HPSR_DFH_OFS-XSI_PSR_IC_OFS,r18;; + ld1 r28=[r28];; + dep r29=r28,r29,IA64_PSR_DFH_BIT,1;; mov cr.ipsr=r29;; // set shared_mem ipsr (from ipsr in r30 with ipsr.ri already set) extr.u r29=r30,IA64_PSR_CPL0_BIT,2;; @@ -269,6 +273,12 @@ ENTRY(hyper_ssm_i) movl r22=THIS_CPU(current_psr_i_addr) adds r21=XSI_IPSR_OFS-XSI_PSR_IC_OFS,r18 ;; ld8 r22=[r22] + ;; + adds r27=XSI_VPSR_DFH_OFS-XSI_PSR_IC_OFS,r18;; + ld1 r28=[r27];; + st1 [r27]=r0 + dep r30=r28,r30,IA64_PSR_DFH_BIT,1 + ;; st8 [r21]=r30;; // set shared_mem interrupt_delivery_enabled to 0 // set shared_mem interrupt_collection_enabled to 0 @@ -607,6 +617,10 @@ ENTRY(fast_reflect) movl r27=~(DELIVER_PSR_CLR|IA64_PSR_CPL0);; or r29=r29,r28;; and r29=r29,r27;; + // set hpsr_dfh to ipsr + adds r28=XSI_HPSR_DFH_OFS-XSI_PSR_IC_OFS,r18;; + ld1 r28=[r28];; + dep r29=r28,r29,IA64_PSR_DFH_BIT,1;; mov cr.ipsr=r29;; // set shared_mem ipsr (from ipsr in r30 with ipsr.ri already set) extr.u r29=r30,IA64_PSR_CPL0_BIT,2;; @@ -629,7 +643,13 @@ ENTRY(fast_reflect) (p6) dep r30=0,r30,IA64_PSR_I_BIT,1 (p7) dep r30=-1,r30,IA64_PSR_I_BIT,1 ;; mov r22=1 - adds r21=XSI_IPSR_OFS-XSI_PSR_IC_OFS,r18 ;; + adds r21=XSI_IPSR_OFS-XSI_PSR_IC_OFS,r18 + ;; + adds r27=XSI_VPSR_DFH_OFS-XSI_PSR_IC_OFS,r18;; + ld1 r28=[r27];; + st1 [r27]=r0 + dep r30=r28,r30,IA64_PSR_DFH_BIT,1 + ;; st8 [r21]=r30 ;; // set shared_mem interrupt_delivery_enabled to 0 // set shared_mem interrupt_collection_enabled to 0 @@ -1104,6 +1124,18 @@ just_do_rfi: ;; or r21=r21,r20 ;; + adds r20=XSI_VPSR_DFH_OFS-XSI_PSR_IC_OFS,r18;; + tbit.z p8,p9 = r21, IA64_PSR_DFH_BIT + ;; + (p9) mov r27=1;; + (p9) st1 [r20]=r27 + ;; + (p8) st1 [r20]=r0 + (p8) adds r20=XSI_HPSR_DFH_OFS-XSI_PSR_IC_OFS,r18;; + (p8) ld1 r27=[r20] + ;; + (p8) dep r21=r27,r21, IA64_PSR_DFH_BIT, 1 + ;; mov cr.ipsr=r21 adds r20=XSI_BANKNUM_OFS-XSI_PSR_IC_OFS,r18 ;; ld4 r21=[r20];; @@ -1489,6 +1521,11 @@ ENTRY(hyper_get_psr) ld1 r21=[r20];; dep r8=r21,r8,IA64_PSR_I_BIT,1 ;; + // set vpsr.dfh + adds r20=XSI_VPSR_DFH_OFS-XSI_PSR_IC_OFS,r18;; + ld1 r21=[r20];; + dep r8=r21,r8,IA64_PSR_DFH_BIT,1 + ;; mov r25=cr.iip extr.u r26=r24,41,2 ;; cmp.eq p6,p7=2,r26 ;; diff --git a/xen/arch/ia64/xen/mm.c b/xen/arch/ia64/xen/mm.c index 5cdb25c397..9b153b7f51 100644 --- a/xen/arch/ia64/xen/mm.c +++ b/xen/arch/ia64/xen/mm.c @@ -525,7 +525,9 @@ u64 translate_domain_pte(u64 pteval, u64 address, u64 itir__, u64* logps, This can happen when domU tries to touch i/o port space. Also prevents possible address aliasing issues. */ - printk("Warning: UC to WB for mpaddr=%lx\n", mpaddr); + if (!(mpaddr - IO_PORTS_PADDR < IO_PORTS_SIZE)) + gdprintk(XENLOG_WARNING, "Warning: UC to WB " + "for mpaddr=%lx\n", mpaddr); pteval = (pteval & ~_PAGE_MA_MASK) | _PAGE_MA_WB; } break; @@ -690,7 +692,6 @@ unsigned long lookup_domain_mpa(struct domain *d, unsigned long mpaddr, if (pte != NULL) { pte_t tmp_pte = *pte;// pte is volatile. copy the value. if (pte_present(tmp_pte)) { -//printk("lookup_domain_page: found mapping for %lx, pte=%lx\n",mpaddr,pte_val(*pte)); if (entry != NULL) p2m_entry_set(entry, pte, tmp_pte); return pte_val(tmp_pte); @@ -698,14 +699,20 @@ unsigned long lookup_domain_mpa(struct domain *d, unsigned long mpaddr, return GPFN_INV_MASK; } - printk("%s: d 0x%p id %d current 0x%p id %d\n", - __func__, d, d->domain_id, current, current->vcpu_id); - if (mpaddr < d->arch.convmem_end) - printk("%s: non-allocated mpa 0x%lx (< 0x%lx)\n", __func__, - mpaddr, d->arch.convmem_end); - else - printk("%s: bad mpa 0x%lx (=> 0x%lx)\n", __func__, - mpaddr, d->arch.convmem_end); + if (mpaddr < d->arch.convmem_end) { + gdprintk(XENLOG_WARNING, "vcpu %d iip 0x%016lx: non-allocated mpa " + "0x%lx (< 0x%lx)\n", current->vcpu_id, PSCB(current, iip), + mpaddr, d->arch.convmem_end); + } else if (mpaddr - IO_PORTS_PADDR < IO_PORTS_SIZE) { + /* Log I/O port probing, but complain less loudly about it */ + gdprintk(XENLOG_INFO, "vcpu %d iip 0x%016lx: bad I/O port access " + "0x%lx\n ", current->vcpu_id, PSCB(current, iip), + IO_SPACE_SPARSE_DECODING(mpaddr - IO_PORTS_PADDR)); + } else { + gdprintk(XENLOG_WARNING, "vcpu %d iip 0x%016lx: bad mpa 0x%lx " + "(=> 0x%lx)\n", current->vcpu_id, PSCB(current, iip), + mpaddr, d->arch.convmem_end); + } if (entry != NULL) p2m_entry_set(entry, NULL, __pte(0)); diff --git a/xen/arch/ia64/xen/vcpu.c b/xen/arch/ia64/xen/vcpu.c index 9b554b1b64..a21574ec2b 100644 --- a/xen/arch/ia64/xen/vcpu.c +++ b/xen/arch/ia64/xen/vcpu.c @@ -141,6 +141,9 @@ void vcpu_init_regs(struct vcpu *v) /* dt/rt/it:1;i/ic:1, si:1, vm/bn:1, ac:1 */ /* Need to be expanded as macro */ regs->cr_ipsr = 0x501008826008; + /* lazy fp */ + FP_PSR(v) = IA64_PSR_DFH; + regs->cr_ipsr |= IA64_PSR_DFH; } else { regs->cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BITS_TO_SET | IA64_PSR_BN; @@ -148,6 +151,10 @@ void vcpu_init_regs(struct vcpu *v) | IA64_PSR_RI | IA64_PSR_IS); // domain runs at PL2 regs->cr_ipsr |= 2UL << IA64_PSR_CPL0_BIT; + // lazy fp + PSCB(v, hpsr_dfh) = 1; + PSCB(v, hpsr_mfh) = 0; + regs->cr_ipsr |= IA64_PSR_DFH; } regs->cr_ifs = 1UL << 63; /* or clear? */ regs->ar_fpsr = FPSR_DEFAULT; @@ -265,8 +272,10 @@ IA64FAULT vcpu_reset_psr_sm(VCPU * vcpu, u64 imm24) IA64_PSR_I | IA64_PSR_IC | IA64_PSR_DT | IA64_PSR_DFL | IA64_PSR_DFH)) return IA64_ILLOP_FAULT; - if (imm.dfh) - ipsr->dfh = 0; + if (imm.dfh) { + ipsr->dfh = PSCB(vcpu, hpsr_dfh); + PSCB(vcpu, vpsr_dfh) = 0; + } if (imm.dfl) ipsr->dfl = 0; if (imm.pp) { @@ -320,8 +329,10 @@ IA64FAULT vcpu_set_psr_sm(VCPU * vcpu, u64 imm24) IA64_PSR_DT | IA64_PSR_DFL | IA64_PSR_DFH; if (imm24 & ~mask) return IA64_ILLOP_FAULT; - if (imm.dfh) + if (imm.dfh) { + PSCB(vcpu, vpsr_dfh) = 1; ipsr->dfh = 1; + } if (imm.dfl) ipsr->dfl = 1; if (imm.pp) { @@ -386,8 +397,13 @@ IA64FAULT vcpu_set_psr_l(VCPU * vcpu, u64 val) //if (val & ~(IA64_PSR_PP | IA64_PSR_UP | IA64_PSR_SP)) // return IA64_ILLOP_FAULT; // however trying to set other bits can't be an error as it is in ssm - if (newpsr.dfh) + if (newpsr.dfh) { ipsr->dfh = 1; + PSCB(vcpu, vpsr_dfh) = 1; + } else { + ipsr->dfh = PSCB(vcpu, hpsr_dfh); + PSCB(vcpu, vpsr_dfh) = 0; + } if (newpsr.dfl) ipsr->dfl = 1; if (newpsr.pp) { @@ -466,6 +482,8 @@ IA64FAULT vcpu_get_psr(VCPU * vcpu, u64 * pval) newpsr.pp = 1; else newpsr.pp = 0; + newpsr.dfh = PSCB(vcpu, vpsr_dfh); + *pval = *(unsigned long *)&newpsr; *pval &= (MASK(0, 32) | MASK(35, 2)); return IA64_NO_FAULT; @@ -483,7 +501,7 @@ BOOLEAN vcpu_get_psr_i(VCPU * vcpu) u64 vcpu_get_ipsr_int_state(VCPU * vcpu, u64 prevpsr) { - u64 dcr = PSCBX(vcpu, dcr); + u64 dcr = PSCB(vcpu, dcr); PSR psr; //printk("*** vcpu_get_ipsr_int_state (0x%016lx)...\n",prevpsr); @@ -497,6 +515,7 @@ u64 vcpu_get_ipsr_int_state(VCPU * vcpu, u64 prevpsr) psr.ia64_psr.ic = PSCB(vcpu, interrupt_collection_enabled); psr.ia64_psr.i = !vcpu->vcpu_info->evtchn_upcall_mask; psr.ia64_psr.bn = PSCB(vcpu, banknum); + psr.ia64_psr.dfh = PSCB(vcpu, vpsr_dfh); psr.ia64_psr.dt = 1; psr.ia64_psr.it = 1; psr.ia64_psr.rt = 1; @@ -513,10 +532,7 @@ u64 vcpu_get_ipsr_int_state(VCPU * vcpu, u64 prevpsr) IA64FAULT vcpu_get_dcr(VCPU * vcpu, u64 * pval) { -//verbose("vcpu_get_dcr: called @%p\n",PSCB(vcpu,iip)); - // Reads of cr.dcr on Xen always have the sign bit set, so - // a domain can differentiate whether it is running on SP or not - *pval = PSCBX(vcpu, dcr) | 0x8000000000000000L; + *pval = PSCB(vcpu, dcr); return IA64_NO_FAULT; } @@ -632,11 +648,7 @@ IA64FAULT vcpu_get_iha(VCPU * vcpu, u64 * pval) IA64FAULT vcpu_set_dcr(VCPU * vcpu, u64 val) { - // Reads of cr.dcr on SP always have the sign bit set, so - // a domain can differentiate whether it is running on SP or not - // Thus, writes of DCR should ignore the sign bit -//verbose("vcpu_set_dcr: called\n"); - PSCBX(vcpu, dcr) = val & ~0x8000000000000000L; + PSCB(vcpu, dcr) = val; return IA64_NO_FAULT; } @@ -1343,6 +1355,12 @@ IA64FAULT vcpu_rfi(VCPU * vcpu) if (psr.ia64_psr.cpl < 3) psr.ia64_psr.cpl = 2; int_enable = psr.ia64_psr.i; + if (psr.ia64_psr.dfh) { + PSCB(vcpu, vpsr_dfh) = 1; + } else { + psr.ia64_psr.dfh = PSCB(vcpu, hpsr_dfh); + PSCB(vcpu, vpsr_dfh) = 0; + } if (psr.ia64_psr.ic) PSCB(vcpu, interrupt_collection_enabled) = 1; if (psr.ia64_psr.dt && psr.ia64_psr.rt && psr.ia64_psr.it) diff --git a/xen/arch/ia64/xen/vhpt.c b/xen/arch/ia64/xen/vhpt.c index c8846efc45..d5bae1156a 100644 --- a/xen/arch/ia64/xen/vhpt.c +++ b/xen/arch/ia64/xen/vhpt.c @@ -54,11 +54,7 @@ local_vhpt_flush(void) void vcpu_vhpt_flush(struct vcpu* v) { - /* increment flush clock before flush */ - u32 flush_time = tlbflush_clock_inc_and_return(); __vhpt_flush(vcpu_vhpt_maddr(v)); - /* this must be after flush */ - tlbflush_update_time(&v->arch.tlbflush_timestamp, flush_time); perfc_incrc(vcpu_vhpt_flush); } @@ -177,7 +173,9 @@ pervcpu_vhpt_alloc(struct vcpu *v) void pervcpu_vhpt_free(struct vcpu *v) { - free_domheap_pages(v->arch.vhpt_page, VHPT_SIZE_LOG2 - PAGE_SHIFT); + if (likely(v->arch.vhpt_page != NULL)) + free_domheap_pages(v->arch.vhpt_page, + VHPT_SIZE_LOG2 - PAGE_SHIFT); } #endif diff --git a/xen/arch/ia64/xen/xensetup.c b/xen/arch/ia64/xen/xensetup.c index 5e8ed8261b..8909136b26 100644 --- a/xen/arch/ia64/xen/xensetup.c +++ b/xen/arch/ia64/xen/xensetup.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include unsigned long xenheap_phys_end, total_pages; @@ -265,13 +267,16 @@ void start_kernel(void) early_setup_arch(&cmdline); /* We initialise the serial devices very early so we can get debugging. */ - if (running_on_sim) hpsim_serial_init(); + if (running_on_sim) + hpsim_serial_init(); else { - ns16550_init(0, &ns16550_com1); - /* Also init com2 for Tiger4. */ - ns16550_com2.io_base = 0x2f8; - ns16550_com2.irq = 3; - ns16550_init(1, &ns16550_com2); + ns16550_init(0, &ns16550_com1); + if (ns16550_com1.io_base == 0x3f8) { + /* Also init com2 for Tiger4. */ + ns16550_com2.io_base = 0x2f8; + ns16550_com2.irq = 3; + ns16550_init(1, &ns16550_com2); + } } serial_init_preirq(); @@ -436,6 +441,12 @@ void start_kernel(void) init_xen_time(); /* initialise the time */ timer_init(); + rcu_init(); + +#ifdef CONFIG_XEN_IA64_TLBFLUSH_CLOCK + open_softirq(NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ, new_tlbflush_clock_period); +#endif + #ifdef CONFIG_SMP if ( opt_nosmp ) { @@ -464,6 +475,7 @@ printk("num_online_cpus=%d, max_cpus=%d\n",num_online_cpus(),max_cpus); if ( num_online_cpus() >= max_cpus ) break; if ( !cpu_online(i) ) { + rcu_online_cpu(i); __cpu_up(i); } } diff --git a/xen/arch/powerpc/machine_kexec.c b/xen/arch/powerpc/machine_kexec.c index 2debd26a7e..51ddd75890 100644 --- a/xen/arch/powerpc/machine_kexec.c +++ b/xen/arch/powerpc/machine_kexec.c @@ -19,6 +19,11 @@ void machine_reboot_kexec(xen_kexec_image_t *image) printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__); } +void machine_kexec(xen_kexec_image_t *image) +{ + printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__); +} + /* * Local variables: * mode: C diff --git a/xen/arch/x86/crash.c b/xen/arch/x86/crash.c index 73eb4724a8..cae1768633 100644 --- a/xen/arch/x86/crash.c +++ b/xen/arch/x86/crash.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 653ceafb0b..bca683c59b 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include @@ -331,6 +331,7 @@ int vcpu_initialise(struct vcpu *v) pae_l3_cache_init(&v->arch.pae_l3_cache); + paging_vcpu_init(v); if ( is_hvm_domain(d) ) { @@ -424,7 +425,7 @@ int arch_domain_create(struct domain *d) HYPERVISOR_COMPAT_VIRT_START(d) = __HYPERVISOR_COMPAT_VIRT_START; #endif - shadow_domain_init(d); + paging_domain_init(d); if ( !is_idle_domain(d) ) { @@ -464,7 +465,7 @@ void arch_domain_destroy(struct domain *d) hvm_domain_destroy(d); } - shadow_final_teardown(d); + paging_final_teardown(d); free_xenheap_pages( d->arch.mm_perdomain_pt, @@ -613,7 +614,7 @@ int arch_set_info_guest( { cr3_pfn = gmfn_to_mfn(d, xen_cr3_to_pfn(c.nat->ctrlreg[3])); - if ( shadow_mode_refcounts(d) + if ( paging_mode_refcounts(d) ? !get_page(mfn_to_page(cr3_pfn), d) : !get_page_and_type(mfn_to_page(cr3_pfn), d, PGT_base_page_table) ) @@ -631,7 +632,7 @@ int arch_set_info_guest( cr3_pfn = gmfn_to_mfn(d, compat_cr3_to_pfn(c.cmp->ctrlreg[3])); - if ( shadow_mode_refcounts(d) + if ( paging_mode_refcounts(d) ? !get_page(mfn_to_page(cr3_pfn), d) : !get_page_and_type(mfn_to_page(cr3_pfn), d, PGT_l3_page_table) ) @@ -652,8 +653,8 @@ int arch_set_info_guest( /* Don't redo final setup */ set_bit(_VCPUF_initialised, &v->vcpu_flags); - if ( shadow_mode_enabled(d) ) - shadow_update_paging_modes(v); + if ( paging_mode_enabled(d) ) + paging_update_paging_modes(v); update_cr3(v); @@ -1406,7 +1407,7 @@ static void vcpu_destroy_pagetables(struct vcpu *v) if ( pfn != 0 ) { - if ( shadow_mode_refcounts(d) ) + if ( paging_mode_refcounts(d) ) put_page(mfn_to_page(pfn)); else put_page_and_type(mfn_to_page(pfn)); @@ -1427,7 +1428,7 @@ static void vcpu_destroy_pagetables(struct vcpu *v) pfn = pagetable_get_pfn(v->arch.guest_table); if ( pfn != 0 ) { - if ( shadow_mode_refcounts(d) ) + if ( paging_mode_refcounts(d) ) put_page(mfn_to_page(pfn)); else put_page_and_type(mfn_to_page(pfn)); @@ -1443,7 +1444,7 @@ static void vcpu_destroy_pagetables(struct vcpu *v) pfn = pagetable_get_pfn(v->arch.guest_table_user); if ( pfn != 0 ) { - if ( shadow_mode_refcounts(d) ) + if ( paging_mode_refcounts(d) ) put_page(mfn_to_page(pfn)); else put_page_and_type(mfn_to_page(pfn)); @@ -1464,8 +1465,8 @@ void domain_relinquish_resources(struct domain *d) for_each_vcpu ( d, v ) vcpu_destroy_pagetables(v); - /* Tear down shadow mode stuff. */ - shadow_teardown(d); + /* Tear down paging-assistance stuff. */ + paging_teardown(d); /* * Relinquish GDT mappings. No need for explicit unmapping of the LDT as @@ -1484,35 +1485,12 @@ void domain_relinquish_resources(struct domain *d) void arch_dump_domain_info(struct domain *d) { - if ( shadow_mode_enabled(d) ) - { - printk(" shadow mode: "); - if ( d->arch.shadow.mode & SHM2_enable ) - printk("enabled "); - if ( shadow_mode_refcounts(d) ) - printk("refcounts "); - if ( shadow_mode_log_dirty(d) ) - printk("log_dirty "); - if ( shadow_mode_translate(d) ) - printk("translate "); - if ( shadow_mode_external(d) ) - printk("external "); - printk("\n"); - } + paging_dump_domain_info(d); } void arch_dump_vcpu_info(struct vcpu *v) { - if ( shadow_mode_enabled(v->domain) ) - { - if ( v->arch.shadow.mode ) - printk(" shadowed %u-on-%u, %stranslated\n", - v->arch.shadow.mode->guest_levels, - v->arch.shadow.mode->shadow_levels, - shadow_vcpu_mode_translate(v) ? "" : "not "); - else - printk(" not shadowed\n"); - } + paging_dump_vcpu_info(v); } /* diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c index b32f57861c..5755eef718 100644 --- a/xen/arch/x86/domain_build.c +++ b/xen/arch/x86/domain_build.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include @@ -777,8 +777,8 @@ int construct_dom0(struct domain *d, (void)alloc_vcpu(d, i, i); /* Set up CR3 value for write_ptbase */ - if ( shadow_mode_enabled(v->domain) ) - shadow_update_paging_modes(v); + if ( paging_mode_enabled(v->domain) ) + paging_update_paging_modes(v); else update_cr3(v); @@ -918,8 +918,8 @@ int construct_dom0(struct domain *d, regs->eflags = X86_EFLAGS_IF; if ( opt_dom0_shadow ) - if ( shadow_enable(d, SHM2_enable) == 0 ) - shadow_update_paging_modes(v); + if ( paging_enable(d, PG_SH_enable) == 0 ) + paging_update_paging_modes(v); if ( supervisor_mode_kernel ) { diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index d73ae65bd5..69e2259d7f 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -42,7 +42,7 @@ long arch_do_domctl( d = get_domain_by_id(domctl->domain); if ( d != NULL ) { - ret = shadow_domctl(d, + ret = paging_domctl(d, &domctl->u.shadow_op, guest_handle_cast(u_domctl, void)); put_domain(d); @@ -326,10 +326,6 @@ long arch_do_domctl( struct hvm_domain_context c; struct domain *d; - c.cur = 0; - c.size = domctl->u.hvmcontext.size; - c.data = NULL; - ret = -ESRCH; if ( (d = get_domain_by_id(domctl->domain)) == NULL ) break; @@ -338,19 +334,38 @@ long arch_do_domctl( if ( !is_hvm_domain(d) ) goto gethvmcontext_out; + c.cur = 0; + c.size = hvm_save_size(d); + c.data = NULL; + + if ( guest_handle_is_null(domctl->u.hvmcontext.buffer) ) + { + /* Client is querying for the correct buffer size */ + domctl->u.hvmcontext.size = c.size; + ret = 0; + goto gethvmcontext_out; + } + + /* Check that the client has a big enough buffer */ + ret = -ENOSPC; + if ( domctl->u.hvmcontext.size < c.size ) + goto gethvmcontext_out; + + /* Allocate our own marshalling buffer */ ret = -ENOMEM; if ( (c.data = xmalloc_bytes(c.size)) == NULL ) goto gethvmcontext_out; ret = hvm_save(d, &c); + domctl->u.hvmcontext.size = c.cur; if ( copy_to_guest(domctl->u.hvmcontext.buffer, c.data, c.size) != 0 ) ret = -EFAULT; + gethvmcontext_out: if ( copy_to_guest(u_domctl, domctl, 1) ) ret = -EFAULT; - gethvmcontext_out: if ( c.data != NULL ) xfree(c.data); @@ -383,6 +398,7 @@ long arch_do_domctl( put_domain(d); } + break; case XEN_DOMCTL_get_address_size: { @@ -396,7 +412,11 @@ long arch_do_domctl( ret = 0; put_domain(d); + + if ( copy_to_guest(u_domctl, domctl, 1) ) + ret = -EFAULT; } + break; default: ret = -ENOSYS; diff --git a/xen/arch/x86/hvm/Makefile b/xen/arch/x86/hvm/Makefile index 9fbcf51ede..d94fd082ee 100644 --- a/xen/arch/x86/hvm/Makefile +++ b/xen/arch/x86/hvm/Makefile @@ -15,3 +15,4 @@ obj-y += vpt.o obj-y += vioapic.o obj-y += vlapic.o obj-y += vpic.o +obj-y += save.o diff --git a/xen/arch/x86/hvm/hpet.c b/xen/arch/x86/hvm/hpet.c index 6269e149a8..419a886eba 100644 --- a/xen/arch/x86/hvm/hpet.c +++ b/xen/arch/x86/hvm/hpet.c @@ -409,7 +409,7 @@ static int hpet_load(struct domain *d, hvm_domain_context_t *h) return 0; } -HVM_REGISTER_SAVE_RESTORE(HPET, hpet_save, hpet_load); +HVM_REGISTER_SAVE_RESTORE(HPET, hpet_save, hpet_load, 1, HVMSR_PER_DOM); void hpet_init(struct vcpu *v) { diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 3ecaf9d7de..57d58e7647 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -30,11 +30,10 @@ #include #include #include -#include #include #include #include -#include +#include #include #include #include @@ -106,7 +105,6 @@ void hvm_migrate_timers(struct vcpu *v) pit_migrate_timers(v); rtc_migrate_timers(v); hpet_migrate_timers(v); - pmtimer_migrate_timers(v); if ( vcpu_vlapic(v)->pt.enabled ) migrate_timer(&vcpu_vlapic(v)->pt.timer, v->processor); } @@ -156,7 +154,7 @@ int hvm_domain_initialise(struct domain *d) spin_lock_init(&d->arch.hvm_domain.buffered_io_lock); spin_lock_init(&d->arch.hvm_domain.irq_lock); - rc = shadow_enable(d, SHM2_refcounts|SHM2_translate|SHM2_external); + rc = paging_enable(d, PG_SH_enable|PG_refcounts|PG_translate|PG_external); if ( rc != 0 ) return rc; @@ -170,7 +168,6 @@ void hvm_domain_destroy(struct domain *d) { pit_deinit(d); rtc_deinit(d); - pmtimer_deinit(d); hpet_deinit(d); if ( d->arch.hvm_domain.shared_page_va ) @@ -227,7 +224,8 @@ static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h) return 0; } -HVM_REGISTER_SAVE_RESTORE(CPU, hvm_save_cpu_ctxt, hvm_load_cpu_ctxt); +HVM_REGISTER_SAVE_RESTORE(CPU, hvm_save_cpu_ctxt, hvm_load_cpu_ctxt, + 1, HVMSR_PER_VCPU); int hvm_vcpu_initialise(struct vcpu *v) { @@ -273,6 +271,24 @@ void hvm_vcpu_destroy(struct vcpu *v) /*free_xen_event_channel(v, v->arch.hvm_vcpu.xen_port);*/ } + +void hvm_vcpu_reset(struct vcpu *v) +{ + vcpu_pause(v); + + vlapic_reset(vcpu_vlapic(v)); + + hvm_funcs.vcpu_initialise(v); + + set_bit(_VCPUF_down, &v->vcpu_flags); + clear_bit(_VCPUF_initialised, &v->vcpu_flags); + clear_bit(_VCPUF_fpu_initialised, &v->vcpu_flags); + clear_bit(_VCPUF_fpu_dirtied, &v->vcpu_flags); + clear_bit(_VCPUF_blocked, &v->vcpu_flags); + + vcpu_unpause(v); +} + static void hvm_vcpu_down(void) { struct vcpu *v = current; @@ -366,7 +382,7 @@ static int __hvm_copy(void *buf, paddr_t addr, int size, int dir, int virt) count = min_t(int, PAGE_SIZE - (addr & ~PAGE_MASK), todo); if ( virt ) - mfn = get_mfn_from_gpfn(shadow_gva_to_gfn(current, addr)); + mfn = get_mfn_from_gpfn(paging_gva_to_gfn(current, addr)); else mfn = get_mfn_from_gpfn(addr >> PAGE_SHIFT); @@ -583,7 +599,7 @@ void hvm_do_hypercall(struct cpu_user_regs *pregs) return; } - if ( current->arch.shadow.mode->guest_levels == 4 ) + if ( current->arch.paging.mode->guest_levels == 4 ) { pregs->rax = hvm_hypercall64_table[pregs->rax](pregs->rdi, pregs->rsi, @@ -624,20 +640,13 @@ void hvm_hypercall_page_initialise(struct domain *d, */ int hvm_bringup_ap(int vcpuid, int trampoline_vector) { - struct vcpu *bsp = current, *v; - struct domain *d = bsp->domain; + struct vcpu *v; + struct domain *d = current->domain; struct vcpu_guest_context *ctxt; int rc = 0; BUG_ON(!is_hvm_domain(d)); - if ( bsp->vcpu_id != 0 ) - { - gdprintk(XENLOG_ERR, "Not calling hvm_bringup_ap from BSP context.\n"); - domain_crash(bsp->domain); - return -EINVAL; - } - if ( (v = d->vcpu[vcpuid]) == NULL ) return -ENOENT; @@ -668,8 +677,8 @@ int hvm_bringup_ap(int vcpuid, int trampoline_vector) goto out; } - if ( test_and_clear_bit(_VCPUF_down, &d->vcpu[vcpuid]->vcpu_flags) ) - vcpu_wake(d->vcpu[vcpuid]); + if ( test_and_clear_bit(_VCPUF_down, &v->vcpu_flags) ) + vcpu_wake(v); gdprintk(XENLOG_INFO, "AP %d bringup suceeded.\n", vcpuid); out: diff --git a/xen/arch/x86/hvm/i8254.c b/xen/arch/x86/hvm/i8254.c index 11ae4ff0ca..a3a21809fe 100644 --- a/xen/arch/x86/hvm/i8254.c +++ b/xen/arch/x86/hvm/i8254.c @@ -445,7 +445,7 @@ static int pit_load(struct domain *d, hvm_domain_context_t *h) return 0; } -HVM_REGISTER_SAVE_RESTORE(PIT, pit_save, pit_load); +HVM_REGISTER_SAVE_RESTORE(PIT, pit_save, pit_load, 1, HVMSR_PER_DOM); static void pit_reset(void *opaque) { diff --git a/xen/arch/x86/hvm/intercept.c b/xen/arch/x86/hvm/intercept.c index f130a252ab..3de58812c3 100644 --- a/xen/arch/x86/hvm/intercept.c +++ b/xen/arch/x86/hvm/intercept.c @@ -29,8 +29,6 @@ #include #include #include -#include -#include extern struct hvm_mmio_handler hpet_mmio_handler; @@ -157,180 +155,6 @@ static inline void hvm_mmio_access(struct vcpu *v, } } -/* List of handlers for various HVM save and restore types */ -static struct { - hvm_save_handler save; - hvm_load_handler load; - const char *name; -} hvm_sr_handlers [HVM_SAVE_CODE_MAX + 1] = {{NULL, NULL, ""},}; - -/* Init-time function to add entries to that list */ -void hvm_register_savevm(uint16_t typecode, - const char *name, - hvm_save_handler save_state, - hvm_load_handler load_state) -{ - ASSERT(typecode <= HVM_SAVE_CODE_MAX); - ASSERT(hvm_sr_handlers[typecode].save == NULL); - ASSERT(hvm_sr_handlers[typecode].load == NULL); - hvm_sr_handlers[typecode].save = save_state; - hvm_sr_handlers[typecode].load = load_state; - hvm_sr_handlers[typecode].name = name; -} - - -int hvm_save(struct domain *d, hvm_domain_context_t *h) -{ - uint32_t eax, ebx, ecx, edx; - char *c; - struct hvm_save_header hdr; - struct hvm_save_end end; - hvm_save_handler handler; - uint16_t i; - - hdr.magic = HVM_FILE_MAGIC; - hdr.version = HVM_FILE_VERSION; - - /* Save some CPUID bits */ - cpuid(1, &eax, &ebx, &ecx, &edx); - hdr.cpuid = eax; - - /* Save xen changeset */ - c = strrchr(XEN_CHANGESET, ':'); - if ( c ) - hdr.changeset = simple_strtoll(c, NULL, 16); - else - hdr.changeset = -1ULL; /* Unknown */ - - if ( hvm_save_entry(HEADER, 0, h, &hdr) != 0 ) - { - gdprintk(XENLOG_ERR, "HVM save: failed to write header\n"); - return -EFAULT; - } - - /* Save all available kinds of state */ - for ( i = 0; i <= HVM_SAVE_CODE_MAX; i++ ) - { - handler = hvm_sr_handlers[i].save; - if ( handler != NULL ) - { - gdprintk(XENLOG_INFO, "HVM save: %s\n", hvm_sr_handlers[i].name); - if ( handler(d, h) != 0 ) - { - gdprintk(XENLOG_ERR, - "HVM save: failed to save type %"PRIu16"\n", i); - return -EFAULT; - } - } - } - - /* Save an end-of-file marker */ - if ( hvm_save_entry(END, 0, h, &end) != 0 ) - { - /* Run out of data */ - gdprintk(XENLOG_ERR, "HVM save: no room for end marker.\n"); - return -EFAULT; - } - - /* Save macros should not have let us overrun */ - ASSERT(h->cur <= h->size); - return 0; -} - -int hvm_load(struct domain *d, hvm_domain_context_t *h) -{ - uint32_t eax, ebx, ecx, edx; - char *c; - uint64_t cset; - struct hvm_save_header hdr; - struct hvm_save_descriptor *desc; - hvm_load_handler handler; - struct vcpu *v; - - /* Read the save header, which must be first */ - if ( hvm_load_entry(HEADER, h, &hdr) != 0 ) - return -1; - - if (hdr.magic != HVM_FILE_MAGIC) { - gdprintk(XENLOG_ERR, - "HVM restore: bad magic number %#"PRIx32"\n", hdr.magic); - return -1; - } - - if (hdr.version != HVM_FILE_VERSION) { - gdprintk(XENLOG_ERR, - "HVM restore: unsupported version %u\n", hdr.version); - return -1; - } - - cpuid(1, &eax, &ebx, &ecx, &edx); - /*TODO: need to define how big a difference is acceptable */ - if (hdr.cpuid != eax) - gdprintk(XENLOG_WARNING, "HVM restore: saved CPUID (%#"PRIx32") " - "does not match host (%#"PRIx32").\n", hdr.cpuid, eax); - - - c = strrchr(XEN_CHANGESET, ':'); - if ( hdr.changeset == -1ULL ) - gdprintk(XENLOG_WARNING, - "HVM restore: Xen changeset was not saved.\n"); - else if ( c == NULL ) - gdprintk(XENLOG_WARNING, - "HVM restore: Xen changeset is not available.\n"); - else - { - cset = simple_strtoll(c, NULL, 16); - if ( hdr.changeset != cset ) - gdprintk(XENLOG_WARNING, "HVM restore: saved Xen changeset (%#"PRIx64 - ") does not match host (%#"PRIx64").\n", hdr.changeset, cset); - } - - /* Down all the vcpus: we only re-enable the ones that had state saved. */ - for_each_vcpu(d, v) - if ( test_and_set_bit(_VCPUF_down, &v->vcpu_flags) ) - vcpu_sleep_nosync(v); - - while(1) { - - if ( h->size - h->cur < sizeof(struct hvm_save_descriptor) ) - { - /* Run out of data */ - gdprintk(XENLOG_ERR, - "HVM restore: save did not end with a null entry\n"); - return -1; - } - - /* Read the typecode of the next entry and check for the end-marker */ - desc = (struct hvm_save_descriptor *)(&h->data[h->cur]); - if ( desc->typecode == 0 ) - return 0; - - /* Find the handler for this entry */ - if ( desc->typecode > HVM_SAVE_CODE_MAX - || (handler = hvm_sr_handlers[desc->typecode].load) == NULL ) - { - gdprintk(XENLOG_ERR, - "HVM restore: unknown entry typecode %u\n", - desc->typecode); - return -1; - } - - /* Load the entry */ - gdprintk(XENLOG_INFO, "HVM restore: %s %"PRIu16"\n", - hvm_sr_handlers[desc->typecode].name, desc->instance); - if ( handler(d, h) != 0 ) - { - gdprintk(XENLOG_ERR, - "HVM restore: failed to load entry %u/%u\n", - desc->typecode, desc->instance); - return -1; - } - } - - /* Not reached */ -} - - int hvm_buffered_io_intercept(ioreq_t *p) { struct vcpu *v = current; diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c index 013e723f35..4637515bf4 100644 --- a/xen/arch/x86/hvm/io.c +++ b/xen/arch/x86/hvm/io.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/xen/arch/x86/hvm/irq.c b/xen/arch/x86/hvm/irq.c index 6d8432c1ba..aa531b33fb 100644 --- a/xen/arch/x86/hvm/irq.c +++ b/xen/arch/x86/hvm/irq.c @@ -480,6 +480,9 @@ static int irq_load_link(struct domain *d, hvm_domain_context_t *h) return 0; } -HVM_REGISTER_SAVE_RESTORE(PCI_IRQ, irq_save_pci, irq_load_pci); -HVM_REGISTER_SAVE_RESTORE(ISA_IRQ, irq_save_isa, irq_load_isa); -HVM_REGISTER_SAVE_RESTORE(PCI_LINK, irq_save_link, irq_load_link); +HVM_REGISTER_SAVE_RESTORE(PCI_IRQ, irq_save_pci, irq_load_pci, + 1, HVMSR_PER_DOM); +HVM_REGISTER_SAVE_RESTORE(ISA_IRQ, irq_save_isa, irq_load_isa, + 1, HVMSR_PER_DOM); +HVM_REGISTER_SAVE_RESTORE(PCI_LINK, irq_save_link, irq_load_link, + 1, HVMSR_PER_DOM); diff --git a/xen/arch/x86/hvm/platform.c b/xen/arch/x86/hvm/platform.c index 1c8e4c11c4..32246da991 100644 --- a/xen/arch/x86/hvm/platform.c +++ b/xen/arch/x86/hvm/platform.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -29,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -513,14 +513,30 @@ static int mmio_decode(int address_bytes, unsigned char *opcode, mmio_op->operand[1] = mk_operand(size_reg, 0, 0, MEMORY); switch ( ins_subtype ) { - case 7: /* cmp $imm, m32/16 */ - mmio_op->instr = INSTR_CMP; + case 0: /* add $imm, m32/16 */ + mmio_op->instr = INSTR_ADD; return DECODE_success; case 1: /* or $imm, m32/16 */ mmio_op->instr = INSTR_OR; return DECODE_success; + case 4: /* and $imm, m32/16 */ + mmio_op->instr = INSTR_AND; + return DECODE_success; + + case 5: /* sub $imm, m32/16 */ + mmio_op->instr = INSTR_SUB; + return DECODE_success; + + case 6: /* xor $imm, m32/16 */ + mmio_op->instr = INSTR_XOR; + return DECODE_success; + + case 7: /* cmp $imm, m32/16 */ + mmio_op->instr = INSTR_CMP; + return DECODE_success; + default: printk("%x/%x, This opcode isn't handled yet!\n", *opcode, ins_subtype); @@ -674,6 +690,39 @@ static int mmio_decode(int address_bytes, unsigned char *opcode, } else return DECODE_failure; + case 0xFE: + case 0xFF: + { + unsigned char ins_subtype = (opcode[1] >> 3) & 7; + + if ( opcode[0] == 0xFE ) { + *op_size = BYTE; + GET_OP_SIZE_FOR_BYTE(size_reg); + } else { + GET_OP_SIZE_FOR_NONEBYTE(*op_size); + size_reg = *op_size; + } + + mmio_op->immediate = 1; + mmio_op->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE); + mmio_op->operand[1] = mk_operand(size_reg, 0, 0, MEMORY); + + switch ( ins_subtype ) { + case 0: /* inc */ + mmio_op->instr = INSTR_ADD; + return DECODE_success; + + case 1: /* dec */ + mmio_op->instr = INSTR_SUB; + return DECODE_success; + + default: + printk("%x/%x, This opcode isn't handled yet!\n", + *opcode, ins_subtype); + return DECODE_failure; + } + } + case 0x0F: break; @@ -793,7 +842,7 @@ void send_pio_req(unsigned long port, unsigned long count, int size, if ( value_is_ptr ) /* get physical address of data */ { if ( hvm_paging_enabled(current) ) - p->data = shadow_gva_to_gpa(current, value); + p->data = paging_gva_to_gpa(current, value); else p->data = value; /* guest VA == guest PA */ } @@ -849,7 +898,7 @@ static void send_mmio_req(unsigned char type, unsigned long gpa, if ( value_is_ptr ) { if ( hvm_paging_enabled(v) ) - p->data = shadow_gva_to_gpa(v, value); + p->data = paging_gva_to_gpa(v, value); else p->data = value; /* guest VA == guest PA */ } @@ -965,7 +1014,7 @@ void handle_mmio(unsigned long gpa) if ( ad_size == WORD ) addr &= 0xFFFF; addr += hvm_get_segment_base(v, x86_seg_es); - if ( shadow_gva_to_gpa(v, addr) == gpa ) + if ( paging_gva_to_gpa(v, addr) == gpa ) { enum x86_segment seg; diff --git a/xen/arch/x86/hvm/pmtimer.c b/xen/arch/x86/hvm/pmtimer.c index 28be242f84..a396d27df4 100644 --- a/xen/arch/x86/hvm/pmtimer.c +++ b/xen/arch/x86/hvm/pmtimer.c @@ -2,17 +2,6 @@ #include #include -#define TMR_STS (1 << 0) -static void pmt_update_status(void *opaque) -{ - PMTState *s = opaque; - s->pm1_status |= TMR_STS; - - /* TODO: When TMR_EN == 1, generate a SCI event */ - - set_timer(&s->timer, NOW() + (1000000000ULL << 31) / FREQUENCE_PMTIMER); -} - static int handle_pmt_io(ioreq_t *p) { struct vcpu *v = current; @@ -30,42 +19,62 @@ static int handle_pmt_io(ioreq_t *p) /* PM_TMR_BLK is read-only */ return 1; } else if (p->dir == 1) { /* read */ + /* Set the correct value in the timer, accounting for time + * elapsed since the last time we did that. */ curr_gtime = hvm_get_guest_time(s->vcpu); - s->pm1_timer += ((curr_gtime - s->last_gtime) * s->scale) >> 32; - p->data = s->pm1_timer; + s->pm.timer += ((curr_gtime - s->last_gtime) * s->scale) >> 32; + p->data = s->pm.timer; s->last_gtime = curr_gtime; return 1; } return 0; } +static int pmtimer_save(struct domain *d, hvm_domain_context_t *h) +{ + PMTState *s = &d->arch.hvm_domain.pl_time.vpmt; + uint32_t x; + + /* Update the counter to the guest's current time. We always save + * with the domain paused, so the saved time should be after the + * last_gtime, but just in case, make sure we only go forwards */ + x = ((s->vcpu->arch.hvm_vcpu.guest_time - s->last_gtime) * s->scale) >> 32; + if ( x < 1UL<<31 ) + s->pm.timer += x; + return hvm_save_entry(PMTIMER, 0, h, &s->pm); +} + +static int pmtimer_load(struct domain *d, hvm_domain_context_t *h) +{ + PMTState *s = &d->arch.hvm_domain.pl_time.vpmt; + + /* Reload the counter */ + if ( hvm_load_entry(PMTIMER, h, &s->pm) ) + return -EINVAL; + + /* Calculate future counter values from now. */ + s->last_gtime = hvm_get_guest_time(s->vcpu); + + return 0; +} + +HVM_REGISTER_SAVE_RESTORE(PMTIMER, pmtimer_save, pmtimer_load, + 1, HVMSR_PER_DOM); + + void pmtimer_init(struct vcpu *v, int base) { PMTState *s = &v->domain->arch.hvm_domain.pl_time.vpmt; - s->pm1_timer = 0; - s->pm1_status = 0; + s->pm.timer = 0; s->scale = ((uint64_t)FREQUENCE_PMTIMER << 32) / ticks_per_sec(v); s->vcpu = v; - init_timer(&s->timer, pmt_update_status, s, v->processor); - /* ACPI supports a 32-bit power management timer */ - set_timer(&s->timer, NOW() + (1000000000ULL << 31) / FREQUENCE_PMTIMER); - + /* Not implemented: we should set TMR_STS (bit 0 of PM1a_STS) every + * time the timer's top bit flips, and generate an SCI if TMR_EN + * (bit 0 of PM1a_EN) is set. For now, those registers are in + * qemu-dm, and we just calculate the timer's value on demand. */ + register_portio_handler(v->domain, base, 4, handle_pmt_io); } -void pmtimer_migrate_timers(struct vcpu *v) -{ - struct PMTState *vpmt = &v->domain->arch.hvm_domain.pl_time.vpmt; - - if (vpmt->vcpu == v) - migrate_timer(&vpmt->timer, v->processor); -} - -void pmtimer_deinit(struct domain *d) -{ - PMTState *s = &d->arch.hvm_domain.pl_time.vpmt; - - kill_timer(&s->timer); -} diff --git a/xen/arch/x86/hvm/rtc.c b/xen/arch/x86/hvm/rtc.c index d2ee7f8825..5cda6bbb75 100644 --- a/xen/arch/x86/hvm/rtc.c +++ b/xen/arch/x86/hvm/rtc.c @@ -417,7 +417,7 @@ static int rtc_load(struct domain *d, hvm_domain_context_t *h) return 0; } -HVM_REGISTER_SAVE_RESTORE(RTC, rtc_save, rtc_load); +HVM_REGISTER_SAVE_RESTORE(RTC, rtc_save, rtc_load, 1, HVMSR_PER_DOM); void rtc_init(struct vcpu *v, int base) diff --git a/xen/arch/x86/hvm/save.c b/xen/arch/x86/hvm/save.c new file mode 100644 index 0000000000..a19043c175 --- /dev/null +++ b/xen/arch/x86/hvm/save.c @@ -0,0 +1,229 @@ +/* + * hvm/save.c: Save and restore HVM guest's emulated hardware state. + * + * Copyright (c) 2004, Intel Corporation. + * Copyright (c) 2007, XenSource Inc. + * + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include + + +/* List of handlers for various HVM save and restore types */ +static struct { + hvm_save_handler save; + hvm_load_handler load; + const char *name; + size_t size; + int kind; +} hvm_sr_handlers [HVM_SAVE_CODE_MAX + 1] = {{NULL, NULL, ""},}; + +/* Init-time function to add entries to that list */ +void hvm_register_savevm(uint16_t typecode, + const char *name, + hvm_save_handler save_state, + hvm_load_handler load_state, + size_t size, int kind) +{ + ASSERT(typecode <= HVM_SAVE_CODE_MAX); + ASSERT(hvm_sr_handlers[typecode].save == NULL); + ASSERT(hvm_sr_handlers[typecode].load == NULL); + hvm_sr_handlers[typecode].save = save_state; + hvm_sr_handlers[typecode].load = load_state; + hvm_sr_handlers[typecode].name = name; + hvm_sr_handlers[typecode].size = size; + hvm_sr_handlers[typecode].kind = kind; +} + +size_t hvm_save_size(struct domain *d) +{ + struct vcpu *v; + size_t sz; + int i; + + /* Basic overhead for header and footer */ + sz = (2 * sizeof (struct hvm_save_descriptor)) + HVM_SAVE_LENGTH(HEADER); + + /* Plus space for each thing we will be saving */ + for ( i = 0; i <= HVM_SAVE_CODE_MAX; i++ ) + if ( hvm_sr_handlers[i].kind == HVMSR_PER_VCPU ) + for_each_vcpu(d, v) + sz += hvm_sr_handlers[i].size; + else + sz += hvm_sr_handlers[i].size; + + return sz; +} + + +int hvm_save(struct domain *d, hvm_domain_context_t *h) +{ + uint32_t eax, ebx, ecx, edx; + char *c; + struct hvm_save_header hdr; + struct hvm_save_end end; + hvm_save_handler handler; + uint16_t i; + + hdr.magic = HVM_FILE_MAGIC; + hdr.version = HVM_FILE_VERSION; + + /* Save some CPUID bits */ + cpuid(1, &eax, &ebx, &ecx, &edx); + hdr.cpuid = eax; + + /* Save xen changeset */ + c = strrchr(XEN_CHANGESET, ':'); + if ( c ) + hdr.changeset = simple_strtoll(c, NULL, 16); + else + hdr.changeset = -1ULL; /* Unknown */ + + if ( hvm_save_entry(HEADER, 0, h, &hdr) != 0 ) + { + gdprintk(XENLOG_ERR, "HVM save: failed to write header\n"); + return -EFAULT; + } + + /* Save all available kinds of state */ + for ( i = 0; i <= HVM_SAVE_CODE_MAX; i++ ) + { + handler = hvm_sr_handlers[i].save; + if ( handler != NULL ) + { + gdprintk(XENLOG_INFO, "HVM save: %s\n", hvm_sr_handlers[i].name); + if ( handler(d, h) != 0 ) + { + gdprintk(XENLOG_ERR, + "HVM save: failed to save type %"PRIu16"\n", i); + return -EFAULT; + } + } + } + + /* Save an end-of-file marker */ + if ( hvm_save_entry(END, 0, h, &end) != 0 ) + { + /* Run out of data */ + gdprintk(XENLOG_ERR, "HVM save: no room for end marker.\n"); + return -EFAULT; + } + + /* Save macros should not have let us overrun */ + ASSERT(h->cur <= h->size); + return 0; +} + +int hvm_load(struct domain *d, hvm_domain_context_t *h) +{ + uint32_t eax, ebx, ecx, edx; + char *c; + uint64_t cset; + struct hvm_save_header hdr; + struct hvm_save_descriptor *desc; + hvm_load_handler handler; + struct vcpu *v; + + /* Read the save header, which must be first */ + if ( hvm_load_entry(HEADER, h, &hdr) != 0 ) + return -1; + + if (hdr.magic != HVM_FILE_MAGIC) { + gdprintk(XENLOG_ERR, + "HVM restore: bad magic number %#"PRIx32"\n", hdr.magic); + return -1; + } + + if (hdr.version != HVM_FILE_VERSION) { + gdprintk(XENLOG_ERR, + "HVM restore: unsupported version %u\n", hdr.version); + return -1; + } + + cpuid(1, &eax, &ebx, &ecx, &edx); + /*TODO: need to define how big a difference is acceptable */ + if (hdr.cpuid != eax) + gdprintk(XENLOG_WARNING, "HVM restore: saved CPUID (%#"PRIx32") " + "does not match host (%#"PRIx32").\n", hdr.cpuid, eax); + + + c = strrchr(XEN_CHANGESET, ':'); + if ( hdr.changeset == -1ULL ) + gdprintk(XENLOG_WARNING, + "HVM restore: Xen changeset was not saved.\n"); + else if ( c == NULL ) + gdprintk(XENLOG_WARNING, + "HVM restore: Xen changeset is not available.\n"); + else + { + cset = simple_strtoll(c, NULL, 16); + if ( hdr.changeset != cset ) + gdprintk(XENLOG_WARNING, "HVM restore: saved Xen changeset (%#"PRIx64 + ") does not match host (%#"PRIx64").\n", hdr.changeset, cset); + } + + /* Down all the vcpus: we only re-enable the ones that had state saved. */ + for_each_vcpu(d, v) + if ( test_and_set_bit(_VCPUF_down, &v->vcpu_flags) ) + vcpu_sleep_nosync(v); + + while(1) { + + if ( h->size - h->cur < sizeof(struct hvm_save_descriptor) ) + { + /* Run out of data */ + gdprintk(XENLOG_ERR, + "HVM restore: save did not end with a null entry\n"); + return -1; + } + + /* Read the typecode of the next entry and check for the end-marker */ + desc = (struct hvm_save_descriptor *)(&h->data[h->cur]); + if ( desc->typecode == 0 ) + return 0; + + /* Find the handler for this entry */ + if ( desc->typecode > HVM_SAVE_CODE_MAX + || (handler = hvm_sr_handlers[desc->typecode].load) == NULL ) + { + gdprintk(XENLOG_ERR, + "HVM restore: unknown entry typecode %u\n", + desc->typecode); + return -1; + } + + /* Load the entry */ + gdprintk(XENLOG_INFO, "HVM restore: %s %"PRIu16"\n", + hvm_sr_handlers[desc->typecode].name, desc->instance); + if ( handler(d, h) != 0 ) + { + gdprintk(XENLOG_ERR, + "HVM restore: failed to load entry %u/%u\n", + desc->typecode, desc->instance); + return -1; + } + } + + /* Not reached */ +} diff --git a/xen/arch/x86/hvm/svm/intr.c b/xen/arch/x86/hvm/svm/intr.c index e3e0f0a40e..a4a458c72d 100644 --- a/xen/arch/x86/hvm/svm/intr.c +++ b/xen/arch/x86/hvm/svm/intr.c @@ -24,10 +24,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index 76112e14ef..d3df4a5c3e 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -29,7 +29,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -491,9 +492,6 @@ int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c) v->arch.guest_table = pagetable_from_pfn(mfn); if (old_base_mfn) put_page(mfn_to_page(old_base_mfn)); - /* - * arch.shadow_table should now hold the next CR3 for shadow - */ v->arch.hvm_svm.cpu_cr3 = c->cr3; } @@ -560,7 +558,7 @@ int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c) vmcb->sysenter_esp = c->sysenter_esp; vmcb->sysenter_eip = c->sysenter_eip; - shadow_update_paging_modes(v); + paging_update_paging_modes(v); return 0; bad_cr3: @@ -1095,7 +1093,7 @@ static int svm_do_page_fault(unsigned long va, struct cpu_user_regs *regs) "svm_do_page_fault = 0x%lx, eip = %lx, error_code = %lx", va, (unsigned long)current->arch.hvm_svm.vmcb->rip, (unsigned long)regs->error_code); - return shadow_fault(va, regs); + return paging_fault(va, regs); } @@ -1199,6 +1197,8 @@ static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, /* So far, we do not support 3DNow for the guest. */ clear_bit(X86_FEATURE_3DNOW & 31, &edx); clear_bit(X86_FEATURE_3DNOWEXT & 31, &edx); + /* no FFXSR instructions feature. */ + clear_bit(X86_FEATURE_FFXSR & 31, &edx); } else if ( input == 0x80000007 || input == 0x8000000A ) { @@ -1728,7 +1728,7 @@ static int svm_set_cr0(unsigned long value) v->arch.guest_table = pagetable_from_pfn(mfn); if ( old_base_mfn ) put_page(mfn_to_page(old_base_mfn)); - shadow_update_paging_modes(v); + paging_update_paging_modes(v); HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx", (unsigned long) (mfn << PAGE_SHIFT)); @@ -1751,7 +1751,7 @@ static int svm_set_cr0(unsigned long value) svm_inject_exception(v, TRAP_gp_fault, 1, 0); return 0; } - shadow_update_paging_modes(v); + paging_update_paging_modes(v); } else if ( (value & (X86_CR0_PE | X86_CR0_PG)) == X86_CR0_PE ) { @@ -1761,7 +1761,7 @@ static int svm_set_cr0(unsigned long value) clear_bit(SVM_CPU_STATE_LMA_ENABLED, &v->arch.hvm_svm.cpu_state); } /* we should take care of this kind of situation */ - shadow_update_paging_modes(v); + paging_update_paging_modes(v); } return 1; @@ -1864,7 +1864,7 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs) mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT); if (mfn != pagetable_get_pfn(v->arch.guest_table)) goto bad_cr3; - shadow_update_cr3(v); + paging_update_cr3(v); } else { @@ -1915,7 +1915,7 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs) v->arch.guest_table = pagetable_from_pfn(mfn); if ( old_base_mfn ) put_page(mfn_to_page(old_base_mfn)); - shadow_update_paging_modes(v); + paging_update_paging_modes(v); HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx", (unsigned long) (mfn << PAGE_SHIFT)); @@ -1944,7 +1944,7 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs) * all TLB entries except global entries. */ if ((old_cr ^ value) & (X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE)) - shadow_update_paging_modes(v); + paging_update_paging_modes(v); break; case 8: @@ -2287,7 +2287,7 @@ void svm_handle_invlpg(const short invlpga, struct cpu_user_regs *regs) __update_guest_eip (vmcb, inst_len); } - shadow_invlpg(v, g_vaddr); + paging_invlpg(v, g_vaddr); } @@ -2658,7 +2658,7 @@ void walk_shadow_and_guest_pt(unsigned long gva) struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; paddr_t gpa; - gpa = shadow_gva_to_gpa(current, gva); + gpa = paging_gva_to_gpa(current, gva); printk("gva = %lx, gpa=%"PRIpaddr", gCR3=%x\n", gva, gpa, (u32)vmcb->cr3); if( !svm_paging_enabled(v) || mmio_space(gpa) ) return; @@ -2679,7 +2679,7 @@ void walk_shadow_and_guest_pt(unsigned long gva) shadow_sync_va(v, gva); gpte.l1 = 0; - __copy_from_user(&gpte, &linear_pg_table[ l1_linear_offset(gva) ], + __copy_from_user(&gpte, &__linear_l1_table[ l1_linear_offset(gva) ], sizeof(gpte) ); printk( "G-PTE = %x, flags=%x\n", gpte.l1, l1e_get_flags(gpte) ); @@ -2724,7 +2724,7 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs) if (svm_dbg_on && exit_reason == VMEXIT_EXCEPTION_PF) { if (svm_paging_enabled(v) && - !mmio_space(shadow_gva_to_gpa(current, vmcb->exitinfo2))) + !mmio_space(paging_gva_to_gpa(current, vmcb->exitinfo2))) { printk("I%08ld,ExC=%s(%d),IP=%x:%"PRIx64"," "I1=%"PRIx64",I2=%"PRIx64",INT=%"PRIx64", " @@ -2734,7 +2734,7 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs) (u64)vmcb->exitinfo1, (u64)vmcb->exitinfo2, (u64)vmcb->exitintinfo.bytes, - (u64)shadow_gva_to_gpa(current, vmcb->exitinfo2)); + (u64)paging_gva_to_gpa(current, vmcb->exitinfo2)); } else { diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c index 46d98f9215..0a0622fb75 100644 --- a/xen/arch/x86/hvm/svm/vmcb.c +++ b/xen/arch/x86/hvm/svm/vmcb.c @@ -23,10 +23,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include @@ -196,7 +196,7 @@ static int construct_vmcb(struct vcpu *v) read_cr4() & ~(X86_CR4_PGE | X86_CR4_PSE | X86_CR4_PAE); vmcb->cr4 = arch_svm->cpu_shadow_cr4 | SVM_CR4_HOST_MASK; - shadow_update_paging_modes(v); + paging_update_paging_modes(v); vmcb->cr3 = v->arch.hvm_vcpu.hw_cr3; arch_svm->vmcb->exception_intercepts = MONITOR_DEFAULT_EXCEPTION_BITMAP; @@ -209,7 +209,8 @@ int svm_create_vmcb(struct vcpu *v) struct arch_svm_struct *arch_svm = &v->arch.hvm_svm; int rc; - if ( (arch_svm->vmcb = alloc_vmcb()) == NULL ) + if ( (arch_svm->vmcb == NULL) && + (arch_svm->vmcb = alloc_vmcb()) == NULL ) { printk("Failed to create a new VMCB\n"); return -ENOMEM; diff --git a/xen/arch/x86/hvm/vioapic.c b/xen/arch/x86/hvm/vioapic.c index 4e444ce93d..0ce59f94b1 100644 --- a/xen/arch/x86/hvm/vioapic.c +++ b/xen/arch/x86/hvm/vioapic.c @@ -514,7 +514,7 @@ static int ioapic_load(struct domain *d, hvm_domain_context_t *h) return 0; } -HVM_REGISTER_SAVE_RESTORE(IOAPIC, ioapic_save, ioapic_load); +HVM_REGISTER_SAVE_RESTORE(IOAPIC, ioapic_save, ioapic_load, 1, HVMSR_PER_DOM); void vioapic_init(struct domain *d) { diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c index b38dee2e85..450dcb3237 100644 --- a/xen/arch/x86/hvm/vlapic.c +++ b/xen/arch/x86/hvm/vlapic.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -83,8 +82,6 @@ static unsigned int vlapic_lvt_mask[VLAPIC_LVT_NUM] = #define vlapic_base_address(vlapic) \ (vlapic->hw.apic_base_msr & MSR_IA32_APICBASE_BASE) -static int vlapic_reset(struct vlapic *vlapic); - /* * Generic APIC bitmap vector update & search routines. */ @@ -293,8 +290,11 @@ static int vlapic_accept_irq(struct vcpu *v, int delivery_mode, break; case APIC_DM_SMI: + gdprintk(XENLOG_WARNING, "Ignoring guest SMI\n"); + break; + case APIC_DM_NMI: - gdprintk(XENLOG_WARNING, "Ignoring guest SMI/NMI\n"); + gdprintk(XENLOG_WARNING, "Ignoring guest NMI\n"); break; case APIC_DM_INIT: @@ -303,10 +303,7 @@ static int vlapic_accept_irq(struct vcpu *v, int delivery_mode, break; /* FIXME How to check the situation after vcpu reset? */ if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) ) - { - gdprintk(XENLOG_ERR, "Reset hvm vcpu not supported yet\n"); - goto exit_and_crash; - } + hvm_vcpu_reset(v); v->arch.hvm_vcpu.init_sipi_sipi_state = HVM_VCPU_INIT_SIPI_SIPI_STATE_WAIT_SIPI; result = 1; @@ -764,7 +761,7 @@ int cpu_get_apic_interrupt(struct vcpu *v, int *mode) } /* Reset the VLPAIC back to its power-on/reset state. */ -static int vlapic_reset(struct vlapic *vlapic) +void vlapic_reset(struct vlapic *vlapic) { struct vcpu *v = vlapic_vcpu(vlapic); int i; @@ -793,8 +790,6 @@ static int vlapic_reset(struct vlapic *vlapic) vlapic_set_reg(vlapic, APIC_SPIV, 0xff); vlapic->hw.disabled |= VLAPIC_SW_DISABLED; - - return 1; } #ifdef HVM_DEBUG_SUSPEND @@ -908,8 +903,10 @@ static int lapic_load_regs(struct domain *d, hvm_domain_context_t *h) return 0; } -HVM_REGISTER_SAVE_RESTORE(LAPIC, lapic_save_hidden, lapic_load_hidden); -HVM_REGISTER_SAVE_RESTORE(LAPIC_REGS, lapic_save_regs, lapic_load_regs); +HVM_REGISTER_SAVE_RESTORE(LAPIC, lapic_save_hidden, lapic_load_hidden, + 1, HVMSR_PER_VCPU); +HVM_REGISTER_SAVE_RESTORE(LAPIC_REGS, lapic_save_regs, lapic_load_regs, + 1, HVMSR_PER_VCPU); int vlapic_init(struct vcpu *v) { @@ -922,7 +919,6 @@ int vlapic_init(struct vcpu *v) { dprintk(XENLOG_ERR, "malloc vlapic regs error for vcpu %x\n", v->vcpu_id); - xfree(vlapic); return -ENOMEM; } diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index 20c3ddf61b..9aa54d1922 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -295,6 +295,11 @@ static void construct_vmcs(struct vcpu *v) vmx_vmcs_enter(v); + v->arch.hvm_vmx.cpu_cr2 = 0; + v->arch.hvm_vmx.cpu_cr3 = 0; + memset(&v->arch.hvm_vmx.msr_state, 0, sizeof(v->arch.hvm_vmx.msr_state)); + v->arch.hvm_vmx.vmxassist_enabled = 0; + /* VMCS controls. */ __vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_control); __vmwrite(VM_EXIT_CONTROLS, vmx_vmexit_control); @@ -443,15 +448,18 @@ static void construct_vmcs(struct vcpu *v) vmx_vmcs_exit(v); - shadow_update_paging_modes(v); /* will update HOST & GUEST_CR3 as reqd */ + paging_update_paging_modes(v); /* will update HOST & GUEST_CR3 as reqd */ } int vmx_create_vmcs(struct vcpu *v) { - if ( (v->arch.hvm_vmx.vmcs = vmx_alloc_vmcs()) == NULL ) - return -ENOMEM; - - __vmx_clear_vmcs(v); + if ( v->arch.hvm_vmx.vmcs == NULL ) + { + if ( (v->arch.hvm_vmx.vmcs = vmx_alloc_vmcs()) == NULL ) + return -ENOMEM; + + __vmx_clear_vmcs(v); + } construct_vmcs(v); diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 0a4c008b37..d3ba86b7d0 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -35,12 +35,13 @@ #include #include #include +#include +#include #include #include #include #include #include -#include #include #include #include @@ -484,9 +485,6 @@ int vmx_vmcs_restore(struct vcpu *v, struct hvm_hw_cpu *c) v->arch.guest_table = pagetable_from_pfn(mfn); if (old_base_mfn) put_page(mfn_to_page(old_base_mfn)); - /* - * arch.shadow_table should now hold the next CR3 for shadow - */ v->arch.hvm_vmx.cpu_cr3 = c->cr3; } @@ -556,7 +554,7 @@ int vmx_vmcs_restore(struct vcpu *v, struct hvm_hw_cpu *c) vmx_vmcs_exit(v); - shadow_update_paging_modes(v); + paging_update_paging_modes(v); return 0; bad_cr3: @@ -1126,7 +1124,7 @@ static int vmx_do_page_fault(unsigned long va, struct cpu_user_regs *regs) } #endif - result = shadow_fault(va, regs); + result = paging_fault(va, regs); TRACE_VMEXIT(2, result); #if 0 @@ -1277,7 +1275,7 @@ static void vmx_do_invlpg(unsigned long va) * We do the safest things first, then try to update the shadow * copying from guest */ - shadow_invlpg(v, va); + paging_invlpg(v, va); } @@ -1691,9 +1689,6 @@ static int vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c) v->arch.guest_table = pagetable_from_pfn(mfn); if (old_base_mfn) put_page(mfn_to_page(old_base_mfn)); - /* - * arch.shadow_table should now hold the next CR3 for shadow - */ v->arch.hvm_vmx.cpu_cr3 = c->cr3; } @@ -1753,7 +1748,7 @@ static int vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c) __vmwrite(GUEST_LDTR_BASE, c->ldtr_base); __vmwrite(GUEST_LDTR_AR_BYTES, c->ldtr_arbytes.bytes); - shadow_update_paging_modes(v); + paging_update_paging_modes(v); return 0; bad_cr3: @@ -1906,14 +1901,11 @@ static int vmx_set_cr0(unsigned long value) v->arch.guest_table = pagetable_from_pfn(mfn); if (old_base_mfn) put_page(mfn_to_page(old_base_mfn)); - shadow_update_paging_modes(v); + paging_update_paging_modes(v); HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx", (unsigned long) (mfn << PAGE_SHIFT)); - /* - * arch->shadow_table should hold the next CR3 for shadow - */ HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx", v->arch.hvm_vmx.cpu_cr3, mfn); } @@ -1981,7 +1973,7 @@ static int vmx_set_cr0(unsigned long value) vm_entry_value &= ~VM_ENTRY_IA32E_MODE; __vmwrite(VM_ENTRY_CONTROLS, vm_entry_value); } - shadow_update_paging_modes(v); + paging_update_paging_modes(v); } return 1; @@ -2070,7 +2062,7 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs) mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT); if (mfn != pagetable_get_pfn(v->arch.guest_table)) goto bad_cr3; - shadow_update_cr3(v); + paging_update_cr3(v); } else { /* * If different, make a shadow. Check if the PDBR is valid @@ -2084,9 +2076,6 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs) v->arch.guest_table = pagetable_from_pfn(mfn); if (old_base_mfn) put_page(mfn_to_page(old_base_mfn)); - /* - * arch.shadow_table should now hold the next CR3 for shadow - */ v->arch.hvm_vmx.cpu_cr3 = value; update_cr3(v); HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx", value); @@ -2120,9 +2109,6 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs) HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx", (unsigned long) (mfn << PAGE_SHIFT)); - /* - * arch->shadow_table should hold the next CR3 for shadow - */ HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx", v->arch.hvm_vmx.cpu_cr3, mfn); @@ -2148,7 +2134,7 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs) * all TLB entries except global entries. */ if ( (old_cr ^ value) & (X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE) ) - shadow_update_paging_modes(v); + paging_update_paging_modes(v); break; case 8: diff --git a/xen/arch/x86/hvm/vpic.c b/xen/arch/x86/hvm/vpic.c index 41e3ed11a4..3a5b2a16a8 100644 --- a/xen/arch/x86/hvm/vpic.c +++ b/xen/arch/x86/hvm/vpic.c @@ -440,7 +440,7 @@ static int vpic_load(struct domain *d, hvm_domain_context_t *h) return 0; } -HVM_REGISTER_SAVE_RESTORE(PIC, vpic_save, vpic_load); +HVM_REGISTER_SAVE_RESTORE(PIC, vpic_save, vpic_load, 2, HVMSR_PER_DOM); void vpic_init(struct domain *d) { diff --git a/xen/arch/x86/machine_kexec.c b/xen/arch/x86/machine_kexec.c index 81c392a7d3..5e82975366 100644 --- a/xen/arch/x86/machine_kexec.c +++ b/xen/arch/x86/machine_kexec.c @@ -15,11 +15,15 @@ #include #include #include -#include #include #include #include +typedef void (*relocate_new_kernel_t)( + unsigned long indirection_page, + unsigned long *page_list, + unsigned long start_address); + int machine_kexec_load(int type, int slot, xen_kexec_image_t *image) { unsigned long prev_ma = 0; @@ -40,8 +44,26 @@ int machine_kexec_load(int type, int slot, xen_kexec_image_t *image) else { /* Odd pages: va for previous ma. */ - set_fixmap(fix_base + (k >> 1), prev_ma); - image->page_list[k] = fix_to_virt(fix_base + (k >> 1)); + if ( IS_COMPAT(dom0) ) + { + + /* + * The compatability bounce code sets up a page table + * with a 1-1 mapping of the first 1G of memory so + * VA==PA here. + * + * This Linux purgatory code still sets up separate + * high and low mappings on the control page (entries + * 0 and 1) but it is harmless if they are equal since + * that PT is not live at the time. + */ + image->page_list[k] = prev_ma; + } + else + { + set_fixmap(fix_base + (k >> 1), prev_ma); + image->page_list[k] = fix_to_virt(fix_base + (k >> 1)); + } } } @@ -94,6 +116,31 @@ void machine_reboot_kexec(xen_kexec_image_t *image) BUG(); } +void machine_kexec(xen_kexec_image_t *image) +{ +#ifdef CONFIG_COMPAT + if ( IS_COMPAT(dom0) ) + { + extern void compat_machine_kexec(unsigned long rnk, + unsigned long indirection_page, + unsigned long *page_list, + unsigned long start_address); + compat_machine_kexec(image->page_list[1], + image->indirection_page, + image->page_list, + image->start_address); + } + else +#endif + { + relocate_new_kernel_t rnk; + + rnk = (relocate_new_kernel_t) image->page_list[1]; + (*rnk)(image->indirection_page, image->page_list, + image->start_address); + } +} + /* * Local variables: * mode: C diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index f23638cdb9..5d043ad598 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -99,6 +99,7 @@ #include #include #include +#include #include #include #include @@ -373,9 +374,6 @@ void write_ptbase(struct vcpu *v) /* Should be called after CR3 is updated. * Updates vcpu->arch.cr3 and, for HVM guests, vcpu->arch.hvm_vcpu.cpu_cr3. * - * Also updates other state derived from CR3 (vcpu->arch.guest_vtable, - * shadow_vtable, etc). - * * Uses values found in vcpu->arch.(guest_table and guest_table_user), and * for HVM guests, arch.monitor_table and hvm's guest CR3. * @@ -385,9 +383,9 @@ void update_cr3(struct vcpu *v) { unsigned long cr3_mfn=0; - if ( shadow_mode_enabled(v->domain) ) + if ( paging_mode_enabled(v->domain) ) { - shadow_update_cr3(v); + paging_update_cr3(v); return; } @@ -615,7 +613,7 @@ get_page_from_l1e( * qemu-dm helper process in dom0 to map the domain's memory without * messing up the count of "real" writable mappings.) */ okay = (((l1e_get_flags(l1e) & _PAGE_RW) && - !(unlikely(shadow_mode_external(d) && (d != current->domain)))) + !(unlikely(paging_mode_external(d) && (d != current->domain)))) ? get_page_and_type(page, d, PGT_writable_page) : get_page(page, d)); if ( !okay ) @@ -804,9 +802,9 @@ void put_page_from_l1e(l1_pgentry_t l1e, struct domain *d) } /* Remember we didn't take a type-count of foreign writable mappings - * to shadow external domains */ + * to paging-external domains */ if ( (l1e_get_flags(l1e) & _PAGE_RW) && - !(unlikely((e != d) && shadow_mode_external(e))) ) + !(unlikely((e != d) && paging_mode_external(e))) ) { put_page_and_type(page); } @@ -976,6 +974,19 @@ static void pae_flush_pgd( l3_pgentry_t *l3tab_ptr; struct pae_l3_cache *cache; + if ( unlikely(shadow_mode_enabled(d)) ) + { + cpumask_t m = CPU_MASK_NONE; + /* Re-shadow this l3 table on any vcpus that are using it */ + for_each_vcpu ( d, v ) + if ( pagetable_get_pfn(v->arch.guest_table) == mfn ) + { + paging_update_cr3(v); + cpus_or(m, m, v->vcpu_dirty_cpumask); + } + flush_tlb_mask(m); + } + /* If below 4GB then the pgdir is not shadowed in low memory. */ if ( !l3tab_needs_shadow(mfn) ) return; @@ -1259,20 +1270,13 @@ static inline int update_intpte(intpte_t *p, { int rv = 1; #ifndef PTE_UPDATE_WITH_CMPXCHG - if ( unlikely(shadow_mode_enabled(v->domain)) ) - rv = shadow_write_guest_entry(v, p, new, _mfn(mfn)); - else - rv = (!__copy_to_user(p, &new, sizeof(new))); + rv = paging_write_guest_entry(v, p, new, _mfn(mfn)); #else { intpte_t t = old; for ( ; ; ) { - if ( unlikely(shadow_mode_enabled(v->domain)) ) - rv = shadow_cmpxchg_guest_entry(v, p, &t, new, _mfn(mfn)); - else - rv = (!cmpxchg_user(p, t, new)); - + rv = paging_cmpxchg_guest_entry(v, p, &t, new, _mfn(mfn)); if ( unlikely(rv == 0) ) { MEM_LOG("Failed to update %" PRIpte " -> %" PRIpte @@ -1310,7 +1314,7 @@ static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e, if ( unlikely(__copy_from_user(&ol1e, pl1e, sizeof(ol1e)) != 0) ) return 0; - if ( unlikely(shadow_mode_refcounts(d)) ) + if ( unlikely(paging_mode_refcounts(d)) ) return UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, current); if ( l1e_get_flags(nl1e) & _PAGE_PRESENT ) @@ -1572,7 +1576,7 @@ void free_page_type(struct page_info *page, unsigned long type) */ queue_deferred_ops(owner, DOP_FLUSH_ALL_TLBS); - if ( unlikely(shadow_mode_enabled(owner)) ) + if ( unlikely(paging_mode_enabled(owner)) ) { /* A page table is dirtied when its type count becomes zero. */ mark_dirty(owner, page_to_mfn(page)); @@ -1771,7 +1775,7 @@ int new_guest_cr3(unsigned long mfn) #ifdef CONFIG_COMPAT if ( IS_COMPAT(d) ) { - okay = shadow_mode_refcounts(d) + okay = paging_mode_refcounts(d) ? 0 /* Old code was broken, but what should it be? */ : mod_l4_entry(__va(pagetable_get_paddr(v->arch.guest_table)), l4e_from_pfn(mfn, (_PAGE_PRESENT|_PAGE_RW| @@ -1788,7 +1792,7 @@ int new_guest_cr3(unsigned long mfn) return 1; } #endif - okay = shadow_mode_refcounts(d) + okay = paging_mode_refcounts(d) ? get_page_from_pagenr(mfn, d) : get_page_and_type_from_pagenr(mfn, PGT_root_page_table, d); if ( unlikely(!okay) ) @@ -1808,7 +1812,7 @@ int new_guest_cr3(unsigned long mfn) if ( likely(old_base_mfn != 0) ) { - if ( shadow_mode_refcounts(d) ) + if ( paging_mode_refcounts(d) ) put_page(mfn_to_page(old_base_mfn)); else put_page_and_type(mfn_to_page(old_base_mfn)); @@ -1861,7 +1865,7 @@ static int set_foreigndom(domid_t domid) d->domain_id); okay = 0; } - else if ( unlikely(shadow_mode_translate(d)) ) + else if ( unlikely(paging_mode_translate(d)) ) { MEM_LOG("Cannot mix foreign mappings with translated domains"); okay = 0; @@ -2007,7 +2011,7 @@ int do_mmuext_op( if ( (op.cmd - MMUEXT_PIN_L1_TABLE) > (CONFIG_PAGING_LEVELS - 1) ) break; - if ( shadow_mode_refcounts(FOREIGNDOM) ) + if ( paging_mode_refcounts(FOREIGNDOM) ) break; okay = get_page_and_type_from_pagenr(mfn, type, FOREIGNDOM); @@ -2032,7 +2036,7 @@ int do_mmuext_op( break; case MMUEXT_UNPIN_TABLE: - if ( shadow_mode_refcounts(d) ) + if ( paging_mode_refcounts(d) ) break; if ( unlikely(!(okay = get_page_from_pagenr(mfn, d))) ) @@ -2070,7 +2074,7 @@ int do_mmuext_op( } if (likely(mfn != 0)) { - if ( shadow_mode_refcounts(d) ) + if ( paging_mode_refcounts(d) ) okay = get_page_from_pagenr(mfn, d); else okay = get_page_and_type_from_pagenr( @@ -2087,7 +2091,7 @@ int do_mmuext_op( v->arch.guest_table_user = pagetable_from_pfn(mfn); if ( old_mfn != 0 ) { - if ( shadow_mode_refcounts(d) ) + if ( paging_mode_refcounts(d) ) put_page(mfn_to_page(old_mfn)); else put_page_and_type(mfn_to_page(old_mfn)); @@ -2101,8 +2105,8 @@ int do_mmuext_op( break; case MMUEXT_INVLPG_LOCAL: - if ( !shadow_mode_enabled(d) - || shadow_invlpg(v, op.arg1.linear_addr) != 0 ) + if ( !paging_mode_enabled(d) + || paging_invlpg(v, op.arg1.linear_addr) != 0 ) local_flush_tlb_one(op.arg1.linear_addr); break; @@ -2149,7 +2153,7 @@ int do_mmuext_op( unsigned long ptr = op.arg1.linear_addr; unsigned long ents = op.arg2.nr_ents; - if ( shadow_mode_external(d) ) + if ( paging_mode_external(d) ) { MEM_LOG("ignoring SET_LDT hypercall from external " "domain %u", d->domain_id); @@ -2298,9 +2302,9 @@ int do_mmu_update( case PGT_l3_page_table: case PGT_l4_page_table: { - if ( shadow_mode_refcounts(d) ) + if ( paging_mode_refcounts(d) ) { - MEM_LOG("mmu update on shadow-refcounted domain!"); + MEM_LOG("mmu update on auto-refcounted domain!"); break; } @@ -2351,13 +2355,7 @@ int do_mmu_update( if ( unlikely(!get_page_type(page, PGT_writable_page)) ) break; - if ( unlikely(shadow_mode_enabled(d)) ) - okay = shadow_write_guest_entry(v, va, req.val, _mfn(mfn)); - else - { - *(intpte_t *)va = req.val; - okay = 1; - } + okay = paging_write_guest_entry(v, va, req.val, _mfn(mfn)); put_page_type(page); } @@ -2380,9 +2378,9 @@ int do_mmu_update( break; } - if ( unlikely(shadow_mode_translate(FOREIGNDOM)) ) + if ( unlikely(paging_mode_translate(FOREIGNDOM)) ) { - MEM_LOG("Mach-phys update on shadow-translate guest"); + MEM_LOG("Mach-phys update on auto-translate guest"); break; } @@ -2472,7 +2470,7 @@ static int create_grant_pte_mapping( goto failed; } - if ( !shadow_mode_refcounts(d) ) + if ( !paging_mode_refcounts(d) ) put_page_from_l1e(ol1e, d); put_page_type(page); @@ -2578,7 +2576,7 @@ static int create_grant_va_mapping( if ( !okay ) return GNTST_general_error; - if ( !shadow_mode_refcounts(d) ) + if ( !paging_mode_refcounts(d) ) put_page_from_l1e(ol1e, d); return GNTST_okay; @@ -2704,7 +2702,7 @@ int do_update_va_mapping(unsigned long va, u64 val64, perfc_incrc(calls_to_update_va); - if ( unlikely(!__addr_ok(va) && !shadow_mode_external(d)) ) + if ( unlikely(!__addr_ok(va) && !paging_mode_external(d)) ) return -EINVAL; LOCK_BIGLOCK(d); @@ -2744,8 +2742,8 @@ int do_update_va_mapping(unsigned long va, u64 val64, switch ( (bmap_ptr = flags & ~UVMF_FLUSHTYPE_MASK) ) { case UVMF_LOCAL: - if ( !shadow_mode_enabled(d) - || (shadow_invlpg(current, va) != 0) ) + if ( !paging_mode_enabled(d) + || (paging_invlpg(current, va) != 0) ) local_flush_tlb_one(va); break; case UVMF_ALL: @@ -2980,7 +2978,7 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg) break; } - if ( !shadow_mode_translate(d) || (mfn == 0) ) + if ( !paging_mode_translate(d) || (mfn == 0) ) { put_domain(d); return -EINVAL; @@ -3235,17 +3233,12 @@ static int ptwr_emulated_update( if ( do_cmpxchg ) { int okay; + intpte_t t = old; ol1e = l1e_from_intpte(old); - if ( shadow_mode_enabled(d) ) - { - intpte_t t = old; - okay = shadow_cmpxchg_guest_entry(v, (intpte_t *) pl1e, - &t, val, _mfn(mfn)); - okay = (okay && t == old); - } - else - okay = (cmpxchg((intpte_t *)pl1e, old, val) == old); + okay = paging_cmpxchg_guest_entry(v, (intpte_t *) pl1e, + &t, val, _mfn(mfn)); + okay = (okay && t == old); if ( !okay ) { diff --git a/xen/arch/x86/mm/Makefile b/xen/arch/x86/mm/Makefile index 5043fd9501..a58211d91a 100644 --- a/xen/arch/x86/mm/Makefile +++ b/xen/arch/x86/mm/Makefile @@ -1 +1,4 @@ subdir-y += shadow + +obj-y += paging.o +obj-y += p2m.o diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c new file mode 100644 index 0000000000..cc42ed8c6a --- /dev/null +++ b/xen/arch/x86/mm/p2m.c @@ -0,0 +1,699 @@ +/****************************************************************************** + * arch/x86/mm/p2m.c + * + * physical-to-machine mappings for automatically-translated domains. + * + * Parts of this code are Copyright (c) 2007 by Advanced Micro Devices. + * Parts of this code are Copyright (c) 2006 by XenSource Inc. + * Parts of this code are Copyright (c) 2006 by Michael A Fetterman + * Parts based on earlier work by Michael A Fetterman, Ian Pratt et al. + * + * 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +/* Debugging and auditing of the P2M code? */ +#define P2M_AUDIT 0 +#define P2M_DEBUGGING 1 + +/* The P2M lock. This protects all updates to the p2m table. + * Updates are expected to be safe against concurrent reads, + * which do *not* require the lock */ + +#define p2m_lock_init(_d) \ + do { \ + spin_lock_init(&(_d)->arch.p2m.lock); \ + (_d)->arch.p2m.locker = -1; \ + (_d)->arch.p2m.locker_function = "nobody"; \ + } while (0) + +#define p2m_lock(_d) \ + do { \ + if ( unlikely((_d)->arch.p2m.locker == current->processor) )\ + { \ + printk("Error: p2m lock held by %s\n", \ + (_d)->arch.p2m.locker_function); \ + BUG(); \ + } \ + spin_lock(&(_d)->arch.p2m.lock); \ + ASSERT((_d)->arch.p2m.locker == -1); \ + (_d)->arch.p2m.locker = current->processor; \ + (_d)->arch.p2m.locker_function = __func__; \ + } while (0) + +#define p2m_unlock(_d) \ + do { \ + ASSERT((_d)->arch.p2m.locker == current->processor); \ + (_d)->arch.p2m.locker = -1; \ + (_d)->arch.p2m.locker_function = "nobody"; \ + spin_unlock(&(_d)->arch.p2m.lock); \ + } while (0) + + + +/* Printouts */ +#define P2M_PRINTK(_f, _a...) \ + debugtrace_printk("p2m: %s(): " _f, __func__, ##_a) +#define P2M_ERROR(_f, _a...) \ + printk("pg error: %s(): " _f, __func__, ##_a) +#if P2M_DEBUGGING +#define P2M_DEBUG(_f, _a...) \ + debugtrace_printk("p2mdebug: %s(): " _f, __func__, ##_a) +#else +#define P2M_DEBUG(_f, _a...) do { (void)(_f); } while(0) +#endif + + +/* Override macros from asm/page.h to make them work with mfn_t */ +#undef mfn_to_page +#define mfn_to_page(_m) (frame_table + mfn_x(_m)) +#undef mfn_valid +#define mfn_valid(_mfn) (mfn_x(_mfn) < max_page) +#undef page_to_mfn +#define page_to_mfn(_pg) (_mfn((_pg) - frame_table)) + + + +// Find the next level's P2M entry, checking for out-of-range gfn's... +// Returns NULL on error. +// +static l1_pgentry_t * +p2m_find_entry(void *table, unsigned long *gfn_remainder, + unsigned long gfn, u32 shift, u32 max) +{ + u32 index; + + index = *gfn_remainder >> shift; + if ( index >= max ) + { + P2M_DEBUG("gfn=0x%lx out of range " + "(gfn_remainder=0x%lx shift=%d index=0x%x max=0x%x)\n", + gfn, *gfn_remainder, shift, index, max); + return NULL; + } + *gfn_remainder &= (1 << shift) - 1; + return (l1_pgentry_t *)table + index; +} + +// Walk one level of the P2M table, allocating a new table if required. +// Returns 0 on error. +// +static int +p2m_next_level(struct domain *d, mfn_t *table_mfn, void **table, + unsigned long *gfn_remainder, unsigned long gfn, u32 shift, + u32 max, unsigned long type) +{ + l1_pgentry_t *p2m_entry; + l1_pgentry_t new_entry; + void *next; + ASSERT(d->arch.p2m.alloc_page); + + if ( !(p2m_entry = p2m_find_entry(*table, gfn_remainder, gfn, + shift, max)) ) + return 0; + + if ( !(l1e_get_flags(*p2m_entry) & _PAGE_PRESENT) ) + { + struct page_info *pg = d->arch.p2m.alloc_page(d); + if ( pg == NULL ) + return 0; + list_add_tail(&pg->list, &d->arch.p2m.pages); + pg->u.inuse.type_info = type | 1 | PGT_validated; + pg->count_info = 1; + + new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)), + __PAGE_HYPERVISOR|_PAGE_USER); + + switch ( type ) { + case PGT_l3_page_table: + paging_write_p2m_entry(d, gfn, p2m_entry, new_entry, 4); + break; + case PGT_l2_page_table: + paging_write_p2m_entry(d, gfn, p2m_entry, new_entry, 3); + break; + case PGT_l1_page_table: + paging_write_p2m_entry(d, gfn, p2m_entry, new_entry, 2); + break; + default: + BUG(); + break; + } + } + *table_mfn = _mfn(l1e_get_pfn(*p2m_entry)); + next = map_domain_page(mfn_x(*table_mfn)); + unmap_domain_page(*table); + *table = next; + + return 1; +} + +// Returns 0 on error (out of memory) +static int +set_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn) +{ + // XXX -- this might be able to be faster iff current->domain == d + mfn_t table_mfn = pagetable_get_mfn(d->arch.phys_table); + void *table =map_domain_page(mfn_x(table_mfn)); + unsigned long gfn_remainder = gfn; + l1_pgentry_t *p2m_entry; + l1_pgentry_t entry_content; + int rv=0; + +#if CONFIG_PAGING_LEVELS >= 4 + if ( !p2m_next_level(d, &table_mfn, &table, &gfn_remainder, gfn, + L4_PAGETABLE_SHIFT - PAGE_SHIFT, + L4_PAGETABLE_ENTRIES, PGT_l3_page_table) ) + goto out; +#endif +#if CONFIG_PAGING_LEVELS >= 3 + // When using PAE Xen, we only allow 33 bits of pseudo-physical + // address in translated guests (i.e. 8 GBytes). This restriction + // comes from wanting to map the P2M table into the 16MB RO_MPT hole + // in Xen's address space for translated PV guests. + // + if ( !p2m_next_level(d, &table_mfn, &table, &gfn_remainder, gfn, + L3_PAGETABLE_SHIFT - PAGE_SHIFT, + (CONFIG_PAGING_LEVELS == 3 + ? 8 + : L3_PAGETABLE_ENTRIES), + PGT_l2_page_table) ) + goto out; +#endif + if ( !p2m_next_level(d, &table_mfn, &table, &gfn_remainder, gfn, + L2_PAGETABLE_SHIFT - PAGE_SHIFT, + L2_PAGETABLE_ENTRIES, PGT_l1_page_table) ) + goto out; + + p2m_entry = p2m_find_entry(table, &gfn_remainder, gfn, + 0, L1_PAGETABLE_ENTRIES); + ASSERT(p2m_entry); + + /* Track the highest gfn for which we have ever had a valid mapping */ + if ( mfn_valid(mfn) && (gfn > d->arch.p2m.max_mapped_pfn) ) + d->arch.p2m.max_mapped_pfn = gfn; + + if ( mfn_valid(mfn) ) + entry_content = l1e_from_pfn(mfn_x(mfn), __PAGE_HYPERVISOR|_PAGE_USER); + else + entry_content = l1e_empty(); + + /* level 1 entry */ + paging_write_p2m_entry(d, gfn, p2m_entry, entry_content, 1); + + /* Success */ + rv = 1; + + out: + unmap_domain_page(table); + return rv; +} + + +/* Init the datastructures for later use by the p2m code */ +void p2m_init(struct domain *d) +{ + p2m_lock_init(d); + INIT_LIST_HEAD(&d->arch.p2m.pages); +} + + +// Allocate a new p2m table for a domain. +// +// The structure of the p2m table is that of a pagetable for xen (i.e. it is +// controlled by CONFIG_PAGING_LEVELS). +// +// The alloc_page and free_page functions will be used to get memory to +// build the p2m, and to release it again at the end of day. +// +// Returns 0 for success or -errno. +// +int p2m_alloc_table(struct domain *d, + struct page_info * (*alloc_page)(struct domain *d), + void (*free_page)(struct domain *d, struct page_info *pg)) + +{ + mfn_t mfn; + struct list_head *entry; + struct page_info *page, *p2m_top; + unsigned int page_count = 0; + unsigned long gfn; + + p2m_lock(d); + + if ( pagetable_get_pfn(d->arch.phys_table) != 0 ) + { + P2M_ERROR("p2m already allocated for this domain\n"); + p2m_unlock(d); + return -EINVAL; + } + + P2M_PRINTK("allocating p2m table\n"); + + d->arch.p2m.alloc_page = alloc_page; + d->arch.p2m.free_page = free_page; + + p2m_top = d->arch.p2m.alloc_page(d); + if ( p2m_top == NULL ) + { + p2m_unlock(d); + return -ENOMEM; + } +list_add_tail(&p2m_top->list, &d->arch.p2m.pages); + + p2m_top->count_info = 1; + p2m_top->u.inuse.type_info = +#if CONFIG_PAGING_LEVELS == 4 + PGT_l4_page_table +#elif CONFIG_PAGING_LEVELS == 3 + PGT_l3_page_table +#elif CONFIG_PAGING_LEVELS == 2 + PGT_l2_page_table +#endif + | 1 | PGT_validated; + + d->arch.phys_table = pagetable_from_mfn(page_to_mfn(p2m_top)); + + P2M_PRINTK("populating p2m table\n"); + + /* Initialise physmap tables for slot zero. Other code assumes this. */ + gfn = 0; +mfn = _mfn(INVALID_MFN); + if ( !set_p2m_entry(d, gfn, mfn) ) + goto error; + + for ( entry = d->page_list.next; + entry != &d->page_list; + entry = entry->next ) + { + page = list_entry(entry, struct page_info, list); + mfn = page_to_mfn(page); + gfn = get_gpfn_from_mfn(mfn_x(mfn)); + page_count++; + if ( +#ifdef __x86_64__ + (gfn != 0x5555555555555555L) +#else + (gfn != 0x55555555L) +#endif + && gfn != INVALID_M2P_ENTRY + && !set_p2m_entry(d, gfn, mfn) ) + goto error; + } + + P2M_PRINTK("p2m table initialised (%u pages)\n", page_count); + p2m_unlock(d); + return 0; + + error: + P2M_PRINTK("failed to initialize p2m table, gfn=%05lx, mfn=%" + PRI_mfn "\n", gfn, mfn_x(mfn)); + p2m_unlock(d); + return -ENOMEM; +} + +void p2m_teardown(struct domain *d) +/* Return all the p2m pages to Xen. + * We know we don't have any extra mappings to these pages */ +{ + struct list_head *entry, *n; + struct page_info *pg; + + p2m_lock(d); + d->arch.phys_table = pagetable_null(); + + list_for_each_safe(entry, n, &d->arch.p2m.pages) + { + pg = list_entry(entry, struct page_info, list); + list_del(entry); + d->arch.p2m.free_page(d, pg); + } + p2m_unlock(d); +} + +mfn_t +gfn_to_mfn_foreign(struct domain *d, unsigned long gpfn) +/* Read another domain's p2m entries */ +{ + mfn_t mfn; + paddr_t addr = ((paddr_t)gpfn) << PAGE_SHIFT; + l2_pgentry_t *l2e; + l1_pgentry_t *l1e; + + ASSERT(paging_mode_translate(d)); + mfn = pagetable_get_mfn(d->arch.phys_table); + + + if ( gpfn > d->arch.p2m.max_mapped_pfn ) + /* This pfn is higher than the highest the p2m map currently holds */ + return _mfn(INVALID_MFN); + +#if CONFIG_PAGING_LEVELS >= 4 + { + l4_pgentry_t *l4e = map_domain_page(mfn_x(mfn)); + l4e += l4_table_offset(addr); + if ( (l4e_get_flags(*l4e) & _PAGE_PRESENT) == 0 ) + { + unmap_domain_page(l4e); + return _mfn(INVALID_MFN); + } + mfn = _mfn(l4e_get_pfn(*l4e)); + unmap_domain_page(l4e); + } +#endif +#if CONFIG_PAGING_LEVELS >= 3 + { + l3_pgentry_t *l3e = map_domain_page(mfn_x(mfn)); +#if CONFIG_PAGING_LEVELS == 3 + /* On PAE hosts the p2m has eight l3 entries, not four (see + * shadow_set_p2m_entry()) so we can't use l3_table_offset. + * Instead, just count the number of l3es from zero. It's safe + * to do this because we already checked that the gfn is within + * the bounds of the p2m. */ + l3e += (addr >> L3_PAGETABLE_SHIFT); +#else + l3e += l3_table_offset(addr); +#endif + if ( (l3e_get_flags(*l3e) & _PAGE_PRESENT) == 0 ) + { + unmap_domain_page(l3e); + return _mfn(INVALID_MFN); + } + mfn = _mfn(l3e_get_pfn(*l3e)); + unmap_domain_page(l3e); + } +#endif + + l2e = map_domain_page(mfn_x(mfn)); + l2e += l2_table_offset(addr); + if ( (l2e_get_flags(*l2e) & _PAGE_PRESENT) == 0 ) + { + unmap_domain_page(l2e); + return _mfn(INVALID_MFN); + } + mfn = _mfn(l2e_get_pfn(*l2e)); + unmap_domain_page(l2e); + + l1e = map_domain_page(mfn_x(mfn)); + l1e += l1_table_offset(addr); + if ( (l1e_get_flags(*l1e) & _PAGE_PRESENT) == 0 ) + { + unmap_domain_page(l1e); + return _mfn(INVALID_MFN); + } + mfn = _mfn(l1e_get_pfn(*l1e)); + unmap_domain_page(l1e); + + return mfn; +} + +#if P2M_AUDIT +static void audit_p2m(struct domain *d) +{ + struct list_head *entry; + struct page_info *page; + struct domain *od; + unsigned long mfn, gfn, m2pfn, lp2mfn = 0; + mfn_t p2mfn; + unsigned long orphans_d = 0, orphans_i = 0, mpbad = 0, pmbad = 0; + int test_linear; + + if ( !paging_mode_translate(d) ) + return; + + //P2M_PRINTK("p2m audit starts\n"); + + test_linear = ( (d == current->domain) + && !pagetable_is_null(current->arch.monitor_table) ); + if ( test_linear ) + local_flush_tlb(); + + /* Audit part one: walk the domain's page allocation list, checking + * the m2p entries. */ + for ( entry = d->page_list.next; + entry != &d->page_list; + entry = entry->next ) + { + page = list_entry(entry, struct page_info, list); + mfn = mfn_x(page_to_mfn(page)); + + // P2M_PRINTK("auditing guest page, mfn=%#lx\n", mfn); + + od = page_get_owner(page); + + if ( od != d ) + { + P2M_PRINTK("wrong owner %#lx -> %p(%u) != %p(%u)\n", + mfn, od, (od?od->domain_id:-1), d, d->domain_id); + continue; + } + + gfn = get_gpfn_from_mfn(mfn); + if ( gfn == INVALID_M2P_ENTRY ) + { + orphans_i++; + //P2M_PRINTK("orphaned guest page: mfn=%#lx has invalid gfn\n", + // mfn); + continue; + } + + if ( gfn == 0x55555555 ) + { + orphans_d++; + //P2M_PRINTK("orphaned guest page: mfn=%#lx has debug gfn\n", + // mfn); + continue; + } + + p2mfn = gfn_to_mfn_foreign(d, gfn); + if ( mfn_x(p2mfn) != mfn ) + { + mpbad++; + P2M_PRINTK("map mismatch mfn %#lx -> gfn %#lx -> mfn %#lx" + " (-> gfn %#lx)\n", + mfn, gfn, mfn_x(p2mfn), + (mfn_valid(p2mfn) + ? get_gpfn_from_mfn(mfn_x(p2mfn)) + : -1u)); + /* This m2p entry is stale: the domain has another frame in + * this physical slot. No great disaster, but for neatness, + * blow away the m2p entry. */ + set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY); + } + + if ( test_linear && (gfn <= d->arch.p2m.max_mapped_pfn) ) + { + lp2mfn = mfn_x(gfn_to_mfn_current(gfn)); + if ( lp2mfn != mfn_x(p2mfn) ) + { + P2M_PRINTK("linear mismatch gfn %#lx -> mfn %#lx " + "(!= mfn %#lx)\n", gfn, lp2mfn, mfn_x(p2mfn)); + } + } + + // P2M_PRINTK("OK: mfn=%#lx, gfn=%#lx, p2mfn=%#lx, lp2mfn=%#lx\n", + // mfn, gfn, p2mfn, lp2mfn); + } + + /* Audit part two: walk the domain's p2m table, checking the entries. */ + if ( pagetable_get_pfn(d->arch.phys_table) != 0 ) + { + l2_pgentry_t *l2e; + l1_pgentry_t *l1e; + int i1, i2; + +#if CONFIG_PAGING_LEVELS == 4 + l4_pgentry_t *l4e; + l3_pgentry_t *l3e; + int i3, i4; + l4e = map_domain_page(mfn_x(pagetable_get_mfn(d->arch.phys_table))); +#elif CONFIG_PAGING_LEVELS == 3 + l3_pgentry_t *l3e; + int i3; + l3e = map_domain_page(mfn_x(pagetable_get_mfn(d->arch.phys_table))); +#else /* CONFIG_PAGING_LEVELS == 2 */ + l2e = map_domain_page(mfn_x(pagetable_get_mfn(d->arch.phys_table))); +#endif + + gfn = 0; +#if CONFIG_PAGING_LEVELS >= 3 +#if CONFIG_PAGING_LEVELS >= 4 + for ( i4 = 0; i4 < L4_PAGETABLE_ENTRIES; i4++ ) + { + if ( !(l4e_get_flags(l4e[i4]) & _PAGE_PRESENT) ) + { + gfn += 1 << (L4_PAGETABLE_SHIFT - PAGE_SHIFT); + continue; + } + l3e = map_domain_page(mfn_x(_mfn(l4e_get_pfn(l4e[i4])))); +#endif /* now at levels 3 or 4... */ + for ( i3 = 0; + i3 < ((CONFIG_PAGING_LEVELS==4) ? L3_PAGETABLE_ENTRIES : 8); + i3++ ) + { + if ( !(l3e_get_flags(l3e[i3]) & _PAGE_PRESENT) ) + { + gfn += 1 << (L3_PAGETABLE_SHIFT - PAGE_SHIFT); + continue; + } + l2e = map_domain_page(mfn_x(_mfn(l3e_get_pfn(l3e[i3])))); +#endif /* all levels... */ + for ( i2 = 0; i2 < L2_PAGETABLE_ENTRIES; i2++ ) + { + if ( !(l2e_get_flags(l2e[i2]) & _PAGE_PRESENT) ) + { + gfn += 1 << (L2_PAGETABLE_SHIFT - PAGE_SHIFT); + continue; + } + l1e = map_domain_page(mfn_x(_mfn(l2e_get_pfn(l2e[i2])))); + + for ( i1 = 0; i1 < L1_PAGETABLE_ENTRIES; i1++, gfn++ ) + { + if ( !(l1e_get_flags(l1e[i1]) & _PAGE_PRESENT) ) + continue; + mfn = l1e_get_pfn(l1e[i1]); + ASSERT(mfn_valid(_mfn(mfn))); + m2pfn = get_gpfn_from_mfn(mfn); + if ( m2pfn != gfn ) + { + pmbad++; + P2M_PRINTK("mismatch: gfn %#lx -> mfn %#lx" + " -> gfn %#lx\n", gfn, mfn, m2pfn); + BUG(); + } + } + unmap_domain_page(l1e); + } +#if CONFIG_PAGING_LEVELS >= 3 + unmap_domain_page(l2e); + } +#if CONFIG_PAGING_LEVELS >= 4 + unmap_domain_page(l3e); + } +#endif +#endif + +#if CONFIG_PAGING_LEVELS == 4 + unmap_domain_page(l4e); +#elif CONFIG_PAGING_LEVELS == 3 + unmap_domain_page(l3e); +#else /* CONFIG_PAGING_LEVELS == 2 */ + unmap_domain_page(l2e); +#endif + + } + + //P2M_PRINTK("p2m audit complete\n"); + //if ( orphans_i | orphans_d | mpbad | pmbad ) + // P2M_PRINTK("p2m audit found %lu orphans (%lu inval %lu debug)\n", + // orphans_i + orphans_d, orphans_i, orphans_d, + if ( mpbad | pmbad ) + P2M_PRINTK("p2m audit found %lu odd p2m, %lu bad m2p entries\n", + pmbad, mpbad); +} +#else +#define audit_p2m(_d) do { (void)(_d); } while(0) +#endif /* P2M_AUDIT */ + + + +static void +p2m_remove_page(struct domain *d, unsigned long gfn, unsigned long mfn) +{ + if ( !paging_mode_translate(d) ) + return; + P2M_DEBUG("removing gfn=%#lx mfn=%#lx\n", gfn, mfn); + + ASSERT(mfn_x(gfn_to_mfn(d, gfn)) == mfn); + //ASSERT(mfn_to_gfn(d, mfn) == gfn); + + set_p2m_entry(d, gfn, _mfn(INVALID_MFN)); + set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY); +} + +void +guest_physmap_remove_page(struct domain *d, unsigned long gfn, + unsigned long mfn) +{ + p2m_lock(d); + audit_p2m(d); + p2m_remove_page(d, gfn, mfn); + audit_p2m(d); + p2m_unlock(d); +} + +void +guest_physmap_add_page(struct domain *d, unsigned long gfn, + unsigned long mfn) +{ + unsigned long ogfn; + mfn_t omfn; + + if ( !paging_mode_translate(d) ) + return; + + p2m_lock(d); + audit_p2m(d); + + P2M_DEBUG("adding gfn=%#lx mfn=%#lx\n", gfn, mfn); + + omfn = gfn_to_mfn(d, gfn); + if ( mfn_valid(omfn) ) + { + set_p2m_entry(d, gfn, _mfn(INVALID_MFN)); + set_gpfn_from_mfn(mfn_x(omfn), INVALID_M2P_ENTRY); + } + + ogfn = mfn_to_gfn(d, _mfn(mfn)); + if ( +#ifdef __x86_64__ + (ogfn != 0x5555555555555555L) +#else + (ogfn != 0x55555555L) +#endif + && (ogfn != INVALID_M2P_ENTRY) + && (ogfn != gfn) ) + { + /* This machine frame is already mapped at another physical address */ + P2M_DEBUG("aliased! mfn=%#lx, old gfn=%#lx, new gfn=%#lx\n", + mfn, ogfn, gfn); + if ( mfn_valid(omfn = gfn_to_mfn(d, ogfn)) ) + { + P2M_DEBUG("old gfn=%#lx -> mfn %#lx\n", + ogfn , mfn_x(omfn)); + if ( mfn_x(omfn) == mfn ) + p2m_remove_page(d, ogfn, mfn); + } + } + + set_p2m_entry(d, gfn, _mfn(mfn)); + set_gpfn_from_mfn(mfn, gfn); + + audit_p2m(d); + p2m_unlock(d); +} + + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/arch/x86/mm/paging.c b/xen/arch/x86/mm/paging.c new file mode 100644 index 0000000000..4605dd5e24 --- /dev/null +++ b/xen/arch/x86/mm/paging.c @@ -0,0 +1,143 @@ +/****************************************************************************** + * arch/x86/paging.c + * + * x86 specific paging support + * Copyright (c) 2007 Advanced Micro Devices (Wei Huang) + * Copyright (c) 2007 XenSource Inc. + * + * 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +/* Xen command-line option to enable hardware-assisted paging */ +int opt_hap_enabled = 0; +boolean_param("hap", opt_hap_enabled); + +/* Printouts */ +#define PAGING_PRINTK(_f, _a...) \ + debugtrace_printk("pg: %s(): " _f, __func__, ##_a) +#define PAGING_ERROR(_f, _a...) \ + printk("pg error: %s(): " _f, __func__, ##_a) +#define PAGING_DEBUG(flag, _f, _a...) \ + do { \ + if (PAGING_DEBUG_ ## flag) \ + debugtrace_printk("pgdebug: %s(): " _f, __func__, ##_a); \ + } while (0) + + +/* Domain paging struct initialization. */ +void paging_domain_init(struct domain *d) +{ + p2m_init(d); + shadow_domain_init(d); +} + +/* vcpu paging struct initialization goes here */ +void paging_vcpu_init(struct vcpu *v) +{ + shadow_vcpu_init(v); +} + + +int paging_domctl(struct domain *d, xen_domctl_shadow_op_t *sc, + XEN_GUEST_HANDLE(void) u_domctl) +{ + /* Here, dispatch domctl to the appropriate paging code */ + return shadow_domctl(d, sc, u_domctl); +} + +/* Call when destroying a domain */ +void paging_teardown(struct domain *d) +{ + shadow_teardown(d); + /* Call other modes' teardown code here */ +} + +/* Call once all of the references to the domain have gone away */ +void paging_final_teardown(struct domain *d) +{ + shadow_teardown(d); + /* Call other modes' final teardown code here */ +} + +/* Enable an arbitrary paging-assistance mode. Call once at domain + * creation. */ +int paging_enable(struct domain *d, u32 mode) +{ + if ( mode & PG_SH_enable ) + return shadow_enable(d, mode); + else + /* No other modes supported yet */ + return -EINVAL; +} + +/* Print paging-assistance info to the console */ +void paging_dump_domain_info(struct domain *d) +{ + if ( paging_mode_enabled(d) ) + { + printk(" paging assistance: "); + if ( paging_mode_shadow(d) ) + printk("shadow "); + if ( paging_mode_hap(d) ) + printk("hap "); + if ( paging_mode_refcounts(d) ) + printk("refcounts "); + if ( paging_mode_log_dirty(d) ) + printk("log_dirty "); + if ( paging_mode_translate(d) ) + printk("translate "); + if ( paging_mode_external(d) ) + printk("external "); + printk("\n"); + } +} + +void paging_dump_vcpu_info(struct vcpu *v) +{ + if ( paging_mode_enabled(v->domain) ) + { + printk(" paging assistance: "); + if ( paging_mode_shadow(v->domain) ) + { + if ( v->arch.paging.mode ) + printk("shadowed %u-on-%u, %stranslated\n", + v->arch.paging.mode->guest_levels, + v->arch.paging.mode->shadow.shadow_levels, + paging_vcpu_mode_translate(v) ? "" : "not "); + else + printk("not shadowed\n"); + } + else if ( paging_mode_hap(v->domain) && v->arch.paging.mode ) + printk("hap, %u levels\n", + v->arch.paging.mode->guest_levels); + else + printk("none\n"); + } +} + + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c index b00f9d6b25..ff229fa7c5 100644 --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -47,12 +47,27 @@ void shadow_domain_init(struct domain *d) int i; shadow_lock_init(d); for ( i = 0; i <= SHADOW_MAX_ORDER; i++ ) - INIT_LIST_HEAD(&d->arch.shadow.freelists[i]); - INIT_LIST_HEAD(&d->arch.shadow.p2m_freelist); - INIT_LIST_HEAD(&d->arch.shadow.p2m_inuse); - INIT_LIST_HEAD(&d->arch.shadow.pinned_shadows); + INIT_LIST_HEAD(&d->arch.paging.shadow.freelists[i]); + INIT_LIST_HEAD(&d->arch.paging.shadow.p2m_freelist); + INIT_LIST_HEAD(&d->arch.paging.shadow.pinned_shadows); } +/* Setup the shadow-specfic parts of a vcpu struct. Note: The most important + * job is to initialize the update_paging_modes() function pointer, which is + * used to initialized the rest of resources. Therefore, it really does not + * matter to have v->arch.paging.mode pointing to any mode, as long as it can + * be compiled. + */ +void shadow_vcpu_init(struct vcpu *v) +{ +#if CONFIG_PAGING_LEVELS == 4 + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,3,3); +#elif CONFIG_PAGING_LEVELS == 3 + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,3,3); +#elif CONFIG_PAGING_LEVELS == 2 + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,2,2); +#endif +} #if SHADOW_AUDIT int shadow_audit_enable = 0; @@ -265,7 +280,7 @@ hvm_emulate_write(enum x86_segment seg, if ( rc ) return rc; - return v->arch.shadow.mode->x86_emulate_write( + return v->arch.paging.mode->shadow.x86_emulate_write( v, addr, &val, bytes, sh_ctxt); } @@ -288,7 +303,7 @@ hvm_emulate_cmpxchg(enum x86_segment seg, if ( rc ) return rc; - return v->arch.shadow.mode->x86_emulate_cmpxchg( + return v->arch.paging.mode->shadow.x86_emulate_cmpxchg( v, addr, old, new, bytes, sh_ctxt); } @@ -312,7 +327,7 @@ hvm_emulate_cmpxchg8b(enum x86_segment seg, if ( rc ) return rc; - return v->arch.shadow.mode->x86_emulate_cmpxchg8b( + return v->arch.paging.mode->shadow.x86_emulate_cmpxchg8b( v, addr, old_lo, old_hi, new_lo, new_hi, sh_ctxt); } @@ -353,7 +368,7 @@ pv_emulate_write(enum x86_segment seg, struct sh_emulate_ctxt *sh_ctxt = container_of(ctxt, struct sh_emulate_ctxt, ctxt); struct vcpu *v = current; - return v->arch.shadow.mode->x86_emulate_write( + return v->arch.paging.mode->shadow.x86_emulate_write( v, offset, &val, bytes, sh_ctxt); } @@ -368,7 +383,7 @@ pv_emulate_cmpxchg(enum x86_segment seg, struct sh_emulate_ctxt *sh_ctxt = container_of(ctxt, struct sh_emulate_ctxt, ctxt); struct vcpu *v = current; - return v->arch.shadow.mode->x86_emulate_cmpxchg( + return v->arch.paging.mode->shadow.x86_emulate_cmpxchg( v, offset, old, new, bytes, sh_ctxt); } @@ -384,7 +399,7 @@ pv_emulate_cmpxchg8b(enum x86_segment seg, struct sh_emulate_ctxt *sh_ctxt = container_of(ctxt, struct sh_emulate_ctxt, ctxt); struct vcpu *v = current; - return v->arch.shadow.mode->x86_emulate_cmpxchg8b( + return v->arch.paging.mode->shadow.x86_emulate_cmpxchg8b( v, offset, old_lo, old_hi, new_lo, new_hi, sh_ctxt); } @@ -721,7 +736,7 @@ static inline int chunk_is_available(struct domain *d, int order) int i; for ( i = order; i <= SHADOW_MAX_ORDER; i++ ) - if ( !list_empty(&d->arch.shadow.freelists[i]) ) + if ( !list_empty(&d->arch.paging.shadow.freelists[i]) ) return 1; return 0; } @@ -783,7 +798,7 @@ void shadow_prealloc(struct domain *d, unsigned int order) /* Stage one: walk the list of pinned pages, unpinning them */ perfc_incrc(shadow_prealloc_1); - list_for_each_backwards_safe(l, t, &d->arch.shadow.pinned_shadows) + list_for_each_backwards_safe(l, t, &d->arch.paging.shadow.pinned_shadows) { sp = list_entry(l, struct shadow_page_info, list); smfn = shadow_page_to_mfn(sp); @@ -823,9 +838,9 @@ void shadow_prealloc(struct domain *d, unsigned int order) SHADOW_PRINTK("Can't pre-allocate %i shadow pages!\n" " shadow pages total = %u, free = %u, p2m=%u\n", 1 << order, - d->arch.shadow.total_pages, - d->arch.shadow.free_pages, - d->arch.shadow.p2m_pages); + d->arch.paging.shadow.total_pages, + d->arch.paging.shadow.free_pages, + d->arch.paging.shadow.p2m_pages); BUG(); } @@ -840,7 +855,7 @@ static void shadow_blow_tables(struct domain *d) int i; /* Pass one: unpin all pinned pages */ - list_for_each_backwards_safe(l,t, &d->arch.shadow.pinned_shadows) + list_for_each_backwards_safe(l,t, &d->arch.paging.shadow.pinned_shadows) { sp = list_entry(l, struct shadow_page_info, list); smfn = shadow_page_to_mfn(sp); @@ -905,9 +920,9 @@ mfn_t shadow_alloc(struct domain *d, /* Find smallest order which can satisfy the request. */ for ( i = order; i <= SHADOW_MAX_ORDER; i++ ) - if ( !list_empty(&d->arch.shadow.freelists[i]) ) + if ( !list_empty(&d->arch.paging.shadow.freelists[i]) ) { - sp = list_entry(d->arch.shadow.freelists[i].next, + sp = list_entry(d->arch.paging.shadow.freelists[i].next, struct shadow_page_info, list); list_del(&sp->list); @@ -916,10 +931,10 @@ mfn_t shadow_alloc(struct domain *d, { i--; sp->order = i; - list_add_tail(&sp->list, &d->arch.shadow.freelists[i]); + list_add_tail(&sp->list, &d->arch.paging.shadow.freelists[i]); sp += 1 << i; } - d->arch.shadow.free_pages -= 1 << order; + d->arch.paging.shadow.free_pages -= 1 << order; /* Init page info fields and clear the pages */ for ( i = 0; i < 1<arch.shadow.free_pages += 1 << order; + d->arch.paging.shadow.free_pages += 1 << order; for ( i = 0; i < 1<arch.shadow.last_writeable_pte_smfn == mfn_x(smfn) + i ) - v->arch.shadow.last_writeable_pte_smfn = 0; + if ( v->arch.paging.shadow.last_writeable_pte_smfn == mfn_x(smfn) + i ) + v->arch.paging.shadow.last_writeable_pte_smfn = 0; } #endif /* Strip out the type: this is now a free shadow page */ @@ -1019,7 +1034,7 @@ void shadow_free(struct domain *d, mfn_t smfn) } sp->order = order; - list_add_tail(&sp->list, &d->arch.shadow.freelists[order]); + list_add_tail(&sp->list, &d->arch.paging.shadow.freelists[order]); } /* Divert some memory from the pool to be used by the p2m mapping. @@ -1033,19 +1048,19 @@ void shadow_free(struct domain *d, mfn_t smfn) * returns non-zero on success. */ static int -shadow_alloc_p2m_pages(struct domain *d) +sh_alloc_p2m_pages(struct domain *d) { struct page_info *pg; u32 i; ASSERT(shadow_locked_by_me(d)); - if ( d->arch.shadow.total_pages + if ( d->arch.paging.shadow.total_pages < (shadow_min_acceptable_pages(d) + (1<arch.shadow.p2m_pages += (1<arch.shadow.total_pages -= (1<arch.paging.shadow.p2m_pages += (1<arch.paging.shadow.total_pages -= (1<arch.shadow.p2m_freelist); + pg->count_info = 1; + list_add_tail(&pg[i].list, &d->arch.paging.shadow.p2m_freelist); } return 1; } // Returns 0 if no memory is available... -mfn_t +struct page_info * shadow_alloc_p2m_page(struct domain *d) { struct list_head *entry; struct page_info *pg; mfn_t mfn; void *p; + + shadow_lock(d); - if ( list_empty(&d->arch.shadow.p2m_freelist) && - !shadow_alloc_p2m_pages(d) ) - return _mfn(0); - entry = d->arch.shadow.p2m_freelist.next; + if ( list_empty(&d->arch.paging.shadow.p2m_freelist) && + !sh_alloc_p2m_pages(d) ) + { + shadow_unlock(d); + return NULL; + } + entry = d->arch.paging.shadow.p2m_freelist.next; list_del(entry); - list_add_tail(entry, &d->arch.shadow.p2m_inuse); + + shadow_unlock(d); + pg = list_entry(entry, struct page_info, list); - pg->count_info = 1; mfn = page_to_mfn(pg); p = sh_map_domain_page(mfn); clear_page(p); sh_unmap_domain_page(p); - return mfn; + return pg; +} + +void +shadow_free_p2m_page(struct domain *d, struct page_info *pg) +{ + ASSERT(page_get_owner(pg) == d); + /* Should have just the one ref we gave it in alloc_p2m_page() */ + if ( (pg->count_info & PGC_count_mask) != 1 ) + { + SHADOW_ERROR("Odd p2m page count c=%#x t=%"PRtype_info"\n", + pg->count_info, pg->u.inuse.type_info); + } + /* Free should not decrement domain's total allocation, since + * these pages were allocated without an owner. */ + page_set_owner(pg, NULL); + free_domheap_pages(pg, 0); + d->arch.paging.shadow.p2m_pages--; + perfc_decr(shadow_alloc_count); } #if CONFIG_PAGING_LEVELS == 3 @@ -1130,344 +1170,6 @@ static void p2m_install_entry_in_monitors(struct domain *d, } #endif -// Find the next level's P2M entry, checking for out-of-range gfn's... -// Returns NULL on error. -// -static l1_pgentry_t * -p2m_find_entry(void *table, unsigned long *gfn_remainder, - unsigned long gfn, u32 shift, u32 max) -{ - u32 index; - - index = *gfn_remainder >> shift; - if ( index >= max ) - { - SHADOW_DEBUG(P2M, "gfn=0x%lx out of range " - "(gfn_remainder=0x%lx shift=%d index=0x%x max=0x%x)\n", - gfn, *gfn_remainder, shift, index, max); - return NULL; - } - *gfn_remainder &= (1 << shift) - 1; - return (l1_pgentry_t *)table + index; -} - -// Walk one level of the P2M table, allocating a new table if required. -// Returns 0 on error. -// -static int -p2m_next_level(struct domain *d, mfn_t *table_mfn, void **table, - unsigned long *gfn_remainder, unsigned long gfn, u32 shift, - u32 max, unsigned long type) -{ - l1_pgentry_t *p2m_entry; - void *next; - - if ( !(p2m_entry = p2m_find_entry(*table, gfn_remainder, gfn, - shift, max)) ) - return 0; - - if ( !(l1e_get_flags(*p2m_entry) & _PAGE_PRESENT) ) - { - mfn_t mfn = shadow_alloc_p2m_page(d); - if ( mfn_x(mfn) == 0 ) - return 0; - *p2m_entry = l1e_from_pfn(mfn_x(mfn), __PAGE_HYPERVISOR|_PAGE_USER); - mfn_to_page(mfn)->u.inuse.type_info = type | 1 | PGT_validated; - mfn_to_page(mfn)->count_info = 1; -#if CONFIG_PAGING_LEVELS == 3 - if (type == PGT_l2_page_table) - { - struct vcpu *v; - /* We have written to the p2m l3: need to sync the per-vcpu - * copies of it in the monitor tables */ - p2m_install_entry_in_monitors(d, (l3_pgentry_t *)p2m_entry); - /* Also, any vcpus running on shadows of the p2m need to - * reload their CR3s so the change propagates to the shadow */ - ASSERT(shadow_locked_by_me(d)); - for_each_vcpu(d, v) - { - if ( pagetable_get_pfn(v->arch.guest_table) - == pagetable_get_pfn(d->arch.phys_table) - && v->arch.shadow.mode != NULL ) - v->arch.shadow.mode->update_cr3(v, 0); - } - } -#endif - /* The P2M can be shadowed: keep the shadows synced */ - if ( d->vcpu[0] != NULL ) - (void)sh_validate_guest_entry(d->vcpu[0], *table_mfn, - p2m_entry, sizeof *p2m_entry); - } - *table_mfn = _mfn(l1e_get_pfn(*p2m_entry)); - next = sh_map_domain_page(*table_mfn); - sh_unmap_domain_page(*table); - *table = next; - - return 1; -} - -// Returns 0 on error (out of memory) -int -shadow_set_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn) -{ - // XXX -- this might be able to be faster iff current->domain == d - mfn_t table_mfn = pagetable_get_mfn(d->arch.phys_table); - void *table = sh_map_domain_page(table_mfn); - unsigned long gfn_remainder = gfn; - l1_pgentry_t *p2m_entry; - int rv=0; - -#if CONFIG_PAGING_LEVELS >= 4 - if ( !p2m_next_level(d, &table_mfn, &table, &gfn_remainder, gfn, - L4_PAGETABLE_SHIFT - PAGE_SHIFT, - L4_PAGETABLE_ENTRIES, PGT_l3_page_table) ) - goto out; -#endif -#if CONFIG_PAGING_LEVELS >= 3 - // When using PAE Xen, we only allow 33 bits of pseudo-physical - // address in translated guests (i.e. 8 GBytes). This restriction - // comes from wanting to map the P2M table into the 16MB RO_MPT hole - // in Xen's address space for translated PV guests. - // - if ( !p2m_next_level(d, &table_mfn, &table, &gfn_remainder, gfn, - L3_PAGETABLE_SHIFT - PAGE_SHIFT, - (CONFIG_PAGING_LEVELS == 3 - ? 8 - : L3_PAGETABLE_ENTRIES), - PGT_l2_page_table) ) - goto out; -#endif - if ( !p2m_next_level(d, &table_mfn, &table, &gfn_remainder, gfn, - L2_PAGETABLE_SHIFT - PAGE_SHIFT, - L2_PAGETABLE_ENTRIES, PGT_l1_page_table) ) - goto out; - - p2m_entry = p2m_find_entry(table, &gfn_remainder, gfn, - 0, L1_PAGETABLE_ENTRIES); - ASSERT(p2m_entry); - if ( mfn_valid(mfn) ) - *p2m_entry = l1e_from_pfn(mfn_x(mfn), __PAGE_HYPERVISOR|_PAGE_USER); - else - *p2m_entry = l1e_empty(); - - /* Track the highest gfn for which we have ever had a valid mapping */ - if ( mfn_valid(mfn) && (gfn > d->arch.max_mapped_pfn) ) - d->arch.max_mapped_pfn = gfn; - - /* The P2M can be shadowed: keep the shadows synced */ - if ( d->vcpu[0] != NULL ) - (void)sh_validate_guest_entry(d->vcpu[0], table_mfn, - p2m_entry, sizeof(*p2m_entry)); - - /* Success */ - rv = 1; - - out: - sh_unmap_domain_page(table); - return rv; -} - -// Allocate a new p2m table for a domain. -// -// The structure of the p2m table is that of a pagetable for xen (i.e. it is -// controlled by CONFIG_PAGING_LEVELS). -// -// Returns 0 if p2m table could not be initialized -// -static int -shadow_alloc_p2m_table(struct domain *d) -{ - mfn_t p2m_top, mfn; - struct list_head *entry; - struct page_info *page; - unsigned int page_count = 0; - unsigned long gfn; - - SHADOW_PRINTK("allocating p2m table\n"); - ASSERT(pagetable_get_pfn(d->arch.phys_table) == 0); - - p2m_top = shadow_alloc_p2m_page(d); - mfn_to_page(p2m_top)->count_info = 1; - mfn_to_page(p2m_top)->u.inuse.type_info = -#if CONFIG_PAGING_LEVELS == 4 - PGT_l4_page_table -#elif CONFIG_PAGING_LEVELS == 3 - PGT_l3_page_table -#elif CONFIG_PAGING_LEVELS == 2 - PGT_l2_page_table -#endif - | 1 | PGT_validated; - - if ( mfn_x(p2m_top) == 0 ) - return 0; - - d->arch.phys_table = pagetable_from_mfn(p2m_top); - - SHADOW_PRINTK("populating p2m table\n"); - - /* Initialise physmap tables for slot zero. Other code assumes this. */ - gfn = 0; - mfn = _mfn(INVALID_MFN); - if ( !shadow_set_p2m_entry(d, gfn, mfn) ) - goto error; - - /* Build a p2m map that matches the m2p entries for this domain's - * allocated pages. Skip any pages that have an explicitly invalid - * or obviously bogus m2p entry. */ - for ( entry = d->page_list.next; - entry != &d->page_list; - entry = entry->next ) - { - page = list_entry(entry, struct page_info, list); - mfn = page_to_mfn(page); - gfn = get_gpfn_from_mfn(mfn_x(mfn)); - page_count++; - if ( -#ifdef __x86_64__ - (gfn != 0x5555555555555555L) -#else - (gfn != 0x55555555L) -#endif - && gfn != INVALID_M2P_ENTRY - && (gfn < - (RO_MPT_VIRT_END - RO_MPT_VIRT_START) / sizeof (l1_pgentry_t)) - && !shadow_set_p2m_entry(d, gfn, mfn) ) - goto error; - } - - SHADOW_PRINTK("p2m table initialised (%u pages)\n", page_count); - return 1; - - error: - SHADOW_PRINTK("failed to initialize p2m table, gfn=%05lx, mfn=%" - SH_PRI_mfn "\n", gfn, mfn_x(mfn)); - return 0; -} - -mfn_t -sh_gfn_to_mfn_foreign(struct domain *d, unsigned long gpfn) -/* Read another domain's p2m entries */ -{ - mfn_t mfn; - paddr_t addr = ((paddr_t)gpfn) << PAGE_SHIFT; - l2_pgentry_t *l2e; - l1_pgentry_t *l1e; - - ASSERT(shadow_mode_translate(d)); - mfn = pagetable_get_mfn(d->arch.phys_table); - - - if ( gpfn > d->arch.max_mapped_pfn ) - /* This pfn is higher than the highest the p2m map currently holds */ - return _mfn(INVALID_MFN); - -#if CONFIG_PAGING_LEVELS >= 4 - { - l4_pgentry_t *l4e = sh_map_domain_page(mfn); - l4e += l4_table_offset(addr); - if ( (l4e_get_flags(*l4e) & _PAGE_PRESENT) == 0 ) - { - sh_unmap_domain_page(l4e); - return _mfn(INVALID_MFN); - } - mfn = _mfn(l4e_get_pfn(*l4e)); - sh_unmap_domain_page(l4e); - } -#endif -#if CONFIG_PAGING_LEVELS >= 3 - { - l3_pgentry_t *l3e = sh_map_domain_page(mfn); -#if CONFIG_PAGING_LEVELS == 3 - /* On PAE hosts the p2m has eight l3 entries, not four (see - * shadow_set_p2m_entry()) so we can't use l3_table_offset. - * Instead, just count the number of l3es from zero. It's safe - * to do this because we already checked that the gfn is within - * the bounds of the p2m. */ - l3e += (addr >> L3_PAGETABLE_SHIFT); -#else - l3e += l3_table_offset(addr); -#endif - if ( (l3e_get_flags(*l3e) & _PAGE_PRESENT) == 0 ) - { - sh_unmap_domain_page(l3e); - return _mfn(INVALID_MFN); - } - mfn = _mfn(l3e_get_pfn(*l3e)); - sh_unmap_domain_page(l3e); - } -#endif - - l2e = sh_map_domain_page(mfn); - l2e += l2_table_offset(addr); - if ( (l2e_get_flags(*l2e) & _PAGE_PRESENT) == 0 ) - { - sh_unmap_domain_page(l2e); - return _mfn(INVALID_MFN); - } - mfn = _mfn(l2e_get_pfn(*l2e)); - sh_unmap_domain_page(l2e); - - l1e = sh_map_domain_page(mfn); - l1e += l1_table_offset(addr); - if ( (l1e_get_flags(*l1e) & _PAGE_PRESENT) == 0 ) - { - sh_unmap_domain_page(l1e); - return _mfn(INVALID_MFN); - } - mfn = _mfn(l1e_get_pfn(*l1e)); - sh_unmap_domain_page(l1e); - - return mfn; -} - -unsigned long -shadow_gfn_to_mfn_foreign(unsigned long gpfn) -{ - return mfn_x(sh_gfn_to_mfn_foreign(current->domain, gpfn)); -} - - -static void shadow_p2m_teardown(struct domain *d) -/* Return all the p2m pages to Xen. - * We know we don't have any extra mappings to these pages */ -{ - struct list_head *entry, *n; - struct page_info *pg; - - d->arch.phys_table = pagetable_null(); - - list_for_each_safe(entry, n, &d->arch.shadow.p2m_inuse) - { - pg = list_entry(entry, struct page_info, list); - list_del(entry); - /* Should have just the one ref we gave it in alloc_p2m_page() */ - if ( (pg->count_info & PGC_count_mask) != 1 ) - { - SHADOW_PRINTK("Odd p2m page count c=%#x t=%"PRtype_info"\n", - pg->count_info, pg->u.inuse.type_info); - } - ASSERT(page_get_owner(pg) == d); - /* Free should not decrement domain's total allocation, since - * these pages were allocated without an owner. */ - page_set_owner(pg, NULL); - free_domheap_pages(pg, 0); - d->arch.shadow.p2m_pages--; - perfc_decr(shadow_alloc_count); - } - list_for_each_safe(entry, n, &d->arch.shadow.p2m_freelist) - { - list_del(entry); - pg = list_entry(entry, struct page_info, list); - ASSERT(page_get_owner(pg) == d); - /* Free should not decrement domain's total allocation. */ - page_set_owner(pg, NULL); - free_domheap_pages(pg, 0); - d->arch.shadow.p2m_pages--; - perfc_decr(shadow_alloc_count); - } - ASSERT(d->arch.shadow.p2m_pages == 0); -} - /* Set the pool of shadow pages to the required number of pages. * Input will be rounded up to at least shadow_min_acceptable_pages(), * plus space for the p2m table. @@ -1491,11 +1193,11 @@ static unsigned int sh_set_allocation(struct domain *d, pages = (pages + ((1<arch.shadow.total_pages, pages); + d->arch.paging.shadow.total_pages, pages); - while ( d->arch.shadow.total_pages != pages ) + while ( d->arch.paging.shadow.total_pages != pages ) { - if ( d->arch.shadow.total_pages < pages ) + if ( d->arch.paging.shadow.total_pages < pages ) { /* Need to allocate more memory from domheap */ sp = (struct shadow_page_info *) @@ -1505,8 +1207,8 @@ static unsigned int sh_set_allocation(struct domain *d, SHADOW_PRINTK("failed to allocate shadow pages.\n"); return -ENOMEM; } - d->arch.shadow.free_pages += 1<arch.shadow.total_pages += 1<arch.paging.shadow.free_pages += 1<arch.paging.shadow.total_pages += 1<order = SHADOW_MAX_ORDER; list_add_tail(&sp->list, - &d->arch.shadow.freelists[SHADOW_MAX_ORDER]); + &d->arch.paging.shadow.freelists[SHADOW_MAX_ORDER]); } - else if ( d->arch.shadow.total_pages > pages ) + else if ( d->arch.paging.shadow.total_pages > pages ) { /* Need to return memory to domheap */ shadow_prealloc(d, SHADOW_MAX_ORDER); - ASSERT(!list_empty(&d->arch.shadow.freelists[SHADOW_MAX_ORDER])); - sp = list_entry(d->arch.shadow.freelists[SHADOW_MAX_ORDER].next, + ASSERT(!list_empty(&d->arch.paging.shadow.freelists[SHADOW_MAX_ORDER])); + sp = list_entry(d->arch.paging.shadow.freelists[SHADOW_MAX_ORDER].next, struct shadow_page_info, list); list_del(&sp->list); - d->arch.shadow.free_pages -= 1<arch.shadow.total_pages -= 1<arch.paging.shadow.free_pages -= 1<arch.paging.shadow.total_pages -= 1<arch.shadow.total_pages; + unsigned int pg = d->arch.paging.shadow.total_pages; return ((pg >> (20 - PAGE_SHIFT)) + ((pg & ((1 << (20 - PAGE_SHIFT)) - 1)) ? 1 : 0)); } @@ -1583,7 +1285,7 @@ static void sh_hash_audit_bucket(struct domain *d, int bucket) if ( !(SHADOW_AUDIT_ENABLE) ) return; - sp = d->arch.shadow.hash_table[bucket]; + sp = d->arch.paging.shadow.hash_table[bucket]; while ( sp ) { /* Not a shadow? */ @@ -1608,7 +1310,7 @@ static void sh_hash_audit_bucket(struct domain *d, int bucket) if ( (gpg->u.inuse.type_info & PGT_type_mask) == PGT_writable_page && (gpg->u.inuse.type_info & PGT_count_mask) != 0 ) { - SHADOW_ERROR("MFN %#lx shadowed (by %#"SH_PRI_mfn")" + SHADOW_ERROR("MFN %#lx shadowed (by %#"PRI_mfn")" " but has typecount %#lx\n", sp->backpointer, mfn_x(shadow_page_to_mfn(sp)), gpg->u.inuse.type_info); @@ -1652,13 +1354,13 @@ static int shadow_hash_alloc(struct domain *d) struct shadow_page_info **table; ASSERT(shadow_locked_by_me(d)); - ASSERT(!d->arch.shadow.hash_table); + ASSERT(!d->arch.paging.shadow.hash_table); table = xmalloc_array(struct shadow_page_info *, SHADOW_HASH_BUCKETS); if ( !table ) return 1; memset(table, 0, SHADOW_HASH_BUCKETS * sizeof (struct shadow_page_info *)); - d->arch.shadow.hash_table = table; + d->arch.paging.shadow.hash_table = table; return 0; } @@ -1667,10 +1369,10 @@ static int shadow_hash_alloc(struct domain *d) static void shadow_hash_teardown(struct domain *d) { ASSERT(shadow_locked_by_me(d)); - ASSERT(d->arch.shadow.hash_table); + ASSERT(d->arch.paging.shadow.hash_table); - xfree(d->arch.shadow.hash_table); - d->arch.shadow.hash_table = NULL; + xfree(d->arch.paging.shadow.hash_table); + d->arch.paging.shadow.hash_table = NULL; } @@ -1683,7 +1385,7 @@ mfn_t shadow_hash_lookup(struct vcpu *v, unsigned long n, unsigned int t) key_t key; ASSERT(shadow_locked_by_me(d)); - ASSERT(d->arch.shadow.hash_table); + ASSERT(d->arch.paging.shadow.hash_table); ASSERT(t); sh_hash_audit(d); @@ -1692,16 +1394,16 @@ mfn_t shadow_hash_lookup(struct vcpu *v, unsigned long n, unsigned int t) key = sh_hash(n, t); sh_hash_audit_bucket(d, key); - sp = d->arch.shadow.hash_table[key]; + sp = d->arch.paging.shadow.hash_table[key]; prev = NULL; while(sp) { if ( sp->backpointer == n && sp->type == t ) { /* Pull-to-front if 'sp' isn't already the head item */ - if ( unlikely(sp != d->arch.shadow.hash_table[key]) ) + if ( unlikely(sp != d->arch.paging.shadow.hash_table[key]) ) { - if ( unlikely(d->arch.shadow.hash_walking != 0) ) + if ( unlikely(d->arch.paging.shadow.hash_walking != 0) ) /* Can't reorder: someone is walking the hash chains */ return shadow_page_to_mfn(sp); else @@ -1710,8 +1412,8 @@ mfn_t shadow_hash_lookup(struct vcpu *v, unsigned long n, unsigned int t) /* Delete sp from the list */ prev->next_shadow = sp->next_shadow; /* Re-insert it at the head of the list */ - sp->next_shadow = d->arch.shadow.hash_table[key]; - d->arch.shadow.hash_table[key] = sp; + sp->next_shadow = d->arch.paging.shadow.hash_table[key]; + d->arch.paging.shadow.hash_table[key] = sp; } } else @@ -1737,7 +1439,7 @@ void shadow_hash_insert(struct vcpu *v, unsigned long n, unsigned int t, key_t key; ASSERT(shadow_locked_by_me(d)); - ASSERT(d->arch.shadow.hash_table); + ASSERT(d->arch.paging.shadow.hash_table); ASSERT(t); sh_hash_audit(d); @@ -1748,8 +1450,8 @@ void shadow_hash_insert(struct vcpu *v, unsigned long n, unsigned int t, /* Insert this shadow at the top of the bucket */ sp = mfn_to_shadow_page(smfn); - sp->next_shadow = d->arch.shadow.hash_table[key]; - d->arch.shadow.hash_table[key] = sp; + sp->next_shadow = d->arch.paging.shadow.hash_table[key]; + d->arch.paging.shadow.hash_table[key] = sp; sh_hash_audit_bucket(d, key); } @@ -1763,7 +1465,7 @@ void shadow_hash_delete(struct vcpu *v, unsigned long n, unsigned int t, key_t key; ASSERT(shadow_locked_by_me(d)); - ASSERT(d->arch.shadow.hash_table); + ASSERT(d->arch.paging.shadow.hash_table); ASSERT(t); sh_hash_audit(d); @@ -1773,13 +1475,13 @@ void shadow_hash_delete(struct vcpu *v, unsigned long n, unsigned int t, sh_hash_audit_bucket(d, key); sp = mfn_to_shadow_page(smfn); - if ( d->arch.shadow.hash_table[key] == sp ) + if ( d->arch.paging.shadow.hash_table[key] == sp ) /* Easy case: we're deleting the head item. */ - d->arch.shadow.hash_table[key] = sp->next_shadow; + d->arch.paging.shadow.hash_table[key] = sp->next_shadow; else { /* Need to search for the one we want */ - x = d->arch.shadow.hash_table[key]; + x = d->arch.paging.shadow.hash_table[key]; while ( 1 ) { ASSERT(x); /* We can't have hit the end, since our target is @@ -1818,15 +1520,15 @@ static void hash_foreach(struct vcpu *v, /* Say we're here, to stop hash-lookups reordering the chains */ ASSERT(shadow_locked_by_me(d)); - ASSERT(d->arch.shadow.hash_walking == 0); - d->arch.shadow.hash_walking = 1; + ASSERT(d->arch.paging.shadow.hash_walking == 0); + d->arch.paging.shadow.hash_walking = 1; for ( i = 0; i < SHADOW_HASH_BUCKETS; i++ ) { /* WARNING: This is not safe against changes to the hash table. * The callback *must* return non-zero if it has inserted or * deleted anything from the hash (lookups are OK, though). */ - for ( x = d->arch.shadow.hash_table[i]; x; x = x->next_shadow ) + for ( x = d->arch.paging.shadow.hash_table[i]; x; x = x->next_shadow ) { if ( callback_mask & (1 << x->type) ) { @@ -1839,7 +1541,7 @@ static void hash_foreach(struct vcpu *v, } if ( done ) break; } - d->arch.shadow.hash_walking = 0; + d->arch.paging.shadow.hash_walking = 0; } @@ -2008,27 +1710,27 @@ int sh_remove_write_access(struct vcpu *v, mfn_t gmfn, * and that mapping is likely to be in the current pagetable, * in the guest's linear map (on non-HIGHPTE linux and windows)*/ -#define GUESS(_a, _h) do { \ - if ( v->arch.shadow.mode->guess_wrmap(v, (_a), gmfn) ) \ - perfc_incrc(shadow_writeable_h_ ## _h); \ - if ( (pg->u.inuse.type_info & PGT_count_mask) == 0 ) \ - return 1; \ +#define GUESS(_a, _h) do { \ + if ( v->arch.paging.mode->shadow.guess_wrmap(v, (_a), gmfn) ) \ + perfc_incrc(shadow_writeable_h_ ## _h); \ + if ( (pg->u.inuse.type_info & PGT_count_mask) == 0 ) \ + return 1; \ } while (0) - if ( v->arch.shadow.mode->guest_levels == 2 ) + if ( v->arch.paging.mode->guest_levels == 2 ) { if ( level == 1 ) /* 32bit non-PAE w2k3: linear map at 0xC0000000 */ GUESS(0xC0000000UL + (fault_addr >> 10), 1); /* Linux lowmem: first 896MB is mapped 1-to-1 above 0xC0000000 */ - if ((gfn = sh_mfn_to_gfn(v->domain, gmfn)) < 0x38000 ) + if ((gfn = mfn_to_gfn(v->domain, gmfn)) < 0x38000 ) GUESS(0xC0000000UL + (gfn << PAGE_SHIFT), 4); } #if CONFIG_PAGING_LEVELS >= 3 - else if ( v->arch.shadow.mode->guest_levels == 3 ) + else if ( v->arch.paging.mode->guest_levels == 3 ) { /* 32bit PAE w2k3: linear map at 0xC0000000 */ switch ( level ) @@ -2038,11 +1740,11 @@ int sh_remove_write_access(struct vcpu *v, mfn_t gmfn, } /* Linux lowmem: first 896MB is mapped 1-to-1 above 0xC0000000 */ - if ((gfn = sh_mfn_to_gfn(v->domain, gmfn)) < 0x38000 ) + if ((gfn = mfn_to_gfn(v->domain, gmfn)) < 0x38000 ) GUESS(0xC0000000UL + (gfn << PAGE_SHIFT), 4); } #if CONFIG_PAGING_LEVELS >= 4 - else if ( v->arch.shadow.mode->guest_levels == 4 ) + else if ( v->arch.paging.mode->guest_levels == 4 ) { /* 64bit w2k3: linear map at 0x0000070000000000 */ switch ( level ) @@ -2054,7 +1756,7 @@ int sh_remove_write_access(struct vcpu *v, mfn_t gmfn, /* 64bit Linux direct map at 0xffff810000000000; older kernels * had it at 0x0000010000000000UL */ - gfn = sh_mfn_to_gfn(v->domain, gmfn); + gfn = mfn_to_gfn(v->domain, gmfn); GUESS(0xffff810000000000UL + (gfn << PAGE_SHIFT), 4); GUESS(0x0000010000000000UL + (gfn << PAGE_SHIFT), 4); } @@ -2073,10 +1775,10 @@ int sh_remove_write_access(struct vcpu *v, mfn_t gmfn, * the writeable mapping by looking at the same MFN where the last * brute-force search succeeded. */ - if ( v->arch.shadow.last_writeable_pte_smfn != 0 ) + if ( v->arch.paging.shadow.last_writeable_pte_smfn != 0 ) { unsigned long old_count = (pg->u.inuse.type_info & PGT_count_mask); - mfn_t last_smfn = _mfn(v->arch.shadow.last_writeable_pte_smfn); + mfn_t last_smfn = _mfn(v->arch.paging.shadow.last_writeable_pte_smfn); int shtype = mfn_to_shadow_page(last_smfn)->type; if ( callbacks[shtype] ) @@ -2431,7 +2133,7 @@ sh_remove_all_shadows_and_parents(struct vcpu *v, mfn_t gmfn) static void sh_update_paging_modes(struct vcpu *v) { struct domain *d = v->domain; - struct shadow_paging_mode *old_mode = v->arch.shadow.mode; + struct paging_mode *old_mode = v->arch.paging.mode; mfn_t old_guest_table; ASSERT(shadow_locked_by_me(d)); @@ -2446,8 +2148,8 @@ static void sh_update_paging_modes(struct vcpu *v) // First, tear down any old shadow tables held by this vcpu. // - if ( v->arch.shadow.mode ) - v->arch.shadow.mode->detach_old_tables(v); + if ( v->arch.paging.mode ) + v->arch.paging.mode->shadow.detach_old_tables(v); if ( !is_hvm_domain(d) ) { @@ -2456,17 +2158,17 @@ static void sh_update_paging_modes(struct vcpu *v) /// #if CONFIG_PAGING_LEVELS == 4 if ( pv_32bit_guest(v) ) - v->arch.shadow.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,3,3); + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,3,3); else - v->arch.shadow.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,4,4); + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,4,4); #elif CONFIG_PAGING_LEVELS == 3 - v->arch.shadow.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,3,3); + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,3,3); #elif CONFIG_PAGING_LEVELS == 2 - v->arch.shadow.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,2,2); + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,2,2); #else #error unexpected paging mode #endif - v->arch.shadow.translate_enabled = !!shadow_mode_translate(d); + v->arch.paging.translate_enabled = !!shadow_mode_translate(d); } else { @@ -2476,8 +2178,8 @@ static void sh_update_paging_modes(struct vcpu *v) ASSERT(shadow_mode_translate(d)); ASSERT(shadow_mode_external(d)); - v->arch.shadow.translate_enabled = !!hvm_paging_enabled(v); - if ( !v->arch.shadow.translate_enabled ) + v->arch.paging.translate_enabled = !!hvm_paging_enabled(v); + if ( !v->arch.paging.translate_enabled ) { /* Set v->arch.guest_table to use the p2m map, and choose * the appropriate shadow mode */ @@ -2485,11 +2187,11 @@ static void sh_update_paging_modes(struct vcpu *v) #if CONFIG_PAGING_LEVELS == 2 v->arch.guest_table = pagetable_from_pfn(pagetable_get_pfn(d->arch.phys_table)); - v->arch.shadow.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,2,2); + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,2,2); #elif CONFIG_PAGING_LEVELS == 3 v->arch.guest_table = pagetable_from_pfn(pagetable_get_pfn(d->arch.phys_table)); - v->arch.shadow.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,3,3); + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,3,3); #else /* CONFIG_PAGING_LEVELS == 4 */ { l4_pgentry_t *l4e; @@ -2501,7 +2203,7 @@ static void sh_update_paging_modes(struct vcpu *v) pagetable_from_pfn(l4e_get_pfn(l4e[0])); sh_unmap_domain_page(l4e); } - v->arch.shadow.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,3,3); + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,3,3); #endif /* Fix up refcounts on guest_table */ get_page(mfn_to_page(pagetable_get_mfn(v->arch.guest_table)), d); @@ -2514,7 +2216,7 @@ static void sh_update_paging_modes(struct vcpu *v) if ( hvm_long_mode_enabled(v) ) { // long mode guest... - v->arch.shadow.mode = + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode, 4, 4); } else @@ -2523,7 +2225,7 @@ static void sh_update_paging_modes(struct vcpu *v) { #if CONFIG_PAGING_LEVELS >= 3 // 32-bit PAE mode guest... - v->arch.shadow.mode = + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode, 3, 3); #else SHADOW_ERROR("PAE not supported in 32-bit Xen\n"); @@ -2535,10 +2237,10 @@ static void sh_update_paging_modes(struct vcpu *v) { // 32-bit 2 level guest... #if CONFIG_PAGING_LEVELS >= 3 - v->arch.shadow.mode = + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode, 3, 2); #else - v->arch.shadow.mode = + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode, 2, 2); #endif } @@ -2546,25 +2248,25 @@ static void sh_update_paging_modes(struct vcpu *v) if ( pagetable_is_null(v->arch.monitor_table) ) { - mfn_t mmfn = v->arch.shadow.mode->make_monitor_table(v); + mfn_t mmfn = v->arch.paging.mode->shadow.make_monitor_table(v); v->arch.monitor_table = pagetable_from_mfn(mmfn); make_cr3(v, mfn_x(mmfn)); hvm_update_host_cr3(v); } - if ( v->arch.shadow.mode != old_mode ) + if ( v->arch.paging.mode != old_mode ) { SHADOW_PRINTK("new paging mode: d=%u v=%u pe=%d g=%u s=%u " "(was g=%u s=%u)\n", d->domain_id, v->vcpu_id, is_hvm_domain(d) ? !!hvm_paging_enabled(v) : 1, - v->arch.shadow.mode->guest_levels, - v->arch.shadow.mode->shadow_levels, + v->arch.paging.mode->guest_levels, + v->arch.paging.mode->shadow.shadow_levels, old_mode ? old_mode->guest_levels : 0, - old_mode ? old_mode->shadow_levels : 0); + old_mode ? old_mode->shadow.shadow_levels : 0); if ( old_mode && - (v->arch.shadow.mode->shadow_levels != - old_mode->shadow_levels) ) + (v->arch.paging.mode->shadow.shadow_levels != + old_mode->shadow.shadow_levels) ) { /* Need to make a new monitor table for the new mode */ mfn_t new_mfn, old_mfn; @@ -2584,9 +2286,9 @@ static void sh_update_paging_modes(struct vcpu *v) old_mfn = pagetable_get_mfn(v->arch.monitor_table); v->arch.monitor_table = pagetable_null(); - new_mfn = v->arch.shadow.mode->make_monitor_table(v); + new_mfn = v->arch.paging.mode->shadow.make_monitor_table(v); v->arch.monitor_table = pagetable_from_mfn(new_mfn); - SHADOW_PRINTK("new monitor table %"SH_PRI_mfn "\n", + SHADOW_PRINTK("new monitor table %"PRI_mfn "\n", mfn_x(new_mfn)); /* Don't be running on the old monitor table when we @@ -2596,7 +2298,7 @@ static void sh_update_paging_modes(struct vcpu *v) if ( v == current ) write_ptbase(v); hvm_update_host_cr3(v); - old_mode->destroy_monitor_table(v, old_mfn); + old_mode->shadow.destroy_monitor_table(v, old_mfn); } } @@ -2606,7 +2308,7 @@ static void sh_update_paging_modes(struct vcpu *v) // This *does* happen, at least for CR4.PGE... } - v->arch.shadow.mode->update_cr3(v, 0); + v->arch.paging.mode->update_cr3(v, 0); } void shadow_update_paging_modes(struct vcpu *v) @@ -2626,9 +2328,7 @@ static void sh_new_mode(struct domain *d, u32 new_mode) ASSERT(shadow_locked_by_me(d)); ASSERT(d != current->domain); - d->arch.shadow.mode = new_mode; - if ( new_mode & SHM2_translate ) - shadow_audit_p2m(d); + d->arch.paging.mode = new_mode; for_each_vcpu(d, v) sh_update_paging_modes(v); } @@ -2642,75 +2342,75 @@ int shadow_enable(struct domain *d, u32 mode) unsigned int old_pages; int rv = 0; - mode |= SHM2_enable; + mode |= PG_SH_enable; domain_pause(d); - shadow_lock(d); /* Sanity check the arguments */ if ( (d == current->domain) || shadow_mode_enabled(d) || - ((mode & SHM2_translate) && !(mode & SHM2_refcounts)) || - ((mode & SHM2_external) && !(mode & SHM2_translate)) ) + ((mode & PG_translate) && !(mode & PG_refcounts)) || + ((mode & PG_external) && !(mode & PG_translate)) ) { rv = -EINVAL; - goto out; + goto out_unlocked; } - // XXX -- eventually would like to require that all memory be allocated - // *after* shadow_enabled() is called... So here, we would test to make - // sure that d->page_list is empty. -#if 0 - spin_lock(&d->page_alloc_lock); - if ( !list_empty(&d->page_list) ) - { - spin_unlock(&d->page_alloc_lock); - rv = -EINVAL; - goto out; - } - spin_unlock(&d->page_alloc_lock); -#endif - /* Init the shadow memory allocation if the user hasn't done so */ - old_pages = d->arch.shadow.total_pages; + old_pages = d->arch.paging.shadow.total_pages; if ( old_pages == 0 ) - if ( sh_set_allocation(d, 256, NULL) != 0 ) /* Use at least 1MB */ + { + unsigned int r; + shadow_lock(d); + r = sh_set_allocation(d, 256, NULL); /* Use at least 1MB */ + shadow_unlock(d); + if ( r != 0 ) { sh_set_allocation(d, 0, NULL); rv = -ENOMEM; - goto out; - } + goto out_unlocked; + } + } + + /* Init the P2M table. Must be done before we take the shadow lock + * to avoid possible deadlock. */ + if ( mode & PG_translate ) + { + rv = p2m_alloc_table(d, shadow_alloc_p2m_page, shadow_free_p2m_page); + if (rv != 0) + goto out_unlocked; + } + + shadow_lock(d); + + /* Sanity check again with the lock held */ + if ( shadow_mode_enabled(d) ) + { + rv = -EINVAL; + goto out_locked; + } /* Init the hash table */ if ( shadow_hash_alloc(d) != 0 ) { - sh_set_allocation(d, old_pages, NULL); rv = -ENOMEM; - goto out; + goto out_locked; } - /* Init the P2M table */ - if ( mode & SHM2_translate ) - if ( !shadow_alloc_p2m_table(d) ) - { - shadow_hash_teardown(d); - sh_set_allocation(d, old_pages, NULL); - shadow_p2m_teardown(d); - rv = -ENOMEM; - goto out; - } - #if (SHADOW_OPTIMIZATIONS & SHOPT_LINUX_L3_TOPLEVEL) /* We assume we're dealing with an older 64bit linux guest until we * see the guest use more than one l4 per vcpu. */ - d->arch.shadow.opt_flags = SHOPT_LINUX_L3_TOPLEVEL; + d->arch.paging.shadow.opt_flags = SHOPT_LINUX_L3_TOPLEVEL; #endif /* Update the bits */ sh_new_mode(d, mode); - shadow_audit_p2m(d); - out: + + out_locked: shadow_unlock(d); + out_unlocked: + if ( rv != 0 && !pagetable_is_null(d->arch.phys_table) ) + p2m_teardown(d); domain_unpause(d); return rv; } @@ -2721,6 +2421,8 @@ void shadow_teardown(struct domain *d) { struct vcpu *v; mfn_t mfn; + struct list_head *entry, *n; + struct page_info *pg; ASSERT(test_bit(_DOMF_dying, &d->domain_flags)); ASSERT(d != current->domain); @@ -2733,48 +2435,55 @@ void shadow_teardown(struct domain *d) /* Release the shadow and monitor tables held by each vcpu */ for_each_vcpu(d, v) { - if ( v->arch.shadow.mode ) + if ( v->arch.paging.mode ) { - v->arch.shadow.mode->detach_old_tables(v); + v->arch.paging.mode->shadow.detach_old_tables(v); if ( shadow_mode_external(d) ) { mfn = pagetable_get_mfn(v->arch.monitor_table); if ( mfn_valid(mfn) && (mfn_x(mfn) != 0) ) - v->arch.shadow.mode->destroy_monitor_table(v, mfn); + v->arch.paging.mode->shadow.destroy_monitor_table(v, mfn); v->arch.monitor_table = pagetable_null(); } } } } - if ( d->arch.shadow.total_pages != 0 ) + list_for_each_safe(entry, n, &d->arch.paging.shadow.p2m_freelist) + { + list_del(entry); + pg = list_entry(entry, struct page_info, list); + shadow_free_p2m_page(d, pg); + } + + if ( d->arch.paging.shadow.total_pages != 0 ) { SHADOW_PRINTK("teardown of domain %u starts." " Shadow pages total = %u, free = %u, p2m=%u\n", d->domain_id, - d->arch.shadow.total_pages, - d->arch.shadow.free_pages, - d->arch.shadow.p2m_pages); + d->arch.paging.shadow.total_pages, + d->arch.paging.shadow.free_pages, + d->arch.paging.shadow.p2m_pages); /* Destroy all the shadows and release memory to domheap */ sh_set_allocation(d, 0, NULL); /* Release the hash table back to xenheap */ - if (d->arch.shadow.hash_table) + if (d->arch.paging.shadow.hash_table) shadow_hash_teardown(d); /* Release the log-dirty bitmap of dirtied pages */ sh_free_log_dirty_bitmap(d); /* Should not have any more memory held */ SHADOW_PRINTK("teardown done." " Shadow pages total = %u, free = %u, p2m=%u\n", - d->arch.shadow.total_pages, - d->arch.shadow.free_pages, - d->arch.shadow.p2m_pages); - ASSERT(d->arch.shadow.total_pages == 0); + d->arch.paging.shadow.total_pages, + d->arch.paging.shadow.free_pages, + d->arch.paging.shadow.p2m_pages); + ASSERT(d->arch.paging.shadow.total_pages == 0); } /* We leave the "permanent" shadow modes enabled, but clear the * log-dirty mode bit. We don't want any more mark_dirty() * calls now that we've torn down the bitmap */ - d->arch.shadow.mode &= ~SHM2_log_dirty; + d->arch.paging.mode &= ~PG_log_dirty; shadow_unlock(d); } @@ -2782,30 +2491,28 @@ void shadow_teardown(struct domain *d) void shadow_final_teardown(struct domain *d) /* Called by arch_domain_destroy(), when it's safe to pull down the p2m map. */ { - SHADOW_PRINTK("dom %u final teardown starts." " Shadow pages total = %u, free = %u, p2m=%u\n", d->domain_id, - d->arch.shadow.total_pages, - d->arch.shadow.free_pages, - d->arch.shadow.p2m_pages); + d->arch.paging.shadow.total_pages, + d->arch.paging.shadow.free_pages, + d->arch.paging.shadow.p2m_pages); /* Double-check that the domain didn't have any shadow memory. * It is possible for a domain that never got domain_kill()ed * to get here with its shadow allocation intact. */ - if ( d->arch.shadow.total_pages != 0 ) + if ( d->arch.paging.shadow.total_pages != 0 ) shadow_teardown(d); /* It is now safe to pull down the p2m map. */ - if ( d->arch.shadow.p2m_pages != 0 ) - shadow_p2m_teardown(d); + p2m_teardown(d); SHADOW_PRINTK("dom %u final teardown done." " Shadow pages total = %u, free = %u, p2m=%u\n", d->domain_id, - d->arch.shadow.total_pages, - d->arch.shadow.free_pages, - d->arch.shadow.p2m_pages); + d->arch.paging.shadow.total_pages, + d->arch.paging.shadow.free_pages, + d->arch.paging.shadow.p2m_pages); } static int shadow_one_bit_enable(struct domain *d, u32 mode) @@ -2814,12 +2521,14 @@ static int shadow_one_bit_enable(struct domain *d, u32 mode) ASSERT(shadow_locked_by_me(d)); /* Sanity check the call */ - if ( d == current->domain || (d->arch.shadow.mode & mode) ) + if ( d == current->domain || (d->arch.paging.mode & mode) ) { return -EINVAL; } - if ( d->arch.shadow.mode == 0 ) + mode |= PG_SH_enable; + + if ( d->arch.paging.mode == 0 ) { /* Init the shadow memory allocation and the hash table */ if ( sh_set_allocation(d, 1, NULL) != 0 @@ -2831,7 +2540,7 @@ static int shadow_one_bit_enable(struct domain *d, u32 mode) } /* Update the bits */ - sh_new_mode(d, d->arch.shadow.mode | mode); + sh_new_mode(d, d->arch.paging.mode | mode); return 0; } @@ -2843,26 +2552,26 @@ static int shadow_one_bit_disable(struct domain *d, u32 mode) ASSERT(shadow_locked_by_me(d)); /* Sanity check the call */ - if ( d == current->domain || !(d->arch.shadow.mode & mode) ) + if ( d == current->domain || !(d->arch.paging.mode & mode) ) { return -EINVAL; } /* Update the bits */ - sh_new_mode(d, d->arch.shadow.mode & ~mode); - if ( d->arch.shadow.mode == 0 ) + sh_new_mode(d, d->arch.paging.mode & ~mode); + if ( d->arch.paging.mode == 0 ) { /* Get this domain off shadows */ SHADOW_PRINTK("un-shadowing of domain %u starts." " Shadow pages total = %u, free = %u, p2m=%u\n", d->domain_id, - d->arch.shadow.total_pages, - d->arch.shadow.free_pages, - d->arch.shadow.p2m_pages); + d->arch.paging.shadow.total_pages, + d->arch.paging.shadow.free_pages, + d->arch.paging.shadow.p2m_pages); for_each_vcpu(d, v) { - if ( v->arch.shadow.mode ) - v->arch.shadow.mode->detach_old_tables(v); + if ( v->arch.paging.mode ) + v->arch.paging.mode->shadow.detach_old_tables(v); #if CONFIG_PAGING_LEVELS == 4 if ( !(v->arch.flags & TF_kernel_mode) ) make_cr3(v, pagetable_get_pfn(v->arch.guest_table_user)); @@ -2885,9 +2594,9 @@ static int shadow_one_bit_disable(struct domain *d, u32 mode) SHADOW_PRINTK("un-shadowing of domain %u done." " Shadow pages total = %u, free = %u, p2m=%u\n", d->domain_id, - d->arch.shadow.total_pages, - d->arch.shadow.free_pages, - d->arch.shadow.p2m_pages); + d->arch.paging.shadow.total_pages, + d->arch.paging.shadow.free_pages, + d->arch.paging.shadow.p2m_pages); } return 0; @@ -2909,7 +2618,7 @@ static int shadow_test_enable(struct domain *d) goto out; } - ret = shadow_one_bit_enable(d, SHM2_enable); + ret = shadow_one_bit_enable(d, PG_SH_enable); out: shadow_unlock(d); domain_unpause(d); @@ -2923,7 +2632,7 @@ static int shadow_test_disable(struct domain *d) domain_pause(d); shadow_lock(d); - ret = shadow_one_bit_disable(d, SHM2_enable); + ret = shadow_one_bit_disable(d, PG_SH_enable); shadow_unlock(d); domain_unpause(d); @@ -2933,19 +2642,19 @@ static int shadow_test_disable(struct domain *d) static int sh_alloc_log_dirty_bitmap(struct domain *d) { - ASSERT(d->arch.shadow.dirty_bitmap == NULL); - d->arch.shadow.dirty_bitmap_size = + ASSERT(d->arch.paging.shadow.dirty_bitmap == NULL); + d->arch.paging.shadow.dirty_bitmap_size = (arch_get_max_pfn(d) + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1); - d->arch.shadow.dirty_bitmap = + d->arch.paging.shadow.dirty_bitmap = xmalloc_array(unsigned long, - d->arch.shadow.dirty_bitmap_size / BITS_PER_LONG); - if ( d->arch.shadow.dirty_bitmap == NULL ) + d->arch.paging.shadow.dirty_bitmap_size / BITS_PER_LONG); + if ( d->arch.paging.shadow.dirty_bitmap == NULL ) { - d->arch.shadow.dirty_bitmap_size = 0; + d->arch.paging.shadow.dirty_bitmap_size = 0; return -ENOMEM; } - memset(d->arch.shadow.dirty_bitmap, 0, d->arch.shadow.dirty_bitmap_size/8); + memset(d->arch.paging.shadow.dirty_bitmap, 0, d->arch.paging.shadow.dirty_bitmap_size/8); return 0; } @@ -2953,11 +2662,11 @@ sh_alloc_log_dirty_bitmap(struct domain *d) static void sh_free_log_dirty_bitmap(struct domain *d) { - d->arch.shadow.dirty_bitmap_size = 0; - if ( d->arch.shadow.dirty_bitmap ) + d->arch.paging.shadow.dirty_bitmap_size = 0; + if ( d->arch.paging.shadow.dirty_bitmap ) { - xfree(d->arch.shadow.dirty_bitmap); - d->arch.shadow.dirty_bitmap = NULL; + xfree(d->arch.paging.shadow.dirty_bitmap); + d->arch.paging.shadow.dirty_bitmap = NULL; } } @@ -2989,7 +2698,7 @@ static int shadow_log_dirty_enable(struct domain *d) goto out; } - ret = shadow_one_bit_enable(d, SHM2_log_dirty); + ret = shadow_one_bit_enable(d, PG_log_dirty); if ( ret != 0 ) sh_free_log_dirty_bitmap(d); @@ -3005,7 +2714,7 @@ static int shadow_log_dirty_disable(struct domain *d) domain_pause(d); shadow_lock(d); - ret = shadow_one_bit_disable(d, SHM2_log_dirty); + ret = shadow_one_bit_disable(d, PG_log_dirty); if ( !shadow_mode_log_dirty(d) ) sh_free_log_dirty_bitmap(d); shadow_unlock(d); @@ -3017,100 +2726,52 @@ static int shadow_log_dirty_disable(struct domain *d) /**************************************************************************/ /* P2M map manipulations */ -static void -sh_p2m_remove_page(struct domain *d, unsigned long gfn, unsigned long mfn) +/* shadow specific code which should be called when P2M table entry is updated + * with new content. It is responsible for update the entry, as well as other + * shadow processing jobs. + */ +void +shadow_write_p2m_entry(struct vcpu *v, unsigned long gfn, l1_pgentry_t *p, + l1_pgentry_t new, unsigned int level) { - struct vcpu *v; + struct domain *d = v->domain; + mfn_t table_mfn = pagetable_get_mfn(d->arch.phys_table); + mfn_t mfn; + + shadow_lock(d); - if ( !shadow_mode_translate(d) ) - return; - - v = current; - if ( v->domain != d ) - v = d->vcpu[0]; - - SHADOW_DEBUG(P2M, "removing gfn=%#lx mfn=%#lx\n", gfn, mfn); - - ASSERT(mfn_x(sh_gfn_to_mfn(d, gfn)) == mfn); - //ASSERT(sh_mfn_to_gfn(d, mfn) == gfn); - - if ( v != NULL ) - { - sh_remove_all_shadows_and_parents(v, _mfn(mfn)); - if ( sh_remove_all_mappings(v, _mfn(mfn)) ) - flush_tlb_mask(d->domain_dirty_cpumask); + /* handle physmap_add and physmap_remove */ + mfn = gfn_to_mfn(d, gfn); + if ( v != NULL && level == 1 && mfn_valid(mfn) ) { + sh_remove_all_shadows_and_parents(v, mfn); + if ( sh_remove_all_mappings(v, mfn) ) + flush_tlb_mask(d->domain_dirty_cpumask); } + + /* update the entry with new content */ + safe_write_pte(p, new); - shadow_set_p2m_entry(d, gfn, _mfn(INVALID_MFN)); - set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY); -} + /* The P2M can be shadowed: keep the shadows synced */ + if ( d->vcpu[0] != NULL ) + (void)sh_validate_guest_entry(d->vcpu[0], table_mfn, p, sizeof(*p)); -void -shadow_guest_physmap_remove_page(struct domain *d, unsigned long gfn, - unsigned long mfn) -{ - shadow_lock(d); - shadow_audit_p2m(d); - sh_p2m_remove_page(d, gfn, mfn); - shadow_audit_p2m(d); - shadow_unlock(d); -} - -void -shadow_guest_physmap_add_page(struct domain *d, unsigned long gfn, - unsigned long mfn) -{ - unsigned long ogfn; - mfn_t omfn; - - if ( !shadow_mode_translate(d) ) - return; - - shadow_lock(d); - shadow_audit_p2m(d); - - SHADOW_DEBUG(P2M, "adding gfn=%#lx mfn=%#lx\n", gfn, mfn); - - omfn = sh_gfn_to_mfn(d, gfn); - if ( mfn_valid(omfn) ) - { - /* Get rid of the old mapping, especially any shadows */ - struct vcpu *v = current; - if ( v->domain != d ) - v = d->vcpu[0]; - if ( v != NULL ) - { - sh_remove_all_shadows_and_parents(v, omfn); - if ( sh_remove_all_mappings(v, omfn) ) - flush_tlb_mask(d->domain_dirty_cpumask); + /* install P2M in monitors for PAE Xen */ +#if CONFIG_PAGING_LEVELS == 3 + if ( level == 3 ) { + struct vcpu *v; + /* We have written to the p2m l3: need to sync the per-vcpu + * copies of it in the monitor tables */ + p2m_install_entry_in_monitors(d, (l3_pgentry_t *)p); + /* Also, any vcpus running on shadows of the p2m need to + * reload their CR3s so the change propagates to the shadow */ + for_each_vcpu(d, v) { + if ( pagetable_get_pfn(v->arch.guest_table) + == pagetable_get_pfn(d->arch.phys_table) + && v->arch.paging.mode != NULL ) + v->arch.paging.mode->update_cr3(v, 0); } - set_gpfn_from_mfn(mfn_x(omfn), INVALID_M2P_ENTRY); } - - ogfn = sh_mfn_to_gfn(d, _mfn(mfn)); - if ( -#ifdef __x86_64__ - (ogfn != 0x5555555555555555L) -#else - (ogfn != 0x55555555L) #endif - && (ogfn != INVALID_M2P_ENTRY) - && (ogfn != gfn) ) - { - /* This machine frame is already mapped at another physical address */ - SHADOW_DEBUG(P2M, "aliased! mfn=%#lx, old gfn=%#lx, new gfn=%#lx\n", - mfn, ogfn, gfn); - if ( mfn_valid(omfn = sh_gfn_to_mfn(d, ogfn)) ) - { - SHADOW_DEBUG(P2M, "old gfn=%#lx -> mfn %#lx\n", - ogfn , mfn_x(omfn)); - if ( mfn_x(omfn) == mfn ) - sh_p2m_remove_page(d, ogfn, mfn); - } - } - - shadow_set_p2m_entry(d, gfn, _mfn(mfn)); - set_gpfn_from_mfn(mfn, gfn); #if (SHADOW_OPTIMIZATIONS & SHOPT_FAST_FAULT_PATH) /* If we're doing FAST_FAULT_PATH, then shadow mode may have @@ -3122,7 +2783,6 @@ shadow_guest_physmap_add_page(struct domain *d, unsigned long gfn, shadow_blow_tables(d); #endif - shadow_audit_p2m(d); shadow_unlock(d); } @@ -3151,11 +2811,11 @@ static int shadow_log_dirty_op( SHADOW_DEBUG(LOGDIRTY, "log-dirty %s: dom %u faults=%u dirty=%u\n", (clean) ? "clean" : "peek", d->domain_id, - d->arch.shadow.fault_count, - d->arch.shadow.dirty_count); + d->arch.paging.shadow.fault_count, + d->arch.paging.shadow.dirty_count); - sc->stats.fault_count = d->arch.shadow.fault_count; - sc->stats.dirty_count = d->arch.shadow.dirty_count; + sc->stats.fault_count = d->arch.paging.shadow.fault_count; + sc->stats.dirty_count = d->arch.paging.shadow.dirty_count; if ( clean ) { @@ -3164,22 +2824,22 @@ static int shadow_log_dirty_op( * but for now, we just unshadow everything except Xen. */ shadow_blow_tables(d); - d->arch.shadow.fault_count = 0; - d->arch.shadow.dirty_count = 0; + d->arch.paging.shadow.fault_count = 0; + d->arch.paging.shadow.dirty_count = 0; } if ( guest_handle_is_null(sc->dirty_bitmap) ) /* caller may have wanted just to clean the state or access stats. */ peek = 0; - if ( (peek || clean) && (d->arch.shadow.dirty_bitmap == NULL) ) + if ( (peek || clean) && (d->arch.paging.shadow.dirty_bitmap == NULL) ) { rv = -EINVAL; /* perhaps should be ENOMEM? */ goto out; } - if ( sc->pages > d->arch.shadow.dirty_bitmap_size ) - sc->pages = d->arch.shadow.dirty_bitmap_size; + if ( sc->pages > d->arch.paging.shadow.dirty_bitmap_size ) + sc->pages = d->arch.paging.shadow.dirty_bitmap_size; #define CHUNK (8*1024) /* Transfer and clear in 1kB chunks for L1 cache. */ for ( i = 0; i < sc->pages; i += CHUNK ) @@ -3192,7 +2852,7 @@ static int shadow_log_dirty_op( { if ( copy_to_guest_offset( sc->dirty_bitmap, i/8, - (uint8_t *)d->arch.shadow.dirty_bitmap + (i/8), bytes) ) + (uint8_t *)d->arch.paging.shadow.dirty_bitmap + (i/8), bytes) ) { rv = -EFAULT; goto out; @@ -3200,7 +2860,7 @@ static int shadow_log_dirty_op( } if ( clean ) - memset((uint8_t *)d->arch.shadow.dirty_bitmap + (i/8), 0, bytes); + memset((uint8_t *)d->arch.paging.shadow.dirty_bitmap + (i/8), 0, bytes); } #undef CHUNK @@ -3221,7 +2881,7 @@ void sh_mark_dirty(struct domain *d, mfn_t gmfn) if ( !shadow_mode_log_dirty(d) || !mfn_valid(gmfn) ) return; - ASSERT(d->arch.shadow.dirty_bitmap != NULL); + ASSERT(d->arch.paging.shadow.dirty_bitmap != NULL); /* We /really/ mean PFN here, even for non-translated guests. */ pfn = get_gpfn_from_mfn(mfn_x(gmfn)); @@ -3235,24 +2895,24 @@ void sh_mark_dirty(struct domain *d, mfn_t gmfn) return; /* N.B. Can use non-atomic TAS because protected by shadow_lock. */ - if ( likely(pfn < d->arch.shadow.dirty_bitmap_size) ) + if ( likely(pfn < d->arch.paging.shadow.dirty_bitmap_size) ) { - if ( !__test_and_set_bit(pfn, d->arch.shadow.dirty_bitmap) ) + if ( !__test_and_set_bit(pfn, d->arch.paging.shadow.dirty_bitmap) ) { SHADOW_DEBUG(LOGDIRTY, - "marked mfn %" SH_PRI_mfn " (pfn=%lx), dom %d\n", + "marked mfn %" PRI_mfn " (pfn=%lx), dom %d\n", mfn_x(gmfn), pfn, d->domain_id); - d->arch.shadow.dirty_count++; + d->arch.paging.shadow.dirty_count++; } } else { SHADOW_PRINTK("mark_dirty OOR! " - "mfn=%" SH_PRI_mfn " pfn=%lx max=%x (dom %d)\n" + "mfn=%" PRI_mfn " pfn=%lx max=%x (dom %d)\n" "owner=%d c=%08x t=%" PRtype_info "\n", mfn_x(gmfn), pfn, - d->arch.shadow.dirty_bitmap_size, + d->arch.paging.shadow.dirty_bitmap_size, d->domain_id, (page_get_owner(mfn_to_page(gmfn)) ? page_get_owner(mfn_to_page(gmfn))->domain_id @@ -3292,7 +2952,7 @@ int shadow_domctl(struct domain *d, return rc; if ( is_hvm_domain(d) ) return -EINVAL; - if ( d->arch.shadow.mode & SHM2_enable ) + if ( d->arch.paging.mode & PG_SH_enable ) if ( (rc = shadow_test_disable(d)) != 0 ) return rc; return 0; @@ -3304,7 +2964,7 @@ int shadow_domctl(struct domain *d, return shadow_log_dirty_enable(d); case XEN_DOMCTL_SHADOW_OP_ENABLE_TRANSLATE: - return shadow_enable(d, SHM2_refcounts|SHM2_translate); + return shadow_enable(d, PG_refcounts|PG_translate); case XEN_DOMCTL_SHADOW_OP_CLEAN: case XEN_DOMCTL_SHADOW_OP_PEEK: @@ -3313,7 +2973,7 @@ int shadow_domctl(struct domain *d, case XEN_DOMCTL_SHADOW_OP_ENABLE: if ( sc->mode & XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY ) return shadow_log_dirty_enable(d); - return shadow_enable(d, sc->mode << SHM2_shift); + return shadow_enable(d, sc->mode << PG_mode_shift); case XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION: sc->mb = shadow_get_allocation(d); @@ -3390,7 +3050,7 @@ void shadow_audit_tables(struct vcpu *v) else { /* Audit only the current mode's tables */ - switch ( v->arch.shadow.mode->guest_levels ) + switch ( v->arch.paging.mode->guest_levels ) { case 2: mask = (SHF_L1_32|SHF_FL1_32|SHF_L2_32); break; case 3: mask = (SHF_L1_PAE|SHF_FL1_PAE|SHF_L2_PAE @@ -3406,199 +3066,6 @@ void shadow_audit_tables(struct vcpu *v) #endif /* Shadow audit */ - -/**************************************************************************/ -/* Auditing p2m tables */ - -#if SHADOW_AUDIT & SHADOW_AUDIT_P2M - -void shadow_audit_p2m(struct domain *d) -{ - struct list_head *entry; - struct page_info *page; - struct domain *od; - unsigned long mfn, gfn, m2pfn, lp2mfn = 0; - mfn_t p2mfn; - unsigned long orphans_d = 0, orphans_i = 0, mpbad = 0, pmbad = 0; - int test_linear; - - if ( !(SHADOW_AUDIT_ENABLE) || !shadow_mode_translate(d) ) - return; - - //SHADOW_PRINTK("p2m audit starts\n"); - - test_linear = ( (d == current->domain) - && !pagetable_is_null(current->arch.monitor_table) ); - if ( test_linear ) - local_flush_tlb(); - - /* Audit part one: walk the domain's page allocation list, checking - * the m2p entries. */ - for ( entry = d->page_list.next; - entry != &d->page_list; - entry = entry->next ) - { - page = list_entry(entry, struct page_info, list); - mfn = mfn_x(page_to_mfn(page)); - - // SHADOW_PRINTK("auditing guest page, mfn=%#lx\n", mfn); - - od = page_get_owner(page); - - if ( od != d ) - { - SHADOW_PRINTK("wrong owner %#lx -> %p(%u) != %p(%u)\n", - mfn, od, (od?od->domain_id:-1), d, d->domain_id); - continue; - } - - gfn = get_gpfn_from_mfn(mfn); - if ( gfn == INVALID_M2P_ENTRY ) - { - orphans_i++; - //SHADOW_PRINTK("orphaned guest page: mfn=%#lx has invalid gfn\n", - // mfn); - continue; - } - - if ( gfn == 0x55555555 ) - { - orphans_d++; - //SHADOW_PRINTK("orphaned guest page: mfn=%#lx has debug gfn\n", - // mfn); - continue; - } - - p2mfn = sh_gfn_to_mfn_foreign(d, gfn); - if ( mfn_x(p2mfn) != mfn ) - { - mpbad++; - SHADOW_PRINTK("map mismatch mfn %#lx -> gfn %#lx -> mfn %#lx" - " (-> gfn %#lx)\n", - mfn, gfn, mfn_x(p2mfn), - (mfn_valid(p2mfn) - ? get_gpfn_from_mfn(mfn_x(p2mfn)) - : -1u)); - /* This m2p entry is stale: the domain has another frame in - * this physical slot. No great disaster, but for neatness, - * blow away the m2p entry. */ - set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY); - } - - if ( test_linear && (gfn <= d->arch.max_mapped_pfn) ) - { - lp2mfn = gfn_to_mfn_current(gfn); - if ( mfn_x(lp2mfn) != mfn_x(p2mfn) ) - { - SHADOW_PRINTK("linear mismatch gfn %#lx -> mfn %#lx " - "(!= mfn %#lx)\n", gfn, - mfn_x(lp2mfn), mfn_x(p2mfn)); - } - } - - // SHADOW_PRINTK("OK: mfn=%#lx, gfn=%#lx, p2mfn=%#lx, lp2mfn=%#lx\n", - // mfn, gfn, p2mfn, lp2mfn); - } - - /* Audit part two: walk the domain's p2m table, checking the entries. */ - if ( pagetable_get_pfn(d->arch.phys_table) != 0 ) - { - l2_pgentry_t *l2e; - l1_pgentry_t *l1e; - int i1, i2; - -#if CONFIG_PAGING_LEVELS == 4 - l4_pgentry_t *l4e; - l3_pgentry_t *l3e; - int i3, i4; - l4e = sh_map_domain_page(pagetable_get_mfn(d->arch.phys_table)); -#elif CONFIG_PAGING_LEVELS == 3 - l3_pgentry_t *l3e; - int i3; - l3e = sh_map_domain_page(pagetable_get_mfn(d->arch.phys_table)); -#else /* CONFIG_PAGING_LEVELS == 2 */ - l2e = sh_map_domain_page(pagetable_get_mfn(d->arch.phys_table)); -#endif - - gfn = 0; -#if CONFIG_PAGING_LEVELS >= 3 -#if CONFIG_PAGING_LEVELS >= 4 - for ( i4 = 0; i4 < L4_PAGETABLE_ENTRIES; i4++ ) - { - if ( !(l4e_get_flags(l4e[i4]) & _PAGE_PRESENT) ) - { - gfn += 1 << (L4_PAGETABLE_SHIFT - PAGE_SHIFT); - continue; - } - l3e = sh_map_domain_page(_mfn(l4e_get_pfn(l4e[i4]))); -#endif /* now at levels 3 or 4... */ - for ( i3 = 0; - i3 < ((CONFIG_PAGING_LEVELS==4) ? L3_PAGETABLE_ENTRIES : 8); - i3++ ) - { - if ( !(l3e_get_flags(l3e[i3]) & _PAGE_PRESENT) ) - { - gfn += 1 << (L3_PAGETABLE_SHIFT - PAGE_SHIFT); - continue; - } - l2e = sh_map_domain_page(_mfn(l3e_get_pfn(l3e[i3]))); -#endif /* all levels... */ - for ( i2 = 0; i2 < L2_PAGETABLE_ENTRIES; i2++ ) - { - if ( !(l2e_get_flags(l2e[i2]) & _PAGE_PRESENT) ) - { - gfn += 1 << (L2_PAGETABLE_SHIFT - PAGE_SHIFT); - continue; - } - l1e = sh_map_domain_page(_mfn(l2e_get_pfn(l2e[i2]))); - - for ( i1 = 0; i1 < L1_PAGETABLE_ENTRIES; i1++, gfn++ ) - { - if ( !(l1e_get_flags(l1e[i1]) & _PAGE_PRESENT) ) - continue; - mfn = l1e_get_pfn(l1e[i1]); - ASSERT(mfn_valid(_mfn(mfn))); - m2pfn = get_gpfn_from_mfn(mfn); - if ( m2pfn != gfn ) - { - pmbad++; - SHADOW_PRINTK("mismatch: gfn %#lx -> mfn %#lx" - " -> gfn %#lx\n", gfn, mfn, m2pfn); - BUG(); - } - } - sh_unmap_domain_page(l1e); - } -#if CONFIG_PAGING_LEVELS >= 3 - sh_unmap_domain_page(l2e); - } -#if CONFIG_PAGING_LEVELS >= 4 - sh_unmap_domain_page(l3e); - } -#endif -#endif - -#if CONFIG_PAGING_LEVELS == 4 - sh_unmap_domain_page(l4e); -#elif CONFIG_PAGING_LEVELS == 3 - sh_unmap_domain_page(l3e); -#else /* CONFIG_PAGING_LEVELS == 2 */ - sh_unmap_domain_page(l2e); -#endif - - } - - //SHADOW_PRINTK("p2m audit complete\n"); - //if ( orphans_i | orphans_d | mpbad | pmbad ) - // SHADOW_PRINTK("p2m audit found %lu orphans (%lu inval %lu debug)\n", - // orphans_i + orphans_d, orphans_i, orphans_d, - if ( mpbad | pmbad ) - SHADOW_PRINTK("p2m audit found %lu odd p2m, %lu bad m2p entries\n", - pmbad, mpbad); -} - -#endif /* p2m audit */ - /* * Local variables: * mode: C diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c index 8b8b8585a7..fec6551d8c 100644 --- a/xen/arch/x86/mm/shadow/multi.c +++ b/xen/arch/x86/mm/shadow/multi.c @@ -237,7 +237,8 @@ guest_walk_tables(struct vcpu *v, unsigned long va, walk_t *gw, int guest_op) #if GUEST_PAGING_LEVELS >= 4 /* 64-bit only... */ /* Get l4e from the top level table */ gw->l4mfn = pagetable_get_mfn(v->arch.guest_table); - gw->l4e = (guest_l4e_t *)v->arch.guest_vtable + guest_l4_table_offset(va); + gw->l4e = (guest_l4e_t *)v->arch.paging.shadow.guest_vtable + + guest_l4_table_offset(va); /* Walk down to the l3e */ if ( !(guest_l4e_get_flags(*gw->l4e) & _PAGE_PRESENT) ) return 0; gw->l3mfn = vcpu_gfn_to_mfn(v, guest_l4e_get_gfn(*gw->l4e)); @@ -248,9 +249,8 @@ guest_walk_tables(struct vcpu *v, unsigned long va, walk_t *gw, int guest_op) gw->l3e = ((guest_l3e_t *)sh_map_domain_page(gw->l3mfn)) + guest_l3_table_offset(va); #else /* PAE only... */ - /* Get l3e from the top level table */ - gw->l3mfn = pagetable_get_mfn(v->arch.guest_table); - gw->l3e = (guest_l3e_t *)v->arch.guest_vtable + guest_l3_table_offset(va); + /* Get l3e from the cache of the guest's top level table */ + gw->l3e = (guest_l3e_t *)&v->arch.paging.shadow.gl3e[guest_l3_table_offset(va)]; #endif /* PAE or 64... */ /* Walk down to the l2e */ if ( !(guest_l3e_get_flags(*gw->l3e) & _PAGE_PRESENT) ) return 0; @@ -264,7 +264,8 @@ guest_walk_tables(struct vcpu *v, unsigned long va, walk_t *gw, int guest_op) #else /* 32-bit only... */ /* Get l2e from the top level table */ gw->l2mfn = pagetable_get_mfn(v->arch.guest_table); - gw->l2e = (guest_l2e_t *)v->arch.guest_vtable + guest_l2_table_offset(va); + gw->l2e = (guest_l2e_t *)v->arch.paging.shadow.guest_vtable + + guest_l2_table_offset(va); #endif /* All levels... */ if ( !(guest_l2e_get_flags(*gw->l2e) & _PAGE_PRESENT) ) return 0; @@ -353,21 +354,21 @@ static inline void print_gw(walk_t *gw) SHADOW_PRINTK("GUEST WALK TO %#lx:\n", gw->va); #if GUEST_PAGING_LEVELS >= 3 /* PAE or 64... */ #if GUEST_PAGING_LEVELS >= 4 /* 64-bit only... */ - SHADOW_PRINTK(" l4mfn=%" SH_PRI_mfn "\n", mfn_x(gw->l4mfn)); + SHADOW_PRINTK(" l4mfn=%" PRI_mfn "\n", mfn_x(gw->l4mfn)); SHADOW_PRINTK(" l4e=%p\n", gw->l4e); if ( gw->l4e ) SHADOW_PRINTK(" *l4e=%" SH_PRI_gpte "\n", gw->l4e->l4); + SHADOW_PRINTK(" l3mfn=%" PRI_mfn "\n", mfn_x(gw->l3mfn)); #endif /* PAE or 64... */ - SHADOW_PRINTK(" l3mfn=%" SH_PRI_mfn "\n", mfn_x(gw->l3mfn)); SHADOW_PRINTK(" l3e=%p\n", gw->l3e); if ( gw->l3e ) SHADOW_PRINTK(" *l3e=%" SH_PRI_gpte "\n", gw->l3e->l3); #endif /* All levels... */ - SHADOW_PRINTK(" l2mfn=%" SH_PRI_mfn "\n", mfn_x(gw->l2mfn)); + SHADOW_PRINTK(" l2mfn=%" PRI_mfn "\n", mfn_x(gw->l2mfn)); SHADOW_PRINTK(" l2e=%p\n", gw->l2e); if ( gw->l2e ) SHADOW_PRINTK(" *l2e=%" SH_PRI_gpte "\n", gw->l2e->l2); - SHADOW_PRINTK(" l1mfn=%" SH_PRI_mfn "\n", mfn_x(gw->l1mfn)); + SHADOW_PRINTK(" l1mfn=%" PRI_mfn "\n", mfn_x(gw->l1mfn)); SHADOW_PRINTK(" l1e=%p\n", gw->l1e); if ( gw->l1e ) SHADOW_PRINTK(" *l1e=%" SH_PRI_gpte "\n", gw->l1e->l1); @@ -1572,7 +1573,7 @@ sh_make_shadow(struct vcpu *v, mfn_t gmfn, u32 shadow_type) #if GUEST_PAGING_LEVELS == 4 #if (SHADOW_OPTIMIZATIONS & SHOPT_LINUX_L3_TOPLEVEL) if ( shadow_type == SH_type_l4_64_shadow && - unlikely(v->domain->arch.shadow.opt_flags & SHOPT_LINUX_L3_TOPLEVEL) ) + unlikely(v->domain->arch.paging.shadow.opt_flags & SHOPT_LINUX_L3_TOPLEVEL) ) { /* We're shadowing a new l4, but we've been assuming the guest uses * only one l4 per vcpu and context switches using an l4 entry. @@ -1584,7 +1585,7 @@ sh_make_shadow(struct vcpu *v, mfn_t gmfn, u32 shadow_type) struct shadow_page_info *sp; struct vcpu *v2; int l4count = 0, vcpus = 0; - list_for_each(l, &v->domain->arch.shadow.pinned_shadows) + list_for_each(l, &v->domain->arch.paging.shadow.pinned_shadows) { sp = list_entry(l, struct shadow_page_info, list); if ( sp->type == SH_type_l4_64_shadow ) @@ -1595,13 +1596,13 @@ sh_make_shadow(struct vcpu *v, mfn_t gmfn, u32 shadow_type) if ( l4count > 2 * vcpus ) { /* Unpin all the pinned l3 tables, and don't pin any more. */ - list_for_each_safe(l, t, &v->domain->arch.shadow.pinned_shadows) + list_for_each_safe(l, t, &v->domain->arch.paging.shadow.pinned_shadows) { sp = list_entry(l, struct shadow_page_info, list); if ( sp->type == SH_type_l3_64_shadow ) sh_unpin(v, shadow_page_to_mfn(sp)); } - v->domain->arch.shadow.opt_flags &= ~SHOPT_LINUX_L3_TOPLEVEL; + v->domain->arch.paging.shadow.opt_flags &= ~SHOPT_LINUX_L3_TOPLEVEL; } } #endif @@ -1641,7 +1642,7 @@ make_fl1_shadow(struct vcpu *v, gfn_t gfn) mfn_t smfn = shadow_alloc(v->domain, SH_type_fl1_shadow, (unsigned long) gfn_x(gfn)); - SHADOW_DEBUG(MAKE_SHADOW, "(%" SH_PRI_gfn ")=>%" SH_PRI_mfn "\n", + SHADOW_DEBUG(MAKE_SHADOW, "(%" SH_PRI_gfn ")=>%" PRI_mfn "\n", gfn_x(gfn), mfn_x(smfn)); set_fl1_shadow_status(v, gfn, smfn); @@ -1851,7 +1852,7 @@ static shadow_l2e_t * shadow_get_and_create_l2e(struct vcpu *v, #elif GUEST_PAGING_LEVELS == 3 /* PAE... */ /* We never demand-shadow PAE l3es: they are only created in * sh_update_cr3(). Check if the relevant sl3e is present. */ - shadow_l3e_t *sl3e = ((shadow_l3e_t *)&v->arch.shadow.l3table) + shadow_l3e_t *sl3e = ((shadow_l3e_t *)&v->arch.paging.shadow.l3table) + shadow_l3_linear_offset(gw->va); if ( !(shadow_l3e_get_flags(*sl3e) & _PAGE_PRESENT) ) return NULL; @@ -2358,7 +2359,7 @@ static int validate_gl1e(struct vcpu *v, void *new_ge, mfn_t sl1mfn, void *se) gfn = guest_l1e_get_gfn(*new_gl1e); gmfn = vcpu_gfn_to_mfn(v, gfn); - mmio = (is_hvm_vcpu(v) && shadow_vcpu_mode_translate(v) && !mfn_valid(gmfn)); + mmio = (is_hvm_vcpu(v) && paging_vcpu_mode_translate(v) && !mfn_valid(gmfn)); l1e_propagate_from_guest(v, new_gl1e, _mfn(INVALID_MFN), gmfn, &new_sl1e, ft_prefetch, mmio); @@ -2506,7 +2507,7 @@ sh_map_and_validate_gl1e(struct vcpu *v, mfn_t gl1mfn, static inline void check_for_early_unshadow(struct vcpu *v, mfn_t gmfn) { #if SHADOW_OPTIMIZATIONS & SHOPT_EARLY_UNSHADOW - if ( v->arch.shadow.last_emulated_mfn == mfn_x(gmfn) && + if ( v->arch.paging.shadow.last_emulated_mfn == mfn_x(gmfn) && sh_mfn_is_a_page_table(gmfn) ) { u32 flags = mfn_to_page(gmfn)->shadow_flags; @@ -2516,7 +2517,7 @@ static inline void check_for_early_unshadow(struct vcpu *v, mfn_t gmfn) sh_remove_shadows(v, gmfn, 1, 0 /* Fast, can fail to unshadow */ ); } } - v->arch.shadow.last_emulated_mfn = mfn_x(gmfn); + v->arch.paging.shadow.last_emulated_mfn = mfn_x(gmfn); #endif } @@ -2524,7 +2525,7 @@ static inline void check_for_early_unshadow(struct vcpu *v, mfn_t gmfn) static inline void reset_early_unshadow(struct vcpu *v) { #if SHADOW_OPTIMIZATIONS & SHOPT_EARLY_UNSHADOW - v->arch.shadow.last_emulated_mfn = INVALID_MFN; + v->arch.paging.shadow.last_emulated_mfn = INVALID_MFN; #endif } @@ -2589,7 +2590,7 @@ static void sh_prefetch(struct vcpu *v, walk_t *gw, gfn = guest_l1e_get_gfn(gl1e); gmfn = vcpu_gfn_to_mfn(v, gfn); mmio = ( is_hvm_vcpu(v) - && shadow_vcpu_mode_translate(v) + && paging_vcpu_mode_translate(v) && mmio_space(gfn_to_paddr(gfn)) ); /* Propagate the entry. Safe to use a pointer to our local @@ -2631,6 +2632,7 @@ static int sh_page_fault(struct vcpu *v, SHADOW_PRINTK("d:v=%u:%u va=%#lx err=%u\n", v->domain->domain_id, v->vcpu_id, va, regs->error_code); + perfc_incrc(shadow_fault); // // XXX: Need to think about eventually mapping superpages directly in the // shadow (when possible), as opposed to splintering them into a @@ -2651,7 +2653,7 @@ static int sh_page_fault(struct vcpu *v, if ( sh_l1e_is_gnp(sl1e) ) { if ( likely(!is_hvm_domain(d) || - shadow_vcpu_mode_translate(v)) ) + paging_vcpu_mode_translate(v)) ) { /* Not-present in a guest PT: pass to the guest as * a not-present fault (by flipping two bits). */ @@ -2701,7 +2703,7 @@ static int sh_page_fault(struct vcpu *v, if ( unlikely(shadow_locked_by_me(d)) ) { SHADOW_ERROR("Recursive shadow fault: lock was taken by %s\n", - d->arch.shadow.locker_function); + d->arch.paging.shadow.locker_function); return 0; } @@ -2726,7 +2728,7 @@ static int sh_page_fault(struct vcpu *v, // if ( unlikely(!(guest_l1e_get_flags(gw.eff_l1e) & _PAGE_PRESENT)) ) { - if ( is_hvm_domain(d) && !shadow_vcpu_mode_translate(v) ) + if ( is_hvm_domain(d) && !paging_vcpu_mode_translate(v) ) { /* Not present in p2m map, means this is mmio */ gpa = va; @@ -2784,13 +2786,13 @@ static int sh_page_fault(struct vcpu *v, gfn = guest_l1e_get_gfn(gw.eff_l1e); gmfn = vcpu_gfn_to_mfn(v, gfn); mmio = (is_hvm_domain(d) - && shadow_vcpu_mode_translate(v) + && paging_vcpu_mode_translate(v) && mmio_space(gfn_to_paddr(gfn))); if ( !mmio && !mfn_valid(gmfn) ) { perfc_incrc(shadow_fault_bail_bad_gfn); - SHADOW_PRINTK("BAD gfn=%"SH_PRI_gfn" gmfn=%"SH_PRI_mfn"\n", + SHADOW_PRINTK("BAD gfn=%"SH_PRI_gfn" gmfn=%"PRI_mfn"\n", gfn_x(gfn), mfn_x(gmfn)); goto not_a_shadow_fault; } @@ -2848,7 +2850,7 @@ static int sh_page_fault(struct vcpu *v, } perfc_incrc(shadow_fault_fixed); - d->arch.shadow.fault_count++; + d->arch.paging.shadow.fault_count++; reset_early_unshadow(v); done: @@ -2949,7 +2951,7 @@ sh_invlpg(struct vcpu *v, unsigned long va) return 0; } #elif SHADOW_PAGING_LEVELS == 3 - if ( !(l3e_get_flags(v->arch.shadow.l3table[shadow_l3_linear_offset(va)]) + if ( !(l3e_get_flags(v->arch.paging.shadow.l3table[shadow_l3_linear_offset(va)]) & _PAGE_PRESENT) ) // no need to flush anything if there's no SL2... return 0; @@ -3120,7 +3122,7 @@ sh_update_linear_entries(struct vcpu *v) } /* Shadow l3 tables are made up by sh_update_cr3 */ - sl3e = v->arch.shadow.l3table; + sl3e = v->arch.paging.shadow.l3table; for ( i = 0; i < SHADOW_L3_PAGETABLE_ENTRIES; i++ ) { @@ -3161,15 +3163,14 @@ sh_update_linear_entries(struct vcpu *v) #if GUEST_PAGING_LEVELS == 2 /* Shadow l3 tables were built by sh_update_cr3 */ if ( shadow_mode_external(d) ) - shadow_l3e = (shadow_l3e_t *)&v->arch.shadow.l3table; + shadow_l3e = (shadow_l3e_t *)&v->arch.paging.shadow.l3table; else BUG(); /* PV 2-on-3 is not supported yet */ #else /* GUEST_PAGING_LEVELS == 3 */ - shadow_l3e = (shadow_l3e_t *)&v->arch.shadow.l3table; - /* Always safe to use guest_vtable, because it's globally mapped */ - guest_l3e = v->arch.guest_vtable; + shadow_l3e = (shadow_l3e_t *)&v->arch.paging.shadow.l3table; + guest_l3e = (guest_l3e_t *)&v->arch.paging.shadow.gl3e; #endif /* GUEST_PAGING_LEVELS */ @@ -3267,39 +3268,37 @@ sh_update_linear_entries(struct vcpu *v) } -/* Removes vcpu->arch.guest_vtable and vcpu->arch.shadow_table[]. +/* Removes vcpu->arch.paging.shadow.guest_vtable and vcpu->arch.shadow_table[]. * Does all appropriate management/bookkeeping/refcounting/etc... */ static void sh_detach_old_tables(struct vcpu *v) { - struct domain *d = v->domain; mfn_t smfn; int i = 0; //// - //// vcpu->arch.guest_vtable + //// vcpu->arch.paging.shadow.guest_vtable //// - if ( v->arch.guest_vtable ) + +#if GUEST_PAGING_LEVELS == 3 + /* PAE guests don't have a mapping of the guest top-level table */ + ASSERT(v->arch.paging.shadow.guest_vtable == NULL); +#else + if ( v->arch.paging.shadow.guest_vtable ) { -#if GUEST_PAGING_LEVELS == 4 + struct domain *d = v->domain; if ( shadow_mode_external(d) || shadow_mode_translate(d) ) - sh_unmap_domain_page_global(v->arch.guest_vtable); -#elif GUEST_PAGING_LEVELS == 3 - if ( 1 || shadow_mode_external(d) || shadow_mode_translate(d) ) - sh_unmap_domain_page_global(v->arch.guest_vtable); -#elif GUEST_PAGING_LEVELS == 2 - if ( shadow_mode_external(d) || shadow_mode_translate(d) ) - sh_unmap_domain_page_global(v->arch.guest_vtable); -#endif - v->arch.guest_vtable = NULL; + sh_unmap_domain_page_global(v->arch.paging.shadow.guest_vtable); + v->arch.paging.shadow.guest_vtable = NULL; } +#endif + //// //// vcpu->arch.shadow_table[] //// - #if GUEST_PAGING_LEVELS == 3 /* PAE guests have four shadow_table entries */ for ( i = 0 ; i < 4 ; i++ ) @@ -3370,7 +3369,7 @@ sh_set_toplevel_shadow(struct vcpu *v, install_new_entry: /* Done. Install it */ - SHADOW_PRINTK("%u/%u [%u] gmfn %#"SH_PRI_mfn" smfn %#"SH_PRI_mfn"\n", + SHADOW_PRINTK("%u/%u [%u] gmfn %#"PRI_mfn" smfn %#"PRI_mfn"\n", GUEST_PAGING_LEVELS, SHADOW_PAGING_LEVELS, slot, mfn_x(gmfn), mfn_x(pagetable_get_mfn(new_entry))); v->arch.shadow_table[slot] = new_entry; @@ -3397,7 +3396,9 @@ sh_update_cr3(struct vcpu *v, int do_locking) struct domain *d = v->domain; mfn_t gmfn; #if GUEST_PAGING_LEVELS == 3 + guest_l3e_t *gl3e; u32 guest_idx=0; + int i; #endif /* Don't do anything on an uninitialised vcpu */ @@ -3410,7 +3411,7 @@ sh_update_cr3(struct vcpu *v, int do_locking) if ( do_locking ) shadow_lock(v->domain); ASSERT(shadow_locked_by_me(v->domain)); - ASSERT(v->arch.shadow.mode); + ASSERT(v->arch.paging.mode); //// //// vcpu->arch.guest_table is already set @@ -3425,7 +3426,7 @@ sh_update_cr3(struct vcpu *v, int do_locking) ASSERT(shadow_mode_external(d)); // Is paging enabled on this vcpu? - if ( shadow_vcpu_mode_translate(v) ) + if ( paging_vcpu_mode_translate(v) ) { gfn = _gfn(paddr_to_pfn(hvm_get_guest_ctrl_reg(v, 3))); gmfn = vcpu_gfn_to_mfn(v, gfn); @@ -3456,55 +3457,54 @@ sh_update_cr3(struct vcpu *v, int do_locking) //// - //// vcpu->arch.guest_vtable + //// vcpu->arch.paging.shadow.guest_vtable //// #if GUEST_PAGING_LEVELS == 4 if ( shadow_mode_external(d) || shadow_mode_translate(d) ) { - if ( v->arch.guest_vtable ) - sh_unmap_domain_page_global(v->arch.guest_vtable); - v->arch.guest_vtable = sh_map_domain_page_global(gmfn); + if ( v->arch.paging.shadow.guest_vtable ) + sh_unmap_domain_page_global(v->arch.paging.shadow.guest_vtable); + v->arch.paging.shadow.guest_vtable = sh_map_domain_page_global(gmfn); } else - v->arch.guest_vtable = __linear_l4_table; + v->arch.paging.shadow.guest_vtable = __linear_l4_table; #elif GUEST_PAGING_LEVELS == 3 - if ( v->arch.guest_vtable ) - sh_unmap_domain_page_global(v->arch.guest_vtable); - if ( shadow_mode_external(d) ) - { - if ( shadow_vcpu_mode_translate(v) ) - /* Paging enabled: find where in the page the l3 table is */ - guest_idx = guest_index((void *)hvm_get_guest_ctrl_reg(v, 3)); - else - /* Paging disabled: l3 is at the start of a page (in the p2m) */ - guest_idx = 0; - - // Ignore the low 2 bits of guest_idx -- they are really just - // cache control. - guest_idx &= ~3; - - // XXX - why does this need a global map? - v->arch.guest_vtable = - (guest_l3e_t *)sh_map_domain_page_global(gmfn) + guest_idx; - } + /* On PAE guests we don't use a mapping of the guest's own top-level + * table. We cache the current state of that table and shadow that, + * until the next CR3 write makes us refresh our cache. */ + ASSERT(v->arch.paging.shadow.guest_vtable == NULL); + + if ( shadow_mode_external(d) && paging_vcpu_mode_translate(v) ) + /* Paging enabled: find where in the page the l3 table is */ + guest_idx = guest_index((void *)hvm_get_guest_ctrl_reg(v, 3)); else - v->arch.guest_vtable = sh_map_domain_page_global(gmfn); + /* Paging disabled or PV: l3 is at the start of a page */ + guest_idx = 0; + + // Ignore the low 2 bits of guest_idx -- they are really just + // cache control. + guest_idx &= ~3; + + gl3e = ((guest_l3e_t *)sh_map_domain_page(gmfn)) + guest_idx; + for ( i = 0; i < 4 ; i++ ) + v->arch.paging.shadow.gl3e[i] = gl3e[i]; + sh_unmap_domain_page(gl3e); #elif GUEST_PAGING_LEVELS == 2 if ( shadow_mode_external(d) || shadow_mode_translate(d) ) { - if ( v->arch.guest_vtable ) - sh_unmap_domain_page_global(v->arch.guest_vtable); - v->arch.guest_vtable = sh_map_domain_page_global(gmfn); + if ( v->arch.paging.shadow.guest_vtable ) + sh_unmap_domain_page_global(v->arch.paging.shadow.guest_vtable); + v->arch.paging.shadow.guest_vtable = sh_map_domain_page_global(gmfn); } else - v->arch.guest_vtable = __linear_l2_table; + v->arch.paging.shadow.guest_vtable = __linear_l2_table; #else #error this should never happen #endif #if 0 - printk("%s %s %d gmfn=%05lx guest_vtable=%p\n", - __func__, __FILE__, __LINE__, gmfn, v->arch.guest_vtable); + printk("%s %s %d gmfn=%05lx shadow.guest_vtable=%p\n", + __func__, __FILE__, __LINE__, gmfn, v->arch.paging.shadow.guest_vtable); #endif //// @@ -3522,10 +3522,10 @@ sh_update_cr3(struct vcpu *v, int do_locking) /* PAE guests have four shadow_table entries, based on the * current values of the guest's four l3es. */ { - int i, flush = 0; + int flush = 0; gfn_t gl2gfn; mfn_t gl2mfn; - guest_l3e_t *gl3e = (guest_l3e_t*)v->arch.guest_vtable; + guest_l3e_t *gl3e = (guest_l3e_t*)&v->arch.paging.shadow.gl3e; /* First, make all four entries read-only. */ for ( i = 0; i < 4; i++ ) { @@ -3566,7 +3566,7 @@ sh_update_cr3(struct vcpu *v, int do_locking) #endif /// - /// v->arch.shadow.l3table + /// v->arch.paging.shadow.l3table /// #if SHADOW_PAGING_LEVELS == 3 { @@ -3581,7 +3581,7 @@ sh_update_cr3(struct vcpu *v, int do_locking) /* 3-on-3: make a PAE l3 that points at the four l2 pages */ smfn = pagetable_get_mfn(v->arch.shadow_table[i]); #endif - v->arch.shadow.l3table[i] = + v->arch.paging.shadow.l3table[i] = (mfn_x(smfn) == 0) ? shadow_l3e_empty() : shadow_l3e_from_mfn(smfn, _PAGE_PRESENT); @@ -3605,8 +3605,8 @@ sh_update_cr3(struct vcpu *v, int do_locking) /* 2-on-3 or 3-on-3: Use the PAE shadow l3 table we just fabricated. * Don't use make_cr3 because (a) we know it's below 4GB, and * (b) it's not necessarily page-aligned, and make_cr3 takes a pfn */ - ASSERT(virt_to_maddr(&v->arch.shadow.l3table) <= 0xffffffe0ULL); - v->arch.cr3 = virt_to_maddr(&v->arch.shadow.l3table); + ASSERT(virt_to_maddr(&v->arch.paging.shadow.l3table) <= 0xffffffe0ULL); + v->arch.cr3 = virt_to_maddr(&v->arch.paging.shadow.l3table); #else /* 2-on-2 or 4-on-4: Just use the shadow top-level directly */ make_cr3(v, pagetable_get_pfn(v->arch.shadow_table[0])); @@ -3622,7 +3622,7 @@ sh_update_cr3(struct vcpu *v, int do_locking) ASSERT(is_hvm_domain(d)); #if SHADOW_PAGING_LEVELS == 3 /* 2-on-3 or 3-on-3: Use the PAE shadow l3 table we just fabricated */ - hvm_update_guest_cr3(v, virt_to_maddr(&v->arch.shadow.l3table)); + hvm_update_guest_cr3(v, virt_to_maddr(&v->arch.paging.shadow.l3table)); #else /* 2-on-2 or 4-on-4: Just use the shadow top-level directly */ hvm_update_guest_cr3(v, pagetable_get_paddr(v->arch.shadow_table[0])); @@ -3665,7 +3665,7 @@ static int sh_guess_wrmap(struct vcpu *v, unsigned long vaddr, mfn_t gmfn) if ( !(shadow_l3e_get_flags(*sl3p) & _PAGE_PRESENT) ) return 0; #elif SHADOW_PAGING_LEVELS == 3 - sl3p = ((shadow_l3e_t *) v->arch.shadow.l3table) + sl3p = ((shadow_l3e_t *) v->arch.paging.shadow.l3table) + shadow_l3_linear_offset(vaddr); if ( !(shadow_l3e_get_flags(*sl3p) & _PAGE_PRESENT) ) return 0; @@ -3709,7 +3709,7 @@ int sh_rm_write_access_from_l1(struct vcpu *v, mfn_t sl1mfn, (void) shadow_set_l1e(v, sl1e, ro_sl1e, sl1mfn); #if SHADOW_OPTIMIZATIONS & SHOPT_WRITABLE_HEURISTIC /* Remember the last shadow that we shot a writeable mapping in */ - v->arch.shadow.last_writeable_pte_smfn = mfn_x(base_sl1mfn); + v->arch.paging.shadow.last_writeable_pte_smfn = mfn_x(base_sl1mfn); #endif if ( (mfn_to_page(readonly_mfn)->u.inuse.type_info & PGT_count_mask) == 0 ) @@ -3875,11 +3875,9 @@ static inline void * emulate_map_dest(struct vcpu *v, goto page_fault; } - /* Attempted a write to a bad gfn? This should never happen: - * after all, we're here because this write is to a page table. */ - BUG_ON(!mfn_valid(mfn)); + if ( !mfn_valid(mfn) ) + return NULL; - ASSERT(sh_mfn_is_a_page_table(mfn)); *mfnp = mfn; return sh_map_domain_page(mfn) + (vaddr & ~PAGE_MASK); @@ -4052,8 +4050,8 @@ sh_x86_emulate_cmpxchg8b(struct vcpu *v, unsigned long vaddr, #define AUDIT_FAIL(_level, _fmt, _a...) do { \ printk("Shadow %u-on-%u audit failed at level %i, index %i\n" \ - "gl" #_level "mfn = %" SH_PRI_mfn \ - " sl" #_level "mfn = %" SH_PRI_mfn \ + "gl" #_level "mfn = %" PRI_mfn \ + " sl" #_level "mfn = %" PRI_mfn \ " &gl" #_level "e = %p &sl" #_level "e = %p" \ " gl" #_level "e = %" SH_PRI_gpte \ " sl" #_level "e = %" SH_PRI_pte "\nError: " _fmt "\n", \ @@ -4107,7 +4105,7 @@ audit_gfn_to_mfn(struct vcpu *v, gfn_t gfn, mfn_t gmfn) != PGT_writable_page ) return _mfn(gfn_x(gfn)); /* This is a paging-disabled shadow */ else - return sh_gfn_to_mfn(v->domain, gfn_x(gfn)); + return gfn_to_mfn(v->domain, gfn_x(gfn)); } @@ -4158,7 +4156,7 @@ int sh_audit_l1_table(struct vcpu *v, mfn_t sl1mfn, mfn_t x) gmfn = audit_gfn_to_mfn(v, gfn, gl1mfn); if ( mfn_x(gmfn) != mfn_x(mfn) ) AUDIT_FAIL(1, "bad translation: gfn %" SH_PRI_gfn - " --> %" SH_PRI_mfn " != mfn %" SH_PRI_mfn, + " --> %" PRI_mfn " != mfn %" PRI_mfn, gfn_x(gfn), mfn_x(gmfn), mfn_x(mfn)); } } @@ -4221,8 +4219,8 @@ int sh_audit_l2_table(struct vcpu *v, mfn_t sl2mfn, mfn_t x) SH_type_l1_shadow); if ( mfn_x(gmfn) != mfn_x(mfn) ) AUDIT_FAIL(2, "bad translation: gfn %" SH_PRI_gfn - " (--> %" SH_PRI_mfn ")" - " --> %" SH_PRI_mfn " != mfn %" SH_PRI_mfn, + " (--> %" PRI_mfn ")" + " --> %" PRI_mfn " != mfn %" PRI_mfn, gfn_x(gfn), (guest_l2e_get_flags(*gl2e) & _PAGE_PSE) ? 0 : mfn_x(audit_gfn_to_mfn(v, gfn, gl2mfn)), @@ -4264,7 +4262,7 @@ int sh_audit_l3_table(struct vcpu *v, mfn_t sl3mfn, mfn_t x) : SH_type_l2_shadow); if ( mfn_x(gmfn) != mfn_x(mfn) ) AUDIT_FAIL(3, "bad translation: gfn %" SH_PRI_gfn - " --> %" SH_PRI_mfn " != mfn %" SH_PRI_mfn, + " --> %" PRI_mfn " != mfn %" PRI_mfn, gfn_x(gfn), mfn_x(gmfn), mfn_x(mfn)); } }); @@ -4299,7 +4297,7 @@ int sh_audit_l4_table(struct vcpu *v, mfn_t sl4mfn, mfn_t x) SH_type_l3_shadow); if ( mfn_x(gmfn) != mfn_x(mfn) ) AUDIT_FAIL(4, "bad translation: gfn %" SH_PRI_gfn - " --> %" SH_PRI_mfn " != mfn %" SH_PRI_mfn, + " --> %" PRI_mfn " != mfn %" PRI_mfn, gfn_x(gfn), mfn_x(gmfn), mfn_x(mfn)); } }); @@ -4316,30 +4314,29 @@ int sh_audit_l4_table(struct vcpu *v, mfn_t sl4mfn, mfn_t x) /**************************************************************************/ /* Entry points into this mode of the shadow code. * This will all be mangled by the preprocessor to uniquify everything. */ -struct shadow_paging_mode sh_paging_mode = { - .page_fault = sh_page_fault, - .invlpg = sh_invlpg, - .gva_to_gpa = sh_gva_to_gpa, - .gva_to_gfn = sh_gva_to_gfn, - .update_cr3 = sh_update_cr3, - .map_and_validate_gl1e = sh_map_and_validate_gl1e, - .map_and_validate_gl2e = sh_map_and_validate_gl2e, - .map_and_validate_gl2he = sh_map_and_validate_gl2he, - .map_and_validate_gl3e = sh_map_and_validate_gl3e, - .map_and_validate_gl4e = sh_map_and_validate_gl4e, - .detach_old_tables = sh_detach_old_tables, - .x86_emulate_write = sh_x86_emulate_write, - .x86_emulate_cmpxchg = sh_x86_emulate_cmpxchg, - .x86_emulate_cmpxchg8b = sh_x86_emulate_cmpxchg8b, - .make_monitor_table = sh_make_monitor_table, - .destroy_monitor_table = sh_destroy_monitor_table, - .guest_map_l1e = sh_guest_map_l1e, - .guest_get_eff_l1e = sh_guest_get_eff_l1e, +struct paging_mode sh_paging_mode = { + .page_fault = sh_page_fault, + .invlpg = sh_invlpg, + .gva_to_gpa = sh_gva_to_gpa, + .gva_to_gfn = sh_gva_to_gfn, + .update_cr3 = sh_update_cr3, + .update_paging_modes = shadow_update_paging_modes, + .write_p2m_entry = shadow_write_p2m_entry, + .write_guest_entry = shadow_write_guest_entry, + .cmpxchg_guest_entry = shadow_cmpxchg_guest_entry, + .guest_map_l1e = sh_guest_map_l1e, + .guest_get_eff_l1e = sh_guest_get_eff_l1e, + .guest_levels = GUEST_PAGING_LEVELS, + .shadow.detach_old_tables = sh_detach_old_tables, + .shadow.x86_emulate_write = sh_x86_emulate_write, + .shadow.x86_emulate_cmpxchg = sh_x86_emulate_cmpxchg, + .shadow.x86_emulate_cmpxchg8b = sh_x86_emulate_cmpxchg8b, + .shadow.make_monitor_table = sh_make_monitor_table, + .shadow.destroy_monitor_table = sh_destroy_monitor_table, #if SHADOW_OPTIMIZATIONS & SHOPT_WRITABLE_HEURISTIC - .guess_wrmap = sh_guess_wrmap, + .shadow.guess_wrmap = sh_guess_wrmap, #endif - .guest_levels = GUEST_PAGING_LEVELS, - .shadow_levels = SHADOW_PAGING_LEVELS, + .shadow.shadow_levels = SHADOW_PAGING_LEVELS, }; /* diff --git a/xen/arch/x86/mm/shadow/multi.h b/xen/arch/x86/mm/shadow/multi.h index 97903059d4..323c0c7e64 100644 --- a/xen/arch/x86/mm/shadow/multi.h +++ b/xen/arch/x86/mm/shadow/multi.h @@ -115,5 +115,5 @@ SHADOW_INTERNAL_NAME(sh_destroy_monitor_table, SHADOW_LEVELS, GUEST_LEVELS) (struct vcpu *v, mfn_t mmfn); #endif -extern struct shadow_paging_mode +extern struct paging_mode SHADOW_INTERNAL_NAME(sh_paging_mode, SHADOW_LEVELS, GUEST_LEVELS); diff --git a/xen/arch/x86/mm/shadow/page-guest32.h b/xen/arch/x86/mm/shadow/page-guest32.h index e93206169a..5d333bd91b 100644 --- a/xen/arch/x86/mm/shadow/page-guest32.h +++ b/xen/arch/x86/mm/shadow/page-guest32.h @@ -87,11 +87,6 @@ static inline l2_pgentry_32_t l2e_from_paddr_32(paddr_t pa, unsigned int flags) #define l2_table_offset_32(a) \ (((a) >> L2_PAGETABLE_SHIFT_32) & (L2_PAGETABLE_ENTRIES_32 - 1)) -#define linear_l1_table_32 \ - ((l1_pgentry_32_t *)(LINEAR_PT_VIRT_START)) - -#define linear_pg_table_32 linear_l1_table_32 - #endif /* __X86_PAGE_GUEST_H__ */ /* diff --git a/xen/arch/x86/mm/shadow/private.h b/xen/arch/x86/mm/shadow/private.h index 21d78eb2de..44c0c37c47 100644 --- a/xen/arch/x86/mm/shadow/private.h +++ b/xen/arch/x86/mm/shadow/private.h @@ -41,13 +41,12 @@ #define SHADOW_AUDIT_ENTRIES 0x04 /* Check this walk's shadows */ #define SHADOW_AUDIT_ENTRIES_FULL 0x08 /* Check every shadow */ #define SHADOW_AUDIT_ENTRIES_MFNS 0x10 /* Check gfn-mfn map in shadows */ -#define SHADOW_AUDIT_P2M 0x20 /* Check the p2m table */ #ifdef NDEBUG #define SHADOW_AUDIT 0 #define SHADOW_AUDIT_ENABLE 0 #else -#define SHADOW_AUDIT 0x15 /* Basic audit of all except p2m. */ +#define SHADOW_AUDIT 0x15 /* Basic audit of all */ #define SHADOW_AUDIT_ENABLE shadow_audit_enable extern int shadow_audit_enable; #endif @@ -84,9 +83,9 @@ extern int shadow_audit_enable; #define SHADOW_DEBUG_PROPAGATE 1 #define SHADOW_DEBUG_MAKE_SHADOW 1 #define SHADOW_DEBUG_DESTROY_SHADOW 1 -#define SHADOW_DEBUG_P2M 0 #define SHADOW_DEBUG_A_AND_D 1 #define SHADOW_DEBUG_EMULATE 1 +#define SHADOW_DEBUG_P2M 1 #define SHADOW_DEBUG_LOGDIRTY 0 /****************************************************************************** @@ -108,36 +107,36 @@ extern int shadow_audit_enable; #error shadow.h currently requires CONFIG_SMP #endif -#define shadow_lock_init(_d) \ - do { \ - spin_lock_init(&(_d)->arch.shadow.lock); \ - (_d)->arch.shadow.locker = -1; \ - (_d)->arch.shadow.locker_function = "nobody"; \ +#define shadow_lock_init(_d) \ + do { \ + spin_lock_init(&(_d)->arch.paging.shadow.lock); \ + (_d)->arch.paging.shadow.locker = -1; \ + (_d)->arch.paging.shadow.locker_function = "nobody"; \ } while (0) #define shadow_locked_by_me(_d) \ - (current->processor == (_d)->arch.shadow.locker) + (current->processor == (_d)->arch.paging.shadow.locker) -#define shadow_lock(_d) \ - do { \ - if ( unlikely((_d)->arch.shadow.locker == current->processor) ) \ - { \ - printk("Error: shadow lock held by %s\n", \ - (_d)->arch.shadow.locker_function); \ - BUG(); \ - } \ - spin_lock(&(_d)->arch.shadow.lock); \ - ASSERT((_d)->arch.shadow.locker == -1); \ - (_d)->arch.shadow.locker = current->processor; \ - (_d)->arch.shadow.locker_function = __func__; \ +#define shadow_lock(_d) \ + do { \ + if ( unlikely((_d)->arch.paging.shadow.locker == current->processor) )\ + { \ + printk("Error: shadow lock held by %s\n", \ + (_d)->arch.paging.shadow.locker_function); \ + BUG(); \ + } \ + spin_lock(&(_d)->arch.paging.shadow.lock); \ + ASSERT((_d)->arch.paging.shadow.locker == -1); \ + (_d)->arch.paging.shadow.locker = current->processor; \ + (_d)->arch.paging.shadow.locker_function = __func__; \ } while (0) -#define shadow_unlock(_d) \ - do { \ - ASSERT((_d)->arch.shadow.locker == current->processor); \ - (_d)->arch.shadow.locker = -1; \ - (_d)->arch.shadow.locker_function = "nobody"; \ - spin_unlock(&(_d)->arch.shadow.lock); \ +#define shadow_unlock(_d) \ + do { \ + ASSERT((_d)->arch.paging.shadow.locker == current->processor); \ + (_d)->arch.paging.shadow.locker = -1; \ + (_d)->arch.paging.shadow.locker_function = "nobody"; \ + spin_unlock(&(_d)->arch.paging.shadow.lock); \ } while (0) @@ -152,13 +151,6 @@ extern void shadow_audit_tables(struct vcpu *v); #define shadow_audit_tables(_v) do {} while(0) #endif -#if SHADOW_AUDIT & SHADOW_AUDIT_P2M -extern void shadow_audit_p2m(struct domain *d); -#else -#define shadow_audit_p2m(_d) do {} while(0) -#endif - - /****************************************************************************** * Macro for dealing with the naming of the internal names of the * shadow code's external entry points. @@ -304,7 +296,7 @@ static inline int sh_type_is_pinnable(struct vcpu *v, unsigned int t) * page. When we're shadowing those kernels, we have to pin l3 * shadows so they don't just evaporate on every context switch. * For all other guests, we'd rather use the up-pointer field in l3s. */ - if ( unlikely((v->domain->arch.shadow.opt_flags & SHOPT_LINUX_L3_TOPLEVEL) + if ( unlikely((v->domain->arch.paging.shadow.opt_flags & SHOPT_LINUX_L3_TOPLEVEL) && CONFIG_PAGING_LEVELS >= 4 && t == SH_type_l3_64_shadow) ) return 1; @@ -379,12 +371,11 @@ void sh_install_xen_entries_in_l2h(struct vcpu *v, mfn_t sl2hmfn); void sh_install_xen_entries_in_l2(struct vcpu *v, mfn_t gl2mfn, mfn_t sl2mfn); /* Update the shadows in response to a pagetable write from Xen */ -extern int sh_validate_guest_entry(struct vcpu *v, mfn_t gmfn, - void *entry, u32 size); +int sh_validate_guest_entry(struct vcpu *v, mfn_t gmfn, void *entry, u32 size); /* Update the shadows in response to a pagetable write from a HVM guest */ -extern void sh_validate_guest_pt_write(struct vcpu *v, mfn_t gmfn, - void *entry, u32 size); +void sh_validate_guest_pt_write(struct vcpu *v, mfn_t gmfn, + void *entry, u32 size); /* Remove all writeable mappings of a guest frame from the shadows. * Returns non-zero if we need to flush TLBs. @@ -394,6 +385,21 @@ extern int sh_remove_write_access(struct vcpu *v, mfn_t readonly_mfn, unsigned int level, unsigned long fault_addr); +/* Allocate/free functions for passing to the P2M code. */ +struct page_info *shadow_alloc_p2m_page(struct domain *d); +void shadow_free_p2m_page(struct domain *d, struct page_info *pg); + +/* Functions that atomically write PT/P2M entries and update state */ +void shadow_write_p2m_entry(struct vcpu *v, unsigned long gfn, + l1_pgentry_t *p, l1_pgentry_t new, + unsigned int level); +int shadow_write_guest_entry(struct vcpu *v, intpte_t *p, + intpte_t new, mfn_t gmfn); +int shadow_cmpxchg_guest_entry(struct vcpu *v, intpte_t *p, + intpte_t *old, intpte_t new, mfn_t gmfn); + + + /****************************************************************************** * Flags used in the return value of the shadow_set_lXe() functions... */ @@ -477,19 +483,6 @@ sh_unmap_domain_page_global(void *p) unmap_domain_page_global(p); } -static inline mfn_t -pagetable_get_mfn(pagetable_t pt) -{ - return _mfn(pagetable_get_pfn(pt)); -} - -static inline pagetable_t -pagetable_from_mfn(mfn_t mfn) -{ - return pagetable_from_pfn(mfn_x(mfn)); -} - - /****************************************************************************** * Log-dirty mode bitmap handling */ @@ -502,13 +495,13 @@ sh_mfn_is_dirty(struct domain *d, mfn_t gmfn) { unsigned long pfn; ASSERT(shadow_mode_log_dirty(d)); - ASSERT(d->arch.shadow.dirty_bitmap != NULL); + ASSERT(d->arch.paging.shadow.dirty_bitmap != NULL); /* We /really/ mean PFN here, even for non-translated guests. */ pfn = get_gpfn_from_mfn(mfn_x(gmfn)); if ( likely(VALID_M2P(pfn)) - && likely(pfn < d->arch.shadow.dirty_bitmap_size) - && test_bit(pfn, d->arch.shadow.dirty_bitmap) ) + && likely(pfn < d->arch.paging.shadow.dirty_bitmap_size) + && test_bit(pfn, d->arch.paging.shadow.dirty_bitmap) ) return 1; return 0; @@ -612,7 +605,7 @@ static inline int sh_pin(struct vcpu *v, mfn_t smfn) sp->pinned = 1; } /* Put it at the head of the list of pinned shadows */ - list_add(&sp->list, &v->domain->arch.shadow.pinned_shadows); + list_add(&sp->list, &v->domain->arch.paging.shadow.pinned_shadows); return 1; } diff --git a/xen/arch/x86/mm/shadow/types.h b/xen/arch/x86/mm/shadow/types.h index e2edebe555..48670c31c1 100644 --- a/xen/arch/x86/mm/shadow/types.h +++ b/xen/arch/x86/mm/shadow/types.h @@ -414,15 +414,9 @@ valid_gfn(gfn_t m) static inline mfn_t vcpu_gfn_to_mfn(struct vcpu *v, gfn_t gfn) { - if ( !shadow_vcpu_mode_translate(v) ) + if ( !paging_vcpu_mode_translate(v) ) return _mfn(gfn_x(gfn)); - return sh_gfn_to_mfn(v->domain, gfn_x(gfn)); -} - -static inline gfn_t -mfn_to_gfn(struct domain *d, mfn_t mfn) -{ - return _gfn(sh_mfn_to_gfn(d, mfn)); + return gfn_to_mfn(v->domain, gfn_x(gfn)); } static inline paddr_t @@ -453,10 +447,8 @@ struct shadow_walk_t guest_l2e_t *l2e; /* Pointer to guest's level 2 entry */ guest_l1e_t *l1e; /* Pointer to guest's level 1 entry */ guest_l1e_t eff_l1e; /* Effective level 1 entry */ -#if GUEST_PAGING_LEVELS >= 3 #if GUEST_PAGING_LEVELS >= 4 mfn_t l4mfn; /* MFN that the level 4 entry is in */ -#endif mfn_t l3mfn; /* MFN that the level 3 entry is in */ #endif mfn_t l2mfn; /* MFN that the level 2 entry is in */ diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index 0e010e2724..bb15e9b955 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/xen/arch/x86/sysctl.c b/xen/arch/x86/sysctl.c index 0f265825bd..fe4c049908 100644 --- a/xen/arch/x86/sysctl.c +++ b/xen/arch/x86/sysctl.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index dfa22bce04..83be2a3032 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -46,7 +46,7 @@ #include #include #include -#include +#include #include #include #include @@ -860,8 +860,8 @@ static int fixup_page_fault(unsigned long addr, struct cpu_user_regs *regs) if ( unlikely(IN_HYPERVISOR_RANGE(addr)) ) { - if ( shadow_mode_external(d) && guest_mode(regs) ) - return shadow_fault(addr, regs); + if ( paging_mode_external(d) && guest_mode(regs) ) + return paging_fault(addr, regs); if ( (addr >= GDT_LDT_VIRT_START) && (addr < GDT_LDT_VIRT_END) ) return handle_gdt_ldt_mapping_fault( addr - GDT_LDT_VIRT_START, regs); @@ -876,8 +876,8 @@ static int fixup_page_fault(unsigned long addr, struct cpu_user_regs *regs) ptwr_do_page_fault(v, addr, regs) ) return EXCRET_fault_fixed; - if ( shadow_mode_enabled(d) ) - return shadow_fault(addr, regs); + if ( paging_mode_enabled(d) ) + return paging_fault(addr, regs); return 0; } diff --git a/xen/arch/x86/x86_32/domain_page.c b/xen/arch/x86/x86_32/domain_page.c index 9080de1a87..cb414df253 100644 --- a/xen/arch/x86/x86_32/domain_page.c +++ b/xen/arch/x86/x86_32/domain_page.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/xen/arch/x86/x86_32/entry.S b/xen/arch/x86/x86_32/entry.S index 454e963fe3..286c4b5fb7 100644 --- a/xen/arch/x86/x86_32/entry.S +++ b/xen/arch/x86/x86_32/entry.S @@ -84,10 +84,10 @@ restore_all_guest: jmp restore_all_vm86 1: #endif -FLT1: mov UREGS_ds(%esp),%ds -FLT2: mov UREGS_es(%esp),%es -FLT3: mov UREGS_fs(%esp),%fs -FLT4: mov UREGS_gs(%esp),%gs +.Lft1: mov UREGS_ds(%esp),%ds +.Lft2: mov UREGS_es(%esp),%es +.Lft3: mov UREGS_fs(%esp),%fs +.Lft4: mov UREGS_gs(%esp),%gs restore_all_vm86: popl %ebx popl %ecx @@ -97,9 +97,9 @@ restore_all_vm86: popl %ebp popl %eax addl $4,%esp -FLT5: iret +.Lft5: iret .section .fixup,"ax" -FIX5: subl $28,%esp +.Lfx5: subl $28,%esp pushl 28(%esp) # error_code/entry_vector movl %eax,UREGS_eax+4(%esp) movl %ebp,UREGS_ebp+4(%esp) @@ -108,7 +108,7 @@ FIX5: subl $28,%esp movl %edx,UREGS_edx+4(%esp) movl %ecx,UREGS_ecx+4(%esp) movl %ebx,UREGS_ebx+4(%esp) -FIX1: SET_XEN_SEGMENTS(a) +.Lfx1: SET_XEN_SEGMENTS(a) movl %eax,%fs movl %eax,%gs sti @@ -116,11 +116,11 @@ FIX1: SET_XEN_SEGMENTS(a) pushfl # EFLAGS movl $__HYPERVISOR_CS,%eax pushl %eax # CS - movl $DBLFLT1,%eax + movl $.Ldf1,%eax pushl %eax # EIP pushl %esi # error_code/entry_vector jmp handle_exception -DBLFLT1:GET_CURRENT(%ebx) +.Ldf1: GET_CURRENT(%ebx) jmp test_all_events failsafe_callback: GET_CURRENT(%ebx) @@ -142,14 +142,14 @@ failsafe_callback: jmp test_all_events .previous .section __pre_ex_table,"a" - .long FLT1,FIX1 - .long FLT2,FIX1 - .long FLT3,FIX1 - .long FLT4,FIX1 - .long FLT5,FIX5 + .long .Lft1,.Lfx1 + .long .Lft2,.Lfx1 + .long .Lft3,.Lfx1 + .long .Lft4,.Lfx1 + .long .Lft5,.Lfx5 .previous .section __ex_table,"a" - .long DBLFLT1,failsafe_callback + .long .Ldf1,failsafe_callback .previous ALIGN @@ -288,32 +288,33 @@ create_bounce_frame: testl $(2|X86_EFLAGS_VM),%ecx jz ring1 /* jump if returning to an existing ring-1 activation */ movl VCPU_kernel_sp(%ebx),%esi -FLT6: mov VCPU_kernel_ss(%ebx),%gs +.Lft6: mov VCPU_kernel_ss(%ebx),%gs testl $X86_EFLAGS_VM,UREGS_eflags+4(%esp) - jz nvm86_1 + jz .Lnvm86_1 subl $16,%esi /* push ES/DS/FS/GS (VM86 stack frame) */ movl UREGS_es+4(%esp),%eax -FLT7: movl %eax,%gs:(%esi) +.Lft7: movl %eax,%gs:(%esi) movl UREGS_ds+4(%esp),%eax -FLT8: movl %eax,%gs:4(%esi) +.Lft8: movl %eax,%gs:4(%esi) movl UREGS_fs+4(%esp),%eax -FLT9: movl %eax,%gs:8(%esi) +.Lft9: movl %eax,%gs:8(%esi) movl UREGS_gs+4(%esp),%eax -FLT10: movl %eax,%gs:12(%esi) -nvm86_1:subl $8,%esi /* push SS/ESP (inter-priv iret) */ +.Lft10: movl %eax,%gs:12(%esi) +.Lnvm86_1: + subl $8,%esi /* push SS/ESP (inter-priv iret) */ movl UREGS_esp+4(%esp),%eax -FLT11: movl %eax,%gs:(%esi) +.Lft11: movl %eax,%gs:(%esi) movl UREGS_ss+4(%esp),%eax -FLT12: movl %eax,%gs:4(%esi) +.Lft12: movl %eax,%gs:4(%esi) jmp 1f ring1: /* obtain ss/esp from oldss/oldesp -- a ring-1 activation exists */ movl UREGS_esp+4(%esp),%esi -FLT13: mov UREGS_ss+4(%esp),%gs +.Lft13: mov UREGS_ss+4(%esp),%gs 1: /* Construct a stack frame: EFLAGS, CS/EIP */ movb TRAPBOUNCE_flags(%edx),%cl subl $12,%esi movl UREGS_eip+4(%esp),%eax -FLT14: movl %eax,%gs:(%esi) +.Lft14: movl %eax,%gs:(%esi) movl VCPU_vcpu_info(%ebx),%eax pushl VCPUINFO_upcall_mask(%eax) testb $TBF_INTERRUPT,%cl @@ -324,49 +325,51 @@ FLT14: movl %eax,%gs:(%esi) movw UREGS_cs+4(%esp),%ax # Bits 0-15: CS #ifdef CONFIG_X86_SUPERVISOR_MODE_KERNEL testw $2,%ax - jnz FLT15 + jnz .Lft15 and $~3,%ax # RPL 1 -> RPL 0 #endif -FLT15: movl %eax,%gs:4(%esi) +.Lft15: movl %eax,%gs:4(%esi) test $0x00FF0000,%eax # Bits 16-23: saved_upcall_mask setz %ch # %ch == !saved_upcall_mask movl UREGS_eflags+4(%esp),%eax andl $~X86_EFLAGS_IF,%eax shlb $1,%ch # Bit 9 (EFLAGS.IF) orb %ch,%ah # Fold EFLAGS.IF into %eax -FLT16: movl %eax,%gs:8(%esi) +.Lft16: movl %eax,%gs:8(%esi) test $TBF_EXCEPTION_ERRCODE,%cl jz 1f subl $4,%esi # push error_code onto guest frame movl TRAPBOUNCE_error_code(%edx),%eax -FLT17: movl %eax,%gs:(%esi) +.Lft17: movl %eax,%gs:(%esi) 1: testb $TBF_FAILSAFE,%cl jz 2f subl $16,%esi # add DS/ES/FS/GS to failsafe stack frame testl $X86_EFLAGS_VM,UREGS_eflags+4(%esp) - jz nvm86_2 + jz .Lnvm86_2 xorl %eax,%eax # VM86: we write zero selector values -FLT18: movl %eax,%gs:(%esi) -FLT19: movl %eax,%gs:4(%esi) -FLT20: movl %eax,%gs:8(%esi) -FLT21: movl %eax,%gs:12(%esi) +.Lft18: movl %eax,%gs:(%esi) +.Lft19: movl %eax,%gs:4(%esi) +.Lft20: movl %eax,%gs:8(%esi) +.Lft21: movl %eax,%gs:12(%esi) jmp 2f -nvm86_2:movl UREGS_ds+4(%esp),%eax # non-VM86: write real selector values -FLT22: movl %eax,%gs:(%esi) +.Lnvm86_2: + movl UREGS_ds+4(%esp),%eax # non-VM86: write real selector values +.Lft22: movl %eax,%gs:(%esi) movl UREGS_es+4(%esp),%eax -FLT23: movl %eax,%gs:4(%esi) +.Lft23: movl %eax,%gs:4(%esi) movl UREGS_fs+4(%esp),%eax -FLT24: movl %eax,%gs:8(%esi) +.Lft24: movl %eax,%gs:8(%esi) movl UREGS_gs+4(%esp),%eax -FLT25: movl %eax,%gs:12(%esi) +.Lft25: movl %eax,%gs:12(%esi) 2: testl $X86_EFLAGS_VM,UREGS_eflags+4(%esp) - jz nvm86_3 + jz .Lnvm86_3 xorl %eax,%eax /* zero DS-GS, just as a real CPU would */ movl %eax,UREGS_ds+4(%esp) movl %eax,UREGS_es+4(%esp) movl %eax,UREGS_fs+4(%esp) movl %eax,UREGS_gs+4(%esp) -nvm86_3:/* Rewrite our stack frame and return to ring 1. */ +.Lnvm86_3: + /* Rewrite our stack frame and return to ring 1. */ /* IA32 Ref. Vol. 3: TF, VM, RF and NT flags are cleared on trap. */ andl $~(X86_EFLAGS_VM|X86_EFLAGS_RF|\ X86_EFLAGS_NT|X86_EFLAGS_TF),UREGS_eflags+4(%esp) @@ -382,16 +385,16 @@ nvm86_3:/* Rewrite our stack frame and return to ring 1. */ movb $0,TRAPBOUNCE_flags(%edx) ret .section __ex_table,"a" - .long FLT6,domain_crash_synchronous , FLT7,domain_crash_synchronous - .long FLT8,domain_crash_synchronous , FLT9,domain_crash_synchronous - .long FLT10,domain_crash_synchronous , FLT11,domain_crash_synchronous - .long FLT12,domain_crash_synchronous , FLT13,domain_crash_synchronous - .long FLT14,domain_crash_synchronous , FLT15,domain_crash_synchronous - .long FLT16,domain_crash_synchronous , FLT17,domain_crash_synchronous - .long FLT18,domain_crash_synchronous , FLT19,domain_crash_synchronous - .long FLT20,domain_crash_synchronous , FLT21,domain_crash_synchronous - .long FLT22,domain_crash_synchronous , FLT23,domain_crash_synchronous - .long FLT24,domain_crash_synchronous , FLT25,domain_crash_synchronous + .long .Lft6,domain_crash_synchronous , .Lft7,domain_crash_synchronous + .long .Lft8,domain_crash_synchronous , .Lft9,domain_crash_synchronous + .long .Lft10,domain_crash_synchronous , .Lft11,domain_crash_synchronous + .long .Lft12,domain_crash_synchronous , .Lft13,domain_crash_synchronous + .long .Lft14,domain_crash_synchronous , .Lft15,domain_crash_synchronous + .long .Lft16,domain_crash_synchronous , .Lft17,domain_crash_synchronous + .long .Lft18,domain_crash_synchronous , .Lft19,domain_crash_synchronous + .long .Lft20,domain_crash_synchronous , .Lft21,domain_crash_synchronous + .long .Lft22,domain_crash_synchronous , .Lft23,domain_crash_synchronous + .long .Lft24,domain_crash_synchronous , .Lft25,domain_crash_synchronous .previous domain_crash_synchronous_string: diff --git a/xen/arch/x86/x86_64/Makefile b/xen/arch/x86/x86_64/Makefile index df5632e0a0..98f20a43c6 100644 --- a/xen/arch/x86/x86_64/Makefile +++ b/xen/arch/x86/x86_64/Makefile @@ -1,4 +1,7 @@ +subdir-y += compat + obj-y += entry.o +obj-y += compat_kexec.o obj-y += gpr_switch.o obj-y += mm.o obj-y += traps.o @@ -12,7 +15,6 @@ ifeq ($(CONFIG_COMPAT),y) # extra dependencies compat.o: ../compat.c domctl.o: ../domctl.c -entry.o: compat/entry.S mm.o: compat/mm.c physdev.o: ../physdev.c platform_hypercall.o: ../platform_hypercall.c diff --git a/xen/arch/x86/x86_64/compat/Makefile b/xen/arch/x86/x86_64/compat/Makefile new file mode 100644 index 0000000000..6547e0c737 --- /dev/null +++ b/xen/arch/x86/x86_64/compat/Makefile @@ -0,0 +1,2 @@ +obj-y += entry.o + diff --git a/xen/arch/x86/x86_64/compat/entry.S b/xen/arch/x86/x86_64/compat/entry.S index 070deec3d1..3f1d1b8d07 100644 --- a/xen/arch/x86/x86_64/compat/entry.S +++ b/xen/arch/x86/x86_64/compat/entry.S @@ -2,10 +2,27 @@ * Compatibility hypercall routines. */ +#include +#include +#include +#include +#include +#include #include +#include -.text +#define GET_GUEST_REGS(reg) \ + movq $~(STACK_SIZE-1),reg; \ + andq %rsp,reg; \ + orq $(STACK_SIZE-CPUINFO_sizeof),reg; +#define GET_CURRENT(reg) \ + movq $STACK_SIZE-8, reg; \ + orq %rsp, reg; \ + andq $~7,reg; \ + movq (reg),reg; + + ALIGN ENTRY(compat_hypercall) pushq $0 movl $TRAP_syscall,4(%rsp) @@ -62,7 +79,7 @@ compat_skip_clobber: movl %eax,UREGS_rax(%rsp) # save the return value /* %rbx: struct vcpu */ -compat_test_all_events: +ENTRY(compat_test_all_events) cli # tests must not race interrupts /*compat_test_softirqs:*/ movl VCPU_processor(%rbx),%eax @@ -123,10 +140,10 @@ compat_bad_hypercall: compat_restore_all_guest: RESTORE_ALL addq $8,%rsp -CFLT0: iretq +.Lft0: iretq .section .fixup,"ax" -CFIX0: popq -15*8-8(%rsp) # error_code/entry_vector +.Lfx0: popq -15*8-8(%rsp) # error_code/entry_vector SAVE_ALL # 15*8 bytes pushed movq -8(%rsp),%rsi # error_code/entry_vector sti # after stack abuse (-1024(%rsp)) @@ -135,11 +152,11 @@ CFIX0: popq -15*8-8(%rsp) # error_code/entry_vector pushq %rax # RSP pushfq # RFLAGS pushq $__HYPERVISOR_CS # CS - leaq CDBLFLT0(%rip),%rax + leaq .Ldf0(%rip),%rax pushq %rax # RIP pushq %rsi # error_code/entry_vector jmp handle_exception -CDBLFLT0:GET_CURRENT(%rbx) +.Ldf0: GET_CURRENT(%rbx) jmp compat_test_all_events compat_failsafe_callback: GET_CURRENT(%rbx) @@ -157,14 +174,14 @@ compat_failsafe_callback: jmp compat_test_all_events .previous .section __pre_ex_table,"a" - .quad CFLT0,CFIX0 + .quad .Lft0,.Lfx0 .previous .section __ex_table,"a" - .quad CDBLFLT0,compat_failsafe_callback + .quad .Ldf0,compat_failsafe_callback .previous /* %rdx: trap_bounce, %rbx: struct vcpu */ -compat_post_handle_exception: +ENTRY(compat_post_handle_exception) testb $TBF_EXCEPTION,TRAPBOUNCE_flags(%rdx) jz compat_test_all_events call compat_create_bounce_frame @@ -180,16 +197,16 @@ compat_create_bounce_frame: jz 1f /* Push new frame at registered guest-OS stack base. */ movl VCPU_kernel_sp(%rbx),%esi -CFLT1: mov VCPU_kernel_ss(%rbx),%fs +.Lft1: mov VCPU_kernel_ss(%rbx),%fs subl $2*4,%esi movl UREGS_rsp+8(%rsp),%eax -CFLT2: movl %eax,%fs:(%rsi) +.Lft2: movl %eax,%fs:(%rsi) movl UREGS_ss+8(%rsp),%eax -CFLT3: movl %eax,%fs:4(%rsi) +.Lft3: movl %eax,%fs:4(%rsi) jmp 2f 1: /* In kernel context already: push new frame at existing %rsp. */ movl UREGS_rsp+8(%rsp),%esi -CFLT4: mov UREGS_ss+8(%rsp),%fs +.Lft4: mov UREGS_ss+8(%rsp),%fs 2: movb TRAPBOUNCE_flags(%rdx),%cl subl $3*4,%esi @@ -201,7 +218,7 @@ CFLT4: mov UREGS_ss+8(%rsp),%fs popq %rax shll $16,%eax # Bits 16-23: saved_upcall_mask movw UREGS_cs+8(%rsp),%ax # Bits 0-15: CS -CFLT5: movl %eax,%fs:4(%rsi) # CS / saved_upcall_mask +.Lft5: movl %eax,%fs:4(%rsi) # CS / saved_upcall_mask shrl $16,%eax testb %al,%al # Bits 0-7: saved_upcall_mask setz %ch # %ch == !saved_upcall_mask @@ -209,25 +226,25 @@ CFLT5: movl %eax,%fs:4(%rsi) # CS / saved_upcall_mask andl $~X86_EFLAGS_IF,%eax shlb $1,%ch # Bit 9 (EFLAGS.IF) orb %ch,%ah # Fold EFLAGS.IF into %eax -CFLT6: movl %eax,%fs:2*4(%rsi) # EFLAGS +.Lft6: movl %eax,%fs:2*4(%rsi) # EFLAGS movl UREGS_rip+8(%rsp),%eax -CFLT7: movl %eax,%fs:(%rsi) # EIP +.Lft7: movl %eax,%fs:(%rsi) # EIP testb $TBF_EXCEPTION_ERRCODE,%cl jz 1f subl $4,%esi movl TRAPBOUNCE_error_code(%rdx),%eax -CFLT8: movl %eax,%fs:(%rsi) # ERROR CODE +.Lft8: movl %eax,%fs:(%rsi) # ERROR CODE 1: testb $TBF_FAILSAFE,%cl jz 2f subl $4*4,%esi movl %gs,%eax -CFLT9: movl %eax,%fs:3*4(%rsi) # GS -CFLT10: movl %edi,%fs:2*4(%rsi) # FS +.Lft9: movl %eax,%fs:3*4(%rsi) # GS +.Lft10: movl %edi,%fs:2*4(%rsi) # FS movl %es,%eax -CFLT11: movl %eax,%fs:1*4(%rsi) # ES +.Lft11: movl %eax,%fs:1*4(%rsi) # ES movl %ds,%eax -CFLT12: movl %eax,%fs:0*4(%rsi) # DS +.Lft12: movl %eax,%fs:0*4(%rsi) # DS 2: /* Rewrite our stack frame and return to guest-OS mode. */ /* IA32 Ref. Vol. 3: TF, VM, RF and NT flags are cleared on trap. */ @@ -236,7 +253,7 @@ CFLT12: movl %eax,%fs:0*4(%rsi) # DS X86_EFLAGS_NT|X86_EFLAGS_TF),UREGS_eflags+8(%rsp) mov %fs,UREGS_ss+8(%rsp) movl %esi,UREGS_rsp+8(%rsp) -CFLT13: mov %edi,%fs +.Lft13: mov %edi,%fs movzwl TRAPBOUNCE_cs(%rdx),%eax /* Null selectors (0-3) are not allowed. */ testl $~3,%eax @@ -247,18 +264,18 @@ CFLT13: mov %edi,%fs movb $0,TRAPBOUNCE_flags(%rdx) ret .section .fixup,"ax" -CFIX13: +.Lfx13: xorl %edi,%edi - jmp CFLT13 + jmp .Lft13 .previous .section __ex_table,"a" - .quad CFLT1,domain_crash_synchronous , CFLT2,compat_crash_page_fault - .quad CFLT3,compat_crash_page_fault_4 , CFLT4,domain_crash_synchronous - .quad CFLT5,compat_crash_page_fault_4 , CFLT6,compat_crash_page_fault_8 - .quad CFLT7,compat_crash_page_fault , CFLT8,compat_crash_page_fault - .quad CFLT9,compat_crash_page_fault_12, CFLT10,compat_crash_page_fault_8 - .quad CFLT11,compat_crash_page_fault_4 , CFLT12,compat_crash_page_fault - .quad CFLT13,CFIX13 + .quad .Lft1,domain_crash_synchronous , .Lft2,compat_crash_page_fault + .quad .Lft3,compat_crash_page_fault_4 , .Lft4,domain_crash_synchronous + .quad .Lft5,compat_crash_page_fault_4 , .Lft6,compat_crash_page_fault_8 + .quad .Lft7,compat_crash_page_fault , .Lft8,compat_crash_page_fault + .quad .Lft9,compat_crash_page_fault_12, .Lft10,compat_crash_page_fault_8 + .quad .Lft11,compat_crash_page_fault_4 , .Lft12,compat_crash_page_fault + .quad .Lft13,.Lfx13 .previous compat_crash_page_fault_12: @@ -268,17 +285,17 @@ compat_crash_page_fault_8: compat_crash_page_fault_4: addl $4,%esi compat_crash_page_fault: -CFLT14: mov %edi,%fs +.Lft14: mov %edi,%fs movl %esi,%edi call show_page_walk jmp domain_crash_synchronous .section .fixup,"ax" -CFIX14: +.Lfx14: xorl %edi,%edi - jmp CFLT14 + jmp .Lft14 .previous .section __ex_table,"a" - .quad CFLT14,CFIX14 + .quad .Lft14,.Lfx14 .previous .section .rodata, "a", @progbits diff --git a/xen/arch/x86/x86_64/compat_kexec.S b/xen/arch/x86/x86_64/compat_kexec.S new file mode 100644 index 0000000000..c06db6fc7e --- /dev/null +++ b/xen/arch/x86/x86_64/compat_kexec.S @@ -0,0 +1,126 @@ +/* + * Compatibility kexec handler. + */ + +#include + +#include +#include +#include + +.text + + .code64 + +ENTRY(compat_machine_kexec) + /* x86/64 x86/32 */ + /* %rdi - relocate_new_kernel_t CALL */ + /* %rsi - indirection page 4(%esp) */ + /* %rdx - page_list 8(%esp) */ + /* %rcx - start address 12(%esp) */ + /* cpu has pae 16(%esp) */ + + /* Shim the 64 bit page_list into a 32 bit page_list. */ + mov $12,%r9 + lea compat_page_list(%rip), %rbx +1: dec %r9 + movl (%rdx,%r9,8),%eax + movl %eax,(%rbx,%r9,4) + test %r9,%r9 + jnz 1b + + movq %rbx,%rdx + mov $__PAGE_OFFSET,%rbx + sub %rbx, %rdx + + /* + * Setup an identity mapped region in PML4[0] of idle page + * table. + */ + lea idle_pg_table_l3(%rip),%rax + sub %rbx,%rax + or $0x63,%rax + mov %rax, idle_pg_table(%rip) + + /* Switch to idle page table. */ + movq $(idle_pg_table - __PAGE_OFFSET), %rax + movq %rax, %cr3 + + /* Jump to low identity mapping in compatibility mode. */ + ljmp *compatibility_mode_far(%rip) + ud2 + +compatibility_mode_far: + .long compatibility_mode - __PAGE_OFFSET + .long __HYPERVISOR_CS32 + + .code32 + +compatibility_mode: + /* Setup some sane segments. */ + movl $__HYPERVISOR_DS32, %eax + movl %eax, %ds + movl %eax, %es + movl %eax, %fs + movl %eax, %gs + movl %eax, %ss + + /* Push arguments onto stack. */ + pushl $1 /* 16(%esp) - cpu has pae */ + pushl %ecx /* 12(%esp) - start address */ + pushl %edx /* 8(%esp) - page list */ + pushl %esi /* 4(%esp) - indirection page */ + pushl %edi /* 0(%esp) - CALL */ + + /* Disable paging and therefore leave 64 bit mode. */ + movl %cr0, %eax + andl $~X86_CR0_PG, %eax + movl %eax, %cr0 + + /* Switch to 32 bit page table. */ + movl $compat_pg_table - __PAGE_OFFSET, %eax + movl %eax, %cr3 + + /* Clear MSR_EFER[LME], disabling long mode */ + movl $MSR_EFER,%ecx + rdmsr + btcl $_EFER_LME,%eax + wrmsr + + /* Re-enable paging, but only 32 bit mode now. */ + movl %cr0, %eax + orl $X86_CR0_PG, %eax + movl %eax, %cr0 + + popl %eax + call *%eax + ud2 + +compat_page_list: + .fill 12,4,0 + + .align 32,0 + + /* + * These compat page tables contain an identity mapping of the + * first 1G of the physical address space. + */ +compat_pg_table: + .long compat_pg_table_l2 + 0*PAGE_SIZE + 0x01 - __PAGE_OFFSET, 0 + .long 0, 0 + .long 0, 0 + .long 0, 0 + + .align 4096,0 + +compat_pg_table_l2: + .macro identmap from=0, count=512 + .if \count-1 + identmap "(\from+0)","(\count/2)" + identmap "(\from+(0x200000*(\count/2)))","(\count/2)" + .else + .quad 0x00000000000000e3 + \from + .endif + .endm + + identmap diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S index 24f7ea6eb5..36b5c5e1ad 100644 --- a/xen/arch/x86/x86_64/entry.S +++ b/xen/arch/x86/x86_64/entry.S @@ -56,10 +56,10 @@ restore_all_guest: /* No special register assumptions. */ iret_exit_to_guest: addq $8,%rsp -FLT1: iretq +.Lft1: iretq .section .fixup,"ax" -FIX1: popq -15*8-8(%rsp) # error_code/entry_vector +.Lfx1: popq -15*8-8(%rsp) # error_code/entry_vector SAVE_ALL # 15*8 bytes pushed movq -8(%rsp),%rsi # error_code/entry_vector sti # after stack abuse (-1024(%rsp)) @@ -68,11 +68,11 @@ FIX1: popq -15*8-8(%rsp) # error_code/entry_vector pushq %rax # RSP pushf # RFLAGS pushq $__HYPERVISOR_CS # CS - leaq DBLFLT1(%rip),%rax + leaq .Ldf1(%rip),%rax pushq %rax # RIP pushq %rsi # error_code/entry_vector jmp handle_exception -DBLFLT1:GET_CURRENT(%rbx) +.Ldf1: GET_CURRENT(%rbx) jmp test_all_events failsafe_callback: GET_CURRENT(%rbx) @@ -87,10 +87,10 @@ failsafe_callback: jmp test_all_events .previous .section __pre_ex_table,"a" - .quad FLT1,FIX1 + .quad .Lft1,.Lfx1 .previous .section __ex_table,"a" - .quad DBLFLT1,failsafe_callback + .quad .Ldf1,failsafe_callback .previous ALIGN @@ -249,9 +249,9 @@ create_bounce_frame: 1: movb TRAPBOUNCE_flags(%rdx),%cl subq $40,%rsi movq UREGS_ss+8(%rsp),%rax -FLT2: movq %rax,32(%rsi) # SS +.Lft2: movq %rax,32(%rsi) # SS movq UREGS_rsp+8(%rsp),%rax -FLT3: movq %rax,24(%rsi) # RSP +.Lft3: movq %rax,24(%rsi) # RSP movq VCPU_vcpu_info(%rbx),%rax pushq VCPUINFO_upcall_mask(%rax) testb $TBF_INTERRUPT,%cl @@ -260,7 +260,7 @@ FLT3: movq %rax,24(%rsi) # RSP popq %rax shlq $32,%rax # Bits 32-39: saved_upcall_mask movw UREGS_cs+8(%rsp),%ax # Bits 0-15: CS -FLT4: movq %rax,8(%rsi) # CS / saved_upcall_mask +.Lft4: movq %rax,8(%rsi) # CS / saved_upcall_mask shrq $32,%rax testb $0xFF,%al # Bits 0-7: saved_upcall_mask setz %ch # %ch == !saved_upcall_mask @@ -268,30 +268,30 @@ FLT4: movq %rax,8(%rsi) # CS / saved_upcall_mask andq $~X86_EFLAGS_IF,%rax shlb $1,%ch # Bit 9 (EFLAGS.IF) orb %ch,%ah # Fold EFLAGS.IF into %eax -FLT5: movq %rax,16(%rsi) # RFLAGS +.Lft5: movq %rax,16(%rsi) # RFLAGS movq UREGS_rip+8(%rsp),%rax -FLT6: movq %rax,(%rsi) # RIP +.Lft6: movq %rax,(%rsi) # RIP testb $TBF_EXCEPTION_ERRCODE,%cl jz 1f subq $8,%rsi movl TRAPBOUNCE_error_code(%rdx),%eax -FLT7: movq %rax,(%rsi) # ERROR CODE +.Lft7: movq %rax,(%rsi) # ERROR CODE 1: testb $TBF_FAILSAFE,%cl jz 2f subq $32,%rsi movl %gs,%eax -FLT8: movq %rax,24(%rsi) # GS +.Lft8: movq %rax,24(%rsi) # GS movl %fs,%eax -FLT9: movq %rax,16(%rsi) # FS +.Lft9: movq %rax,16(%rsi) # FS movl %es,%eax -FLT10: movq %rax,8(%rsi) # ES +.Lft10: movq %rax,8(%rsi) # ES movl %ds,%eax -FLT11: movq %rax,(%rsi) # DS +.Lft11: movq %rax,(%rsi) # DS 2: subq $16,%rsi movq UREGS_r11+8(%rsp),%rax -FLT12: movq %rax,8(%rsi) # R11 +.Lft12: movq %rax,8(%rsi) # R11 movq UREGS_rcx+8(%rsp),%rax -FLT13: movq %rax,(%rsi) # RCX +.Lft13: movq %rax,(%rsi) # RCX /* Rewrite our stack frame and return to guest-OS mode. */ /* IA32 Ref. Vol. 3: TF, VM, RF and NT flags are cleared on trap. */ /* Also clear AC: alignment checks shouldn't trigger in kernel mode. */ @@ -308,18 +308,18 @@ FLT13: movq %rax,(%rsi) # RCX movb $0,TRAPBOUNCE_flags(%rdx) ret .section __ex_table,"a" - .quad FLT2,domain_crash_synchronous , FLT3,domain_crash_synchronous - .quad FLT4,domain_crash_synchronous , FLT5,domain_crash_synchronous - .quad FLT6,domain_crash_synchronous , FLT7,domain_crash_synchronous - .quad FLT8,domain_crash_synchronous , FLT9,domain_crash_synchronous - .quad FLT10,domain_crash_synchronous , FLT11,domain_crash_synchronous - .quad FLT12,domain_crash_synchronous , FLT13,domain_crash_synchronous + .quad .Lft2,domain_crash_synchronous , .Lft3,domain_crash_synchronous + .quad .Lft4,domain_crash_synchronous , .Lft5,domain_crash_synchronous + .quad .Lft6,domain_crash_synchronous , .Lft7,domain_crash_synchronous + .quad .Lft8,domain_crash_synchronous , .Lft9,domain_crash_synchronous + .quad .Lft10,domain_crash_synchronous , .Lft11,domain_crash_synchronous + .quad .Lft12,domain_crash_synchronous , .Lft13,domain_crash_synchronous .previous domain_crash_synchronous_string: .asciz "domain_crash_sync called from entry.S\n" -domain_crash_synchronous: +ENTRY(domain_crash_synchronous) # Get out of the guest-save area of the stack. GET_GUEST_REGS(%rax) movq %rax,%rsp @@ -357,7 +357,7 @@ ENTRY(ret_from_intr) ALIGN /* No special register assumptions. */ -handle_exception: +ENTRY(handle_exception) SAVE_ALL testb $X86_EFLAGS_IF>>8,UREGS_eflags+1(%rsp) jz exception_with_ints_disabled @@ -633,7 +633,3 @@ ENTRY(hypercall_args_table) .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr - -#ifdef CONFIG_COMPAT -#include "compat/entry.S" -#endif diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c index 65d9c427dc..0c6ee1de35 100644 --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include diff --git a/xen/common/kexec.c b/xen/common/kexec.c index a9e85cad7f..80314a6673 100644 --- a/xen/common/kexec.c +++ b/xen/common/kexec.c @@ -6,7 +6,6 @@ * - Magnus Damm */ -#include #include #include #include diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c index 9d45b8ae21..bbe9235309 100644 --- a/xen/common/libelf/libelf-dominfo.c +++ b/xen/common/libelf/libelf-dominfo.c @@ -15,61 +15,63 @@ const char *elf_xen_feature_names[] = { [XENFEAT_pae_pgdir_above_4gb] = "pae_pgdir_above_4gb" }; const int elf_xen_features = - sizeof(elf_xen_feature_names) / sizeof(elf_xen_feature_names[0]); +sizeof(elf_xen_feature_names) / sizeof(elf_xen_feature_names[0]); int elf_xen_parse_features(const char *features, - uint32_t *supported, - uint32_t *required) + uint32_t *supported, + uint32_t *required) { char feature[64]; int pos, len, i; - if (NULL == features) - return 0; - for (pos = 0; features[pos] != '\0'; pos += len) - { - memset(feature, 0, sizeof(feature)); - for (len = 0;; len++) - { - if (len >= sizeof(feature)-1) - break; - if (features[pos + len] == '\0') - break; - if (features[pos + len] == '|') - { - len++; - break; - } - feature[len] = features[pos + len]; - } + if ( features == NULL ) + return 0; - for (i = 0; i < elf_xen_features; i++) - { - if (!elf_xen_feature_names[i]) - continue; - if (NULL != required && feature[0] == '!') - { - /* required */ - if (0 == strcmp(feature + 1, elf_xen_feature_names[i])) - { - elf_xen_feature_set(i, supported); - elf_xen_feature_set(i, required); - break; - } - } - else - { - /* supported */ - if (0 == strcmp(feature, elf_xen_feature_names[i])) - { - elf_xen_feature_set(i, supported); - break; - } - } - } - if (i == elf_xen_features) - return -1; + for ( pos = 0; features[pos] != '\0'; pos += len ) + { + memset(feature, 0, sizeof(feature)); + for ( len = 0;; len++ ) + { + if ( len >= sizeof(feature)-1 ) + break; + if ( features[pos + len] == '\0' ) + break; + if ( features[pos + len] == '|' ) + { + len++; + break; + } + feature[len] = features[pos + len]; + } + + for ( i = 0; i < elf_xen_features; i++ ) + { + if ( !elf_xen_feature_names[i] ) + continue; + if ( (required != NULL) && (feature[0] == '!') ) + { + /* required */ + if ( !strcmp(feature + 1, elf_xen_feature_names[i]) ) + { + elf_xen_feature_set(i, supported); + elf_xen_feature_set(i, required); + break; + } + } + else + { + /* supported */ + if ( !strcmp(feature, elf_xen_feature_names[i]) ) + { + elf_xen_feature_set(i, supported); + break; + } + } + } + if ( i == elf_xen_features ) + return -1; } + return 0; } @@ -77,26 +79,26 @@ int elf_xen_parse_features(const char *features, /* xen elf notes */ int elf_xen_parse_note(struct elf_binary *elf, - struct elf_dom_parms *parms, - const elf_note *note) + struct elf_dom_parms *parms, + const elf_note *note) { /* *INDENT-OFF* */ static const struct { - char *name; - int str; + char *name; + int str; } note_desc[] = { - [XEN_ELFNOTE_ENTRY] = { "ENTRY", 0}, - [XEN_ELFNOTE_HYPERCALL_PAGE] = { "HYPERCALL_PAGE", 0}, - [XEN_ELFNOTE_VIRT_BASE] = { "VIRT_BASE", 0}, - [XEN_ELFNOTE_PADDR_OFFSET] = { "PADDR_OFFSET", 0}, - [XEN_ELFNOTE_HV_START_LOW] = { "HV_START_LOW", 0}, - [XEN_ELFNOTE_XEN_VERSION] = { "XEN_VERSION", 1}, - [XEN_ELFNOTE_GUEST_OS] = { "GUEST_OS", 1}, - [XEN_ELFNOTE_GUEST_VERSION] = { "GUEST_VERSION", 1}, - [XEN_ELFNOTE_LOADER] = { "LOADER", 1}, - [XEN_ELFNOTE_PAE_MODE] = { "PAE_MODE", 1}, - [XEN_ELFNOTE_FEATURES] = { "FEATURES", 1}, - [XEN_ELFNOTE_BSD_SYMTAB] = { "BSD_SYMTAB", 1}, + [XEN_ELFNOTE_ENTRY] = { "ENTRY", 0}, + [XEN_ELFNOTE_HYPERCALL_PAGE] = { "HYPERCALL_PAGE", 0}, + [XEN_ELFNOTE_VIRT_BASE] = { "VIRT_BASE", 0}, + [XEN_ELFNOTE_PADDR_OFFSET] = { "PADDR_OFFSET", 0}, + [XEN_ELFNOTE_HV_START_LOW] = { "HV_START_LOW", 0}, + [XEN_ELFNOTE_XEN_VERSION] = { "XEN_VERSION", 1}, + [XEN_ELFNOTE_GUEST_OS] = { "GUEST_OS", 1}, + [XEN_ELFNOTE_GUEST_VERSION] = { "GUEST_VERSION", 1}, + [XEN_ELFNOTE_LOADER] = { "LOADER", 1}, + [XEN_ELFNOTE_PAE_MODE] = { "PAE_MODE", 1}, + [XEN_ELFNOTE_FEATURES] = { "FEATURES", 1}, + [XEN_ELFNOTE_BSD_SYMTAB] = { "BSD_SYMTAB", 1}, }; /* *INDENT-ON* */ @@ -104,73 +106,73 @@ int elf_xen_parse_note(struct elf_binary *elf, uint64_t val = 0; int type = elf_uval(elf, note, type); - if ((type >= sizeof(note_desc) / sizeof(note_desc[0])) || - (NULL == note_desc[type].name)) + if ( (type >= sizeof(note_desc) / sizeof(note_desc[0])) || + (note_desc[type].name == NULL) ) { - elf_err(elf, "%s: unknown xen elf note (0x%x)\n", - __FUNCTION__, type); - return -1; + elf_msg(elf, "%s: unknown xen elf note (0x%x)\n", + __FUNCTION__, type); + return 0; } - if (note_desc[type].str) + if ( note_desc[type].str ) { - str = elf_note_desc(elf, note); - elf_msg(elf, "%s: %s = \"%s\"\n", __FUNCTION__, - note_desc[type].name, str); + str = elf_note_desc(elf, note); + elf_msg(elf, "%s: %s = \"%s\"\n", __FUNCTION__, + note_desc[type].name, str); } else { - val = elf_note_numeric(elf, note); - elf_msg(elf, "%s: %s = 0x%" PRIx64 "\n", __FUNCTION__, - note_desc[type].name, val); + val = elf_note_numeric(elf, note); + elf_msg(elf, "%s: %s = 0x%" PRIx64 "\n", __FUNCTION__, + note_desc[type].name, val); } - switch (type) + switch ( type ) { case XEN_ELFNOTE_LOADER: - safe_strcpy(parms->loader, str); - break; + safe_strcpy(parms->loader, str); + break; case XEN_ELFNOTE_GUEST_OS: - safe_strcpy(parms->guest_os, str); - break; + safe_strcpy(parms->guest_os, str); + break; case XEN_ELFNOTE_GUEST_VERSION: - safe_strcpy(parms->guest_ver, str); - break; + safe_strcpy(parms->guest_ver, str); + break; case XEN_ELFNOTE_XEN_VERSION: - safe_strcpy(parms->xen_ver, str); - break; + safe_strcpy(parms->xen_ver, str); + break; case XEN_ELFNOTE_PAE_MODE: - if (0 == strcmp(str, "yes")) - parms->pae = 2 /* extended_cr3 */; - if (strstr(str, "bimodal")) - parms->pae = 3 /* bimodal */; - break; + if ( !strcmp(str, "yes") ) + parms->pae = 2 /* extended_cr3 */; + if ( strstr(str, "bimodal") ) + parms->pae = 3 /* bimodal */; + break; case XEN_ELFNOTE_BSD_SYMTAB: - if (0 == strcmp(str, "yes")) - parms->bsd_symtab = 1; - break; + if ( !strcmp(str, "yes") ) + parms->bsd_symtab = 1; + break; case XEN_ELFNOTE_VIRT_BASE: - parms->virt_base = val; - break; + parms->virt_base = val; + break; case XEN_ELFNOTE_ENTRY: - parms->virt_entry = val; - break; + parms->virt_entry = val; + break; case XEN_ELFNOTE_PADDR_OFFSET: - parms->elf_paddr_offset = val; - break; + parms->elf_paddr_offset = val; + break; case XEN_ELFNOTE_HYPERCALL_PAGE: - parms->virt_hypercall = val; - break; + parms->virt_hypercall = val; + break; case XEN_ELFNOTE_HV_START_LOW: - parms->virt_hv_start_low = val; - break; + parms->virt_hv_start_low = val; + break; case XEN_ELFNOTE_FEATURES: - if (0 != elf_xen_parse_features(str, parms->f_supported, - parms->f_required)) - return -1; - break; + if ( elf_xen_parse_features(str, parms->f_supported, + parms->f_required) ) + return -1; + break; } return 0; @@ -180,83 +182,85 @@ int elf_xen_parse_note(struct elf_binary *elf, /* __xen_guest section */ int elf_xen_parse_guest_info(struct elf_binary *elf, - struct elf_dom_parms *parms) + struct elf_dom_parms *parms) { const char *h; char name[32], value[128]; int len; h = parms->guest_info; - while (*h) + while ( *h ) { - memset(name, 0, sizeof(name)); - memset(value, 0, sizeof(value)); - for (len = 0;; len++, h++) { - if (len >= sizeof(name)-1) - break; - if (*h == '\0') - break; - if (*h == ',') - { - h++; - break; - } - if (*h == '=') - { - h++; - for (len = 0;; len++, h++) { - if (len >= sizeof(value)-1) - break; - if (*h == '\0') - break; - if (*h == ',') - { - h++; - break; - } - value[len] = *h; - } - break; - } - name[len] = *h; - } - elf_msg(elf, "%s: %s=\"%s\"\n", __FUNCTION__, name, value); + memset(name, 0, sizeof(name)); + memset(value, 0, sizeof(value)); + for ( len = 0;; len++, h++ ) + { + if ( len >= sizeof(name)-1 ) + break; + if ( *h == '\0' ) + break; + if ( *h == ',' ) + { + h++; + break; + } + if ( *h == '=' ) + { + h++; + for ( len = 0;; len++, h++ ) + { + if ( len >= sizeof(value)-1 ) + break; + if ( *h == '\0' ) + break; + if ( *h == ',' ) + { + h++; + break; + } + value[len] = *h; + } + break; + } + name[len] = *h; + } + elf_msg(elf, "%s: %s=\"%s\"\n", __FUNCTION__, name, value); - /* strings */ - if (0 == strcmp(name, "LOADER")) - safe_strcpy(parms->loader, value); - if (0 == strcmp(name, "GUEST_OS")) - safe_strcpy(parms->guest_os, value); - if (0 == strcmp(name, "GUEST_VER")) - safe_strcpy(parms->guest_ver, value); - if (0 == strcmp(name, "XEN_VER")) - safe_strcpy(parms->xen_ver, value); - if (0 == strcmp(name, "PAE")) - { - if (0 == strcmp(value, "yes[extended-cr3]")) - parms->pae = 2 /* extended_cr3 */; - else if (0 == strncmp(value, "yes", 3)) - parms->pae = 1 /* yes */; - } - if (0 == strcmp(name, "BSD_SYMTAB")) - parms->bsd_symtab = 1; + /* strings */ + if ( !strcmp(name, "LOADER") ) + safe_strcpy(parms->loader, value); + if ( !strcmp(name, "GUEST_OS") ) + safe_strcpy(parms->guest_os, value); + if ( !strcmp(name, "GUEST_VER") ) + safe_strcpy(parms->guest_ver, value); + if ( !strcmp(name, "XEN_VER") ) + safe_strcpy(parms->xen_ver, value); + if ( !strcmp(name, "PAE") ) + { + if ( !strcmp(value, "yes[extended-cr3]") ) + parms->pae = 2 /* extended_cr3 */; + else if ( !strncmp(value, "yes", 3) ) + parms->pae = 1 /* yes */; + } + if ( !strcmp(name, "BSD_SYMTAB") ) + parms->bsd_symtab = 1; - /* longs */ - if (0 == strcmp(name, "VIRT_BASE")) - parms->virt_base = strtoull(value, NULL, 0); - if (0 == strcmp(name, "VIRT_ENTRY")) - parms->virt_entry = strtoull(value, NULL, 0); - if (0 == strcmp(name, "ELF_PADDR_OFFSET")) - parms->elf_paddr_offset = strtoull(value, NULL, 0); - if (0 == strcmp(name, "HYPERCALL_PAGE")) - parms->virt_hypercall = (strtoull(value, NULL, 0) << 12) + - parms->virt_base; + /* longs */ + if ( !strcmp(name, "VIRT_BASE") ) + parms->virt_base = strtoull(value, NULL, 0); + if ( !strcmp(name, "VIRT_ENTRY") ) + parms->virt_entry = strtoull(value, NULL, 0); + if ( !strcmp(name, "ELF_PADDR_OFFSET") ) + parms->elf_paddr_offset = strtoull(value, NULL, 0); + if ( !strcmp(name, "HYPERCALL_PAGE") ) + parms->virt_hypercall = (strtoull(value, NULL, 0) << 12) + + parms->virt_base; - /* other */ - if (0 == strcmp(name, "FEATURES")) - if (0 != elf_xen_parse_features(value, parms->f_supported, - parms->f_required)) - return -1; + /* other */ + if ( !strcmp(name, "FEATURES") ) + if ( elf_xen_parse_features(value, parms->f_supported, + parms->f_required) ) + return -1; } return 0; } @@ -265,54 +269,59 @@ int elf_xen_parse_guest_info(struct elf_binary *elf, /* sanity checks */ static int elf_xen_note_check(struct elf_binary *elf, - struct elf_dom_parms *parms) + struct elf_dom_parms *parms) { - if (NULL == parms->elf_note_start && NULL == parms->guest_info) { - int machine = elf_uval(elf, elf->ehdr, e_machine); - if (EM_386 == machine || EM_X86_64 == machine) { - elf_err(elf, "%s: ERROR: Not a Xen-ELF image: " - "No ELF notes or '__xen_guest' section found.\n", - __FUNCTION__); - return -1; - } - return 0; + if ( (parms->elf_note_start == NULL) && (parms->guest_info == NULL) ) + { + int machine = elf_uval(elf, elf->ehdr, e_machine); + if ( (machine == EM_386) || (machine == EM_X86_64) ) + { + elf_err(elf, "%s: ERROR: Not a Xen-ELF image: " + "No ELF notes or '__xen_guest' section found.\n", + __FUNCTION__); + return -1; + } + return 0; } /* Check the contents of the Xen notes or guest string. */ - if ( ( 0 == strlen(parms->loader) || strncmp(parms->loader, "generic", 7) ) && - ( 0 == strlen(parms->guest_os) || strncmp(parms->guest_os, "linux", 5) ) ) + if ( ((strlen(parms->loader) == 0) || + strncmp(parms->loader, "generic", 7)) && + ((strlen(parms->guest_os) == 0) || + strncmp(parms->guest_os, "linux", 5)) ) { - elf_err(elf, "%s: ERROR: Will only load images built for the generic " - "loader or Linux images", __FUNCTION__); - return -1; + elf_err(elf, "%s: ERROR: Will only load images built for the generic " + "loader or Linux images", __FUNCTION__); + return -1; } - if ( 0 == strlen(parms->xen_ver) || strncmp(parms->xen_ver, "xen-3.0", 7) ) + if ( (strlen(parms->xen_ver) == 0) || + strncmp(parms->xen_ver, "xen-3.0", 7) ) { - elf_err(elf, "%s: ERROR: Xen will only load images built for Xen v3.0\n", - __FUNCTION__); - return -1; + elf_err(elf, "%s: ERROR: Xen will only load images built " + "for Xen v3.0\n", __FUNCTION__); + return -1; } return 0; } static int elf_xen_addr_calc_check(struct elf_binary *elf, - struct elf_dom_parms *parms) + struct elf_dom_parms *parms) { - if (UNSET_ADDR != parms->elf_paddr_offset && - UNSET_ADDR == parms->virt_base ) + if ( (parms->elf_paddr_offset != UNSET_ADDR) && + (parms->virt_base == UNSET_ADDR) ) { - elf_err(elf, "%s: ERROR: ELF_PADDR_OFFSET set, VIRT_BASE unset\n", - __FUNCTION__); + elf_err(elf, "%s: ERROR: ELF_PADDR_OFFSET set, VIRT_BASE unset\n", + __FUNCTION__); return -1; } /* Initial guess for virt_base is 0 if it is not explicitly defined. */ - if (UNSET_ADDR == parms->virt_base) + if ( parms->virt_base == UNSET_ADDR ) { - parms->virt_base = 0; - elf_msg(elf, "%s: VIRT_BASE unset, using 0x%" PRIx64 "\n", - __FUNCTION__, parms->virt_base); + parms->virt_base = 0; + elf_msg(elf, "%s: VIRT_BASE unset, using 0x%" PRIx64 "\n", + __FUNCTION__, parms->virt_base); } /* @@ -324,22 +333,22 @@ static int elf_xen_addr_calc_check(struct elf_binary *elf, * If we are using the modern ELF notes interface then the default * is 0. */ - if (UNSET_ADDR == parms->elf_paddr_offset) + if ( parms->elf_paddr_offset == UNSET_ADDR ) { - if (parms->elf_note_start) - parms->elf_paddr_offset = 0; - else - parms->elf_paddr_offset = parms->virt_base; - elf_msg(elf, "%s: ELF_PADDR_OFFSET unset, using 0x%" PRIx64 "\n", - __FUNCTION__, parms->elf_paddr_offset); + if ( parms->elf_note_start ) + parms->elf_paddr_offset = 0; + else + parms->elf_paddr_offset = parms->virt_base; + elf_msg(elf, "%s: ELF_PADDR_OFFSET unset, using 0x%" PRIx64 "\n", + __FUNCTION__, parms->elf_paddr_offset); } parms->virt_offset = parms->virt_base - parms->elf_paddr_offset; parms->virt_kstart = elf->pstart + parms->virt_offset; parms->virt_kend = elf->pend + parms->virt_offset; - if (UNSET_ADDR == parms->virt_entry) - parms->virt_entry = elf_uval(elf, elf->ehdr, e_entry); + if ( parms->virt_entry == UNSET_ADDR ) + parms->virt_entry = elf_uval(elf, elf->ehdr, e_entry); elf_msg(elf, "%s: addresses:\n", __FUNCTION__); elf_msg(elf, " virt_base = 0x%" PRIx64 "\n", parms->virt_base); @@ -355,7 +364,7 @@ static int elf_xen_addr_calc_check(struct elf_binary *elf, (parms->virt_base > parms->virt_kstart) ) { elf_err(elf, "%s: ERROR: ELF start or entries are out of bounds.\n", - __FUNCTION__); + __FUNCTION__); return -1; } @@ -366,7 +375,7 @@ static int elf_xen_addr_calc_check(struct elf_binary *elf, /* glue it all together ... */ int elf_xen_parse(struct elf_binary *elf, - struct elf_dom_parms *parms) + struct elf_dom_parms *parms) { const elf_note *note; const elf_shdr *shdr; @@ -382,39 +391,49 @@ int elf_xen_parse(struct elf_binary *elf, /* find and parse elf notes */ count = elf_shdr_count(elf); - for (i = 0; i < count; i++) + for ( i = 0; i < count; i++ ) { - shdr = elf_shdr_by_index(elf, i); - if (0 == strcmp(elf_section_name(elf, shdr), "__xen_guest")) - parms->guest_info = elf_section_start(elf, shdr); - if (elf_uval(elf, shdr, sh_type) != SHT_NOTE) - continue; - parms->elf_note_start = elf_section_start(elf, shdr); - parms->elf_note_end = elf_section_end(elf, shdr); - for (note = parms->elf_note_start; - (void *)note < parms->elf_note_end; - note = elf_note_next(elf, note)) - { - if (0 != strcmp(elf_note_name(elf, note), "Xen")) - continue; - if (0 != elf_xen_parse_note(elf, parms, note)) - return -1; - xen_elfnotes++; - } + shdr = elf_shdr_by_index(elf, i); + if ( !strcmp(elf_section_name(elf, shdr), "__xen_guest") ) + parms->guest_info = elf_section_start(elf, shdr); + if ( elf_uval(elf, shdr, sh_type) != SHT_NOTE ) + continue; + parms->elf_note_start = elf_section_start(elf, shdr); + parms->elf_note_end = elf_section_end(elf, shdr); + for ( note = parms->elf_note_start; + (void *)note < parms->elf_note_end; + note = elf_note_next(elf, note) ) + { + if ( strcmp(elf_note_name(elf, note), "Xen") ) + continue; + if ( elf_xen_parse_note(elf, parms, note) ) + return -1; + xen_elfnotes++; + } } - if (!xen_elfnotes && parms->guest_info) + if ( !xen_elfnotes && parms->guest_info ) { - parms->elf_note_start = NULL; - parms->elf_note_end = NULL; - elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__, - parms->guest_info); - elf_xen_parse_guest_info(elf, parms); + parms->elf_note_start = NULL; + parms->elf_note_end = NULL; + elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__, + parms->guest_info); + elf_xen_parse_guest_info(elf, parms); } - if (0 != elf_xen_note_check(elf, parms)) - return -1; - if (0 != elf_xen_addr_calc_check(elf, parms)) - return -1; + if ( elf_xen_note_check(elf, parms) != 0 ) + return -1; + if ( elf_xen_addr_calc_check(elf, parms) != 0 ) + return -1; return 0; } + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c index 9c4491ebe4..e0f8dba913 100644 --- a/xen/common/libelf/libelf-loader.c +++ b/xen/common/libelf/libelf-loader.c @@ -11,10 +11,10 @@ int elf_init(struct elf_binary *elf, const char *image, size_t size) const elf_shdr *shdr; uint64_t i, count, section, offset; - if (!elf_is_elfbinary(image)) + if ( !elf_is_elfbinary(image) ) { - elf_err(elf, "%s: not an ELF binary\n", __FUNCTION__); - return -1; + elf_err(elf, "%s: not an ELF binary\n", __FUNCTION__); + return -1; } memset(elf, 0, sizeof(*elf)); @@ -26,46 +26,46 @@ int elf_init(struct elf_binary *elf, const char *image, size_t size) /* sanity check phdr */ offset = elf_uval(elf, elf->ehdr, e_phoff) + - elf_uval(elf, elf->ehdr, e_phentsize) * elf_phdr_count(elf); - if (offset > elf->size) + elf_uval(elf, elf->ehdr, e_phentsize) * elf_phdr_count(elf); + if ( offset > elf->size ) { - elf_err(elf, "%s: phdr overflow (off %" PRIx64 " > size %lx)\n", - __FUNCTION__, offset, (unsigned long)elf->size); - return -1; + elf_err(elf, "%s: phdr overflow (off %" PRIx64 " > size %lx)\n", + __FUNCTION__, offset, (unsigned long)elf->size); + return -1; } /* sanity check shdr */ offset = elf_uval(elf, elf->ehdr, e_shoff) + - elf_uval(elf, elf->ehdr, e_shentsize) * elf_shdr_count(elf); - if (offset > elf->size) + elf_uval(elf, elf->ehdr, e_shentsize) * elf_shdr_count(elf); + if ( offset > elf->size ) { - elf_err(elf, "%s: shdr overflow (off %" PRIx64 " > size %lx)\n", - __FUNCTION__, offset, (unsigned long)elf->size); - return -1; + elf_err(elf, "%s: shdr overflow (off %" PRIx64 " > size %lx)\n", + __FUNCTION__, offset, (unsigned long)elf->size); + return -1; } /* find section string table */ section = elf_uval(elf, elf->ehdr, e_shstrndx); shdr = elf_shdr_by_index(elf, section); - if (NULL != shdr) - elf->sec_strtab = elf_section_start(elf, shdr); + if ( shdr != NULL ) + elf->sec_strtab = elf_section_start(elf, shdr); /* find symbol table, symbol string table */ count = elf_shdr_count(elf); - for (i = 0; i < count; i++) + for ( i = 0; i < count; i++ ) { - shdr = elf_shdr_by_index(elf, i); - if (elf_uval(elf, shdr, sh_type) != SHT_SYMTAB) - continue; - elf->sym_tab = shdr; - shdr = elf_shdr_by_index(elf, elf_uval(elf, shdr, sh_link)); - if (NULL == shdr) - { - elf->sym_tab = NULL; - continue; - } - elf->sym_strtab = elf_section_start(elf, shdr); - break; + shdr = elf_shdr_by_index(elf, i); + if ( elf_uval(elf, shdr, sh_type) != SHT_SYMTAB ) + continue; + elf->sym_tab = shdr; + shdr = elf_shdr_by_index(elf, elf_uval(elf, shdr, sh_link)); + if ( shdr == NULL ) + { + elf->sym_tab = NULL; + continue; + } + elf->sym_strtab = elf_section_start(elf, shdr); + break; } return 0; } @@ -91,24 +91,24 @@ void elf_parse_binary(struct elf_binary *elf) uint64_t i, count, paddr, memsz; count = elf_uval(elf, elf->ehdr, e_phnum); - for (i = 0; i < count; i++) + for ( i = 0; i < count; i++ ) { - phdr = elf_phdr_by_index(elf, i); - if (!elf_phdr_is_loadable(elf, phdr)) - continue; - paddr = elf_uval(elf, phdr, p_paddr); - memsz = elf_uval(elf, phdr, p_memsz); - elf_msg(elf, "%s: phdr: paddr=0x%" PRIx64 - " memsz=0x%" PRIx64 "\n", __FUNCTION__, paddr, memsz); - if (low > paddr) - low = paddr; - if (high < paddr + memsz) - high = paddr + memsz; + phdr = elf_phdr_by_index(elf, i); + if ( !elf_phdr_is_loadable(elf, phdr) ) + continue; + paddr = elf_uval(elf, phdr, p_paddr); + memsz = elf_uval(elf, phdr, p_memsz); + elf_msg(elf, "%s: phdr: paddr=0x%" PRIx64 + " memsz=0x%" PRIx64 "\n", __FUNCTION__, paddr, memsz); + if ( low > paddr ) + low = paddr; + if ( high < paddr + memsz ) + high = paddr + memsz; } elf->pstart = low; elf->pend = high; elf_msg(elf, "%s: memory: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", - __FUNCTION__, elf->pstart, elf->pend); + __FUNCTION__, elf->pstart, elf->pend); } void elf_load_binary(struct elf_binary *elf) @@ -118,20 +118,20 @@ void elf_load_binary(struct elf_binary *elf) char *dest; count = elf_uval(elf, elf->ehdr, e_phnum); - for (i = 0; i < count; i++) + for ( i = 0; i < count; i++ ) { - phdr = elf_phdr_by_index(elf, i); - if (!elf_phdr_is_loadable(elf, phdr)) - continue; - paddr = elf_uval(elf, phdr, p_paddr); - offset = elf_uval(elf, phdr, p_offset); - filesz = elf_uval(elf, phdr, p_filesz); - memsz = elf_uval(elf, phdr, p_memsz); - dest = elf_get_ptr(elf, paddr); - elf_msg(elf, "%s: phdr %" PRIu64 " at 0x%p -> 0x%p\n", - __func__, i, dest, dest + filesz); - memcpy(dest, elf->image + offset, filesz); - memset(dest + filesz, 0, memsz - filesz); + phdr = elf_phdr_by_index(elf, i); + if ( !elf_phdr_is_loadable(elf, phdr) ) + continue; + paddr = elf_uval(elf, phdr, p_paddr); + offset = elf_uval(elf, phdr, p_offset); + filesz = elf_uval(elf, phdr, p_filesz); + memsz = elf_uval(elf, phdr, p_memsz); + dest = elf_get_ptr(elf, paddr); + elf_msg(elf, "%s: phdr %" PRIu64 " at 0x%p -> 0x%p\n", + __func__, i, dest, dest + filesz); + memcpy(dest, elf->image + offset, filesz); + memset(dest + filesz, 0, memsz - filesz); } } @@ -146,13 +146,24 @@ uint64_t elf_lookup_addr(struct elf_binary * elf, const char *symbol) uint64_t value; sym = elf_sym_by_name(elf, symbol); - if (NULL == sym) + if ( sym == NULL ) { - elf_err(elf, "%s: not found: %s\n", __FUNCTION__, symbol); - return -1; + elf_err(elf, "%s: not found: %s\n", __FUNCTION__, symbol); + return -1; } + value = elf_uval(elf, sym, st_value); elf_msg(elf, "%s: symbol \"%s\" at 0x%" PRIx64 "\n", __FUNCTION__, - symbol, value); + symbol, value); return value; } + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/common/libelf/libelf-private.h b/xen/common/libelf/libelf-private.h index c404638f66..321fa5eb63 100644 --- a/xen/common/libelf/libelf-private.h +++ b/xen/common/libelf/libelf-private.h @@ -12,9 +12,9 @@ #include #define elf_msg(elf, fmt, args ... ) \ - if (elf->verbose) printk(fmt, ## args ) + if (elf->verbose) printk(fmt, ## args ) #define elf_err(elf, fmt, args ... ) \ - printk(fmt, ## args ) + printk(fmt, ## args ) #define strtoull(str, end, base) simple_strtoull(str, end, base) #define bswap_16(x) swab16(x) @@ -43,12 +43,12 @@ #include "xc_private.h" #define elf_msg(elf, fmt, args ... ) \ - if (elf->log && elf->verbose) fprintf(elf->log, fmt , ## args ) -#define elf_err(elf, fmt, args ... ) do { \ - if (elf->log) \ - fprintf(elf->log, fmt , ## args ); \ - xc_set_error(XC_INVALID_KERNEL, fmt , ## args ); \ - } while (0) + if (elf->log && elf->verbose) fprintf(elf->log, fmt , ## args ) +#define elf_err(elf, fmt, args ... ) do { \ + if (elf->log) \ + fprintf(elf->log, fmt , ## args ); \ + xc_set_error(XC_INVALID_KERNEL, fmt , ## args ); \ +} while (0) #define safe_strcpy(d,s) \ do { strncpy((d),(s),sizeof((d))-1); \ @@ -58,3 +58,13 @@ do { strncpy((d),(s),sizeof((d))-1); \ #endif #endif /* __LIBELF_PRIVATE_H_ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/common/libelf/libelf-relocate.c b/xen/common/libelf/libelf-relocate.c index 7356a94016..89cea4411b 100644 --- a/xen/common/libelf/libelf-relocate.c +++ b/xen/common/libelf/libelf-relocate.c @@ -46,22 +46,22 @@ static const char *rel_names_i386[] = { }; static int elf_reloc_i386(struct elf_binary *elf, int type, - uint64_t addr, uint64_t value) + uint64_t addr, uint64_t value) { void *ptr = elf_get_ptr(elf, addr); uint32_t *u32; - switch (type) + switch ( type ) { case 1 /* R_386_32 */ : - u32 = ptr; - *u32 += elf->reloc_offset; - break; + u32 = ptr; + *u32 += elf->reloc_offset; + break; case 2 /* R_386_PC32 */ : - /* nothing */ - break; + /* nothing */ + break; default: - return -1; + return -1; } return 0; } @@ -96,54 +96,57 @@ static const char *rel_names_x86_64[] = { }; static int elf_reloc_x86_64(struct elf_binary *elf, int type, - uint64_t addr, uint64_t value) + uint64_t addr, uint64_t value) { void *ptr = elf_get_ptr(elf, addr); uint64_t *u64; uint32_t *u32; int32_t *s32; - switch (type) + switch ( type ) { case 1 /* R_X86_64_64 */ : - u64 = ptr; - value += elf->reloc_offset; - *u64 = value; - break; + u64 = ptr; + value += elf->reloc_offset; + *u64 = value; + break; case 2 /* R_X86_64_PC32 */ : - u32 = ptr; - *u32 = value - addr; - if (*u32 != (uint32_t) (value - addr)) - { - elf_err(elf, "R_X86_64_PC32 overflow: 0x%" PRIx32 " != 0x%" PRIx32 "\n", - *u32, (uint32_t) (value - addr)); - return -1; - } - break; + u32 = ptr; + *u32 = value - addr; + if ( *u32 != (uint32_t)(value - addr) ) + { + elf_err(elf, "R_X86_64_PC32 overflow: 0x%" PRIx32 + " != 0x%" PRIx32 "\n", + *u32, (uint32_t) (value - addr)); + return -1; + } + break; case 10 /* R_X86_64_32 */ : - u32 = ptr; - value += elf->reloc_offset; - *u32 = value; - if (*u32 != value) - { - elf_err(elf, "R_X86_64_32 overflow: 0x%" PRIx32 " != 0x%" PRIx64 "\n", - *u32, value); - return -1; - } - break; + u32 = ptr; + value += elf->reloc_offset; + *u32 = value; + if ( *u32 != value ) + { + elf_err(elf, "R_X86_64_32 overflow: 0x%" PRIx32 + " != 0x%" PRIx64 "\n", + *u32, value); + return -1; + } + break; case 11 /* R_X86_64_32S */ : - s32 = ptr; - value += elf->reloc_offset; - *s32 = value; - if (*s32 != (int64_t) value) - { - elf_err(elf, "R_X86_64_32S overflow: 0x%" PRIx32 " != 0x%" PRIx64 "\n", - *s32, (int64_t) value); - return -1; - } - break; + s32 = ptr; + value += elf->reloc_offset; + *s32 = value; + if ( *s32 != (int64_t) value ) + { + elf_err(elf, "R_X86_64_32S overflow: 0x%" PRIx32 + " != 0x%" PRIx64 "\n", + *s32, (int64_t) value); + return -1; + } + break; default: - return -1; + return -1; } return 0; } @@ -154,19 +157,19 @@ static struct relocs { const char **names; int count; int (*func) (struct elf_binary * elf, int type, uint64_t addr, - uint64_t value); + uint64_t value); } relocs[] = /* *INDENT-OFF* */ { [EM_386] = { - .names = rel_names_i386, - .count = sizeof(rel_names_i386) / sizeof(rel_names_i386[0]), - .func = elf_reloc_i386, + .names = rel_names_i386, + .count = sizeof(rel_names_i386) / sizeof(rel_names_i386[0]), + .func = elf_reloc_i386, }, [EM_X86_64] = { - .names = rel_names_x86_64, - .count = sizeof(rel_names_x86_64) / sizeof(rel_names_x86_64[0]), - .func = elf_reloc_x86_64, + .names = rel_names_x86_64, + .count = sizeof(rel_names_x86_64) / sizeof(rel_names_x86_64[0]), + .func = elf_reloc_x86_64, } }; /* *INDENT-ON* */ @@ -175,18 +178,18 @@ static struct relocs { static const char *rela_name(int machine, int type) { - if (machine > sizeof(relocs) / sizeof(relocs[0])) - return "unknown mach"; - if (!relocs[machine].names) - return "unknown mach"; - if (type > relocs[machine].count) - return "unknown rela"; + if ( machine > sizeof(relocs) / sizeof(relocs[0]) ) + return "unknown mach"; + if ( !relocs[machine].names ) + return "unknown mach"; + if ( type > relocs[machine].count ) + return "unknown rela"; return relocs[machine].names[type]; } static int elf_reloc_section(struct elf_binary *elf, - const elf_shdr * rels, - const elf_shdr * sect, const elf_shdr * syms) + const elf_shdr * rels, + const elf_shdr * sect, const elf_shdr * syms) { const void *ptr, *end; const elf_shdr *shdr; @@ -204,18 +207,18 @@ static int elf_reloc_section(struct elf_binary *elf, int machine; machine = elf_uval(elf, elf->ehdr, e_machine); - if (machine >= sizeof(relocs) / sizeof(relocs[0]) || - NULL == relocs[machine].func) + if ( (machine >= (sizeof(relocs) / sizeof(relocs[0]))) || + (relocs[machine].func == NULL) ) { - elf_err(elf, "%s: can't handle machine %d\n", - __FUNCTION__, machine); - return -1; + elf_err(elf, "%s: can't handle machine %d\n", + __FUNCTION__, machine); + return -1; } - if (elf_swap(elf)) + if ( elf_swap(elf) ) { - elf_err(elf, "%s: non-native byte order, relocation not supported\n", - __FUNCTION__); - return -1; + elf_err(elf, "%s: non-native byte order, relocation not supported\n", + __FUNCTION__); + return -1; } s_type = elf_uval(elf, rels, sh_type); @@ -223,89 +226,89 @@ static int elf_reloc_section(struct elf_binary *elf, ptr = elf_section_start(elf, rels); end = elf_section_end(elf, rels); - for (; ptr < end; ptr += rsize) + for ( ; ptr < end; ptr += rsize ) { - switch (s_type) - { - case SHT_REL: - rel = ptr; - r_offset = elf_uval(elf, rel, r_offset); - r_info = elf_uval(elf, rel, r_info); - r_addend = 0; - break; - case SHT_RELA: - rela = ptr; - r_offset = elf_uval(elf, rela, r_offset); - r_info = elf_uval(elf, rela, r_info); - r_addend = elf_uval(elf, rela, r_addend); - break; - default: - /* can't happen */ - return -1; - } - if (elf_64bit(elf)) - { - r_type = ELF64_R_TYPE(r_info); - r_sym = ELF64_R_SYM(r_info); - } - else - { - r_type = ELF32_R_TYPE(r_info); - r_sym = ELF32_R_SYM(r_info); - } + switch ( s_type ) + { + case SHT_REL: + rel = ptr; + r_offset = elf_uval(elf, rel, r_offset); + r_info = elf_uval(elf, rel, r_info); + r_addend = 0; + break; + case SHT_RELA: + rela = ptr; + r_offset = elf_uval(elf, rela, r_offset); + r_info = elf_uval(elf, rela, r_info); + r_addend = elf_uval(elf, rela, r_addend); + break; + default: + /* can't happen */ + return -1; + } + if ( elf_64bit(elf) ) + { + r_type = ELF64_R_TYPE(r_info); + r_sym = ELF64_R_SYM(r_info); + } + else + { + r_type = ELF32_R_TYPE(r_info); + r_sym = ELF32_R_SYM(r_info); + } - sym = elf_sym_by_index(elf, r_sym); - shndx = elf_uval(elf, sym, st_shndx); - switch (shndx) - { - case SHN_UNDEF: - sname = "*UNDEF*"; - sbase = 0; - break; - case SHN_COMMON: - elf_err(elf, "%s: invalid section: %" PRId64 "\n", - __FUNCTION__, shndx); - return -1; - case SHN_ABS: - sname = "*ABS*"; - sbase = 0; - break; - default: - shdr = elf_shdr_by_index(elf, shndx); - if (NULL == shdr) - { - elf_err(elf, "%s: invalid section: %" PRId64 "\n", - __FUNCTION__, shndx); - return -1; - } - sname = elf_section_name(elf, shdr); - sbase = elf_uval(elf, shdr, sh_addr); - } + sym = elf_sym_by_index(elf, r_sym); + shndx = elf_uval(elf, sym, st_shndx); + switch ( shndx ) + { + case SHN_UNDEF: + sname = "*UNDEF*"; + sbase = 0; + break; + case SHN_COMMON: + elf_err(elf, "%s: invalid section: %" PRId64 "\n", + __FUNCTION__, shndx); + return -1; + case SHN_ABS: + sname = "*ABS*"; + sbase = 0; + break; + default: + shdr = elf_shdr_by_index(elf, shndx); + if ( shdr == NULL ) + { + elf_err(elf, "%s: invalid section: %" PRId64 "\n", + __FUNCTION__, shndx); + return -1; + } + sname = elf_section_name(elf, shdr); + sbase = elf_uval(elf, shdr, sh_addr); + } - addr = r_offset; - value = elf_uval(elf, sym, st_value); - value += r_addend; + addr = r_offset; + value = elf_uval(elf, sym, st_value); + value += r_addend; - if (elf->log && elf->verbose > 1) - { - uint64_t st_name = elf_uval(elf, sym, st_name); - const char *name = st_name ? elf->sym_strtab + st_name : "*NONE*"; + if ( elf->log && (elf->verbose > 1) ) + { + uint64_t st_name = elf_uval(elf, sym, st_name); + const char *name = st_name ? elf->sym_strtab + st_name : "*NONE*"; - elf_msg(elf, - "%s: type %s [%d], off 0x%" PRIx64 ", add 0x%" PRIx64 "," - " sym %s [0x%" PRIx64 "], sec %s [0x%" PRIx64 "]" - " -> addr 0x%" PRIx64 " value 0x%" PRIx64 "\n", - __FUNCTION__, rela_name(machine, r_type), r_type, r_offset, - r_addend, name, elf_uval(elf, sym, st_value), sname, sbase, - addr, value); - } + elf_msg(elf, + "%s: type %s [%d], off 0x%" PRIx64 ", add 0x%" PRIx64 "," + " sym %s [0x%" PRIx64 "], sec %s [0x%" PRIx64 "]" + " -> addr 0x%" PRIx64 " value 0x%" PRIx64 "\n", + __FUNCTION__, rela_name(machine, r_type), r_type, r_offset, + r_addend, name, elf_uval(elf, sym, st_value), sname, sbase, + addr, value); + } - if (-1 == relocs[machine].func(elf, r_type, addr, value)) - { - elf_err(elf, "%s: unknown/unsupported reloc type %s [%d]\n", - __FUNCTION__, rela_name(machine, r_type), r_type); - return -1; - } + if ( relocs[machine].func(elf, r_type, addr, value) == -1 ) + { + elf_err(elf, "%s: unknown/unsupported reloc type %s [%d]\n", + __FUNCTION__, rela_name(machine, r_type), r_type); + return -1; + } } return 0; } @@ -316,30 +319,40 @@ int elf_reloc(struct elf_binary *elf) uint64_t i, count, type; count = elf_shdr_count(elf); - for (i = 0; i < count; i++) + for ( i = 0; i < count; i++ ) { - rels = elf_shdr_by_index(elf, i); - type = elf_uval(elf, rels, sh_type); - if (type != SHT_REL && type != SHT_RELA) - continue; + rels = elf_shdr_by_index(elf, i); + type = elf_uval(elf, rels, sh_type); + if ( (type != SHT_REL) && (type != SHT_RELA) ) + continue; - sect = elf_shdr_by_index(elf, elf_uval(elf, rels, sh_info)); - syms = elf_shdr_by_index(elf, elf_uval(elf, rels, sh_link)); - if (NULL == sect || NULL == syms) - continue; + sect = elf_shdr_by_index(elf, elf_uval(elf, rels, sh_info)); + syms = elf_shdr_by_index(elf, elf_uval(elf, rels, sh_link)); + if ( NULL == sect || NULL == syms ) + continue; - if (!(elf_uval(elf, sect, sh_flags) & SHF_ALLOC)) - { - elf_msg(elf, "%s: relocations for %s, skipping\n", - __FUNCTION__, elf_section_name(elf, sect)); - continue; - } + if ( !(elf_uval(elf, sect, sh_flags) & SHF_ALLOC) ) + { + elf_msg(elf, "%s: relocations for %s, skipping\n", + __FUNCTION__, elf_section_name(elf, sect)); + continue; + } - elf_msg(elf, "%s: relocations for %s @ 0x%" PRIx64 "\n", - __FUNCTION__, elf_section_name(elf, sect), - elf_uval(elf, sect, sh_addr)); - if (0 != elf_reloc_section(elf, rels, sect, syms)) - return -1; + elf_msg(elf, "%s: relocations for %s @ 0x%" PRIx64 "\n", + __FUNCTION__, elf_section_name(elf, sect), + elf_uval(elf, sect, sh_addr)); + if ( elf_reloc_section(elf, rels, sect, syms) != 0 ) + return -1; } return 0; } + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c index a80fd8534d..fb73c4664e 100644 --- a/xen/common/libelf/libelf-tools.c +++ b/xen/common/libelf/libelf-tools.c @@ -7,7 +7,7 @@ /* ------------------------------------------------------------------------ */ uint64_t elf_access_unsigned(struct elf_binary * elf, const void *ptr, - uint64_t offset, size_t size) + uint64_t offset, size_t size) { int need_swap = elf_swap(elf); const uint8_t *u8; @@ -15,27 +15,27 @@ uint64_t elf_access_unsigned(struct elf_binary * elf, const void *ptr, const uint32_t *u32; const uint64_t *u64; - switch (size) + switch ( size ) { case 1: - u8 = ptr + offset; - return *u8; + u8 = ptr + offset; + return *u8; case 2: - u16 = ptr + offset; - return need_swap ? bswap_16(*u16) : *u16; + u16 = ptr + offset; + return need_swap ? bswap_16(*u16) : *u16; case 4: - u32 = ptr + offset; - return need_swap ? bswap_32(*u32) : *u32; + u32 = ptr + offset; + return need_swap ? bswap_32(*u32) : *u32; case 8: - u64 = ptr + offset; - return need_swap ? bswap_64(*u64) : *u64; + u64 = ptr + offset; + return need_swap ? bswap_64(*u64) : *u64; default: - return 0; + return 0; } } int64_t elf_access_signed(struct elf_binary *elf, const void *ptr, - uint64_t offset, size_t size) + uint64_t offset, size_t size) { int need_swap = elf_swap(elf); const int8_t *s8; @@ -43,22 +43,22 @@ int64_t elf_access_signed(struct elf_binary *elf, const void *ptr, const int32_t *s32; const int64_t *s64; - switch (size) + switch ( size ) { case 1: - s8 = ptr + offset; - return *s8; + s8 = ptr + offset; + return *s8; case 2: - s16 = ptr + offset; - return need_swap ? bswap_16(*s16) : *s16; + s16 = ptr + offset; + return need_swap ? bswap_16(*s16) : *s16; case 4: - s32 = ptr + offset; - return need_swap ? bswap_32(*s32) : *s32; + s32 = ptr + offset; + return need_swap ? bswap_32(*s32) : *s32; case 8: - s64 = ptr + offset; - return need_swap ? bswap_64(*s64) : *s64; + s64 = ptr + offset; + return need_swap ? bswap_64(*s64) : *s64; default: - return 0; + return 0; } } @@ -88,11 +88,12 @@ const elf_shdr *elf_shdr_by_name(struct elf_binary *elf, const char *name) const char *sname; int i; - for (i = 0; i < count; i++) { - shdr = elf_shdr_by_index(elf, i); - sname = elf_section_name(elf, shdr); - if (sname && 0 == strcmp(sname, name)) - return shdr; + for ( i = 0; i < count; i++ ) + { + shdr = elf_shdr_by_index(elf, i); + sname = elf_section_name(elf, shdr); + if ( sname && !strcmp(sname, name) ) + return shdr; } return NULL; } @@ -100,31 +101,35 @@ const elf_shdr *elf_shdr_by_name(struct elf_binary *elf, const char *name) const elf_shdr *elf_shdr_by_index(struct elf_binary *elf, int index) { uint64_t count = elf_shdr_count(elf); - const void *ptr = NULL; + const void *ptr; - if (index < count) - ptr = elf->image - + elf_uval(elf, elf->ehdr, e_shoff) - + elf_uval(elf, elf->ehdr, e_shentsize) * index; + if ( index >= count ) + return NULL; + + ptr = (elf->image + + elf_uval(elf, elf->ehdr, e_shoff) + + elf_uval(elf, elf->ehdr, e_shentsize) * index); return ptr; } const elf_phdr *elf_phdr_by_index(struct elf_binary *elf, int index) { uint64_t count = elf_uval(elf, elf->ehdr, e_phnum); - const void *ptr = NULL; + const void *ptr; - if (index < count) - ptr = elf->image - + elf_uval(elf, elf->ehdr, e_phoff) - + elf_uval(elf, elf->ehdr, e_phentsize) * index; + if ( index >= count ) + return NULL; + + ptr = (elf->image + + elf_uval(elf, elf->ehdr, e_phoff) + + elf_uval(elf, elf->ehdr, e_phentsize) * index); return ptr; } const char *elf_section_name(struct elf_binary *elf, const elf_shdr * shdr) { - if (NULL == elf->sec_strtab) - return "unknown"; + if ( elf->sec_strtab == NULL ) + return "unknown"; return elf->sec_strtab + elf_uval(elf, shdr, sh_name); } @@ -136,7 +141,7 @@ const void *elf_section_start(struct elf_binary *elf, const elf_shdr * shdr) const void *elf_section_end(struct elf_binary *elf, const elf_shdr * shdr) { return elf->image - + elf_uval(elf, shdr, sh_offset) + elf_uval(elf, shdr, sh_size); + + elf_uval(elf, shdr, sh_offset) + elf_uval(elf, shdr, sh_size); } const elf_sym *elf_sym_by_name(struct elf_binary *elf, const char *symbol) @@ -146,16 +151,16 @@ const elf_sym *elf_sym_by_name(struct elf_binary *elf, const char *symbol) const elf_sym *sym; uint64_t info, name; - for (; ptr < end; ptr += elf_size(elf, sym)) + for ( ; ptr < end; ptr += elf_size(elf, sym) ) { - sym = ptr; - info = elf_uval(elf, sym, st_info); - name = elf_uval(elf, sym, st_name); - if (ELF32_ST_BIND(info) != STB_GLOBAL) - continue; - if (strcmp(elf->sym_strtab + name, symbol) != 0) - continue; - return sym; + sym = ptr; + info = elf_uval(elf, sym, st_info); + name = elf_uval(elf, sym, st_name); + if ( ELF32_ST_BIND(info) != STB_GLOBAL ) + continue; + if ( strcmp(elf->sym_strtab + name, symbol) ) + continue; + return sym; } return NULL; } @@ -192,9 +197,9 @@ uint64_t elf_note_numeric(struct elf_binary *elf, const elf_note * note) case 2: case 4: case 8: - return elf_access_unsigned(elf, desc, 0, descsz); + return elf_access_unsigned(elf, desc, 0, descsz); default: - return 0; + return 0; } } const elf_note *elf_note_next(struct elf_binary *elf, const elf_note * note) @@ -211,9 +216,7 @@ int elf_is_elfbinary(const void *image) { const Elf32_Ehdr *ehdr = image; - if (IS_ELF(*ehdr)) - return 1; - return 0; + return IS_ELF(*ehdr); } int elf_phdr_is_loadable(struct elf_binary *elf, const elf_phdr * phdr) @@ -223,3 +226,13 @@ int elf_phdr_is_loadable(struct elf_binary *elf, const elf_phdr * phdr) return ((p_type == PT_LOAD) && (p_flags & (PF_W | PF_X)) != 0); } + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/common/memory.c b/xen/common/memory.c index 78887e19a6..fcd483818d 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -175,11 +175,13 @@ int guest_remove_page(struct domain *d, unsigned long gmfn) if ( unlikely(!page_is_removable(page)) ) { + shadow_drop_references(d, page); /* We'll make this a guest-visible error in future, so take heed! */ - gdprintk(XENLOG_INFO, "Dom%d freeing in-use page %lx (pseudophys %lx):" - " count=%lx type=%lx\n", - d->domain_id, mfn, get_gpfn_from_mfn(mfn), - (unsigned long)page->count_info, page->u.inuse.type_info); + if ( !page_is_removable(page) ) + gdprintk(XENLOG_INFO, "Dom%d freeing in-use page %lx " + "(pseudophys %lx): count=%lx type=%lx\n", + d->domain_id, mfn, get_gpfn_from_mfn(mfn), + (unsigned long)page->count_info, page->u.inuse.type_info); } guest_physmap_remove_page(d, gmfn, mfn); diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index 01eda8a06d..03045963c9 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -72,10 +72,17 @@ static DEFINE_SPINLOCK(console_lock); * Note, in the above algorithm, to disable rate limiting simply make * the lower threshold equal to the upper. */ +#ifdef NDEBUG #define XENLOG_UPPER_THRESHOLD 2 /* Do not print INFO and DEBUG */ #define XENLOG_LOWER_THRESHOLD 2 /* Always print ERR and WARNING */ #define XENLOG_GUEST_UPPER_THRESHOLD 2 /* Do not print INFO and DEBUG */ #define XENLOG_GUEST_LOWER_THRESHOLD 0 /* Rate-limit ERR and WARNING */ +#else +#define XENLOG_UPPER_THRESHOLD 4 /* Do not discard anything */ +#define XENLOG_LOWER_THRESHOLD 4 /* Print everything */ +#define XENLOG_GUEST_UPPER_THRESHOLD 4 /* Do not discard anything */ +#define XENLOG_GUEST_LOWER_THRESHOLD 4 /* Print everything */ +#endif /* * The XENLOG_DEFAULT is the default given to printks that * do not have any print level associated with them. @@ -102,7 +109,7 @@ static void parse_guest_loglvl(char *s); custom_param("loglvl", parse_loglvl); custom_param("guest_loglvl", parse_guest_loglvl); -static atomic_t print_everything = ATOMIC_INIT(1); +static atomic_t print_everything = ATOMIC_INIT(0); #define ___parse_loglvl(s, ps, lvlstr, lvlnum) \ if ( !strncmp((s), (lvlstr), strlen(lvlstr)) ) { \ @@ -223,7 +230,7 @@ int console_steal(int handle, void (*fn)(const char *)) if ( (handle == -1) || (handle != sercon_handle) ) return 0; - if ( serial_steal_fn == NULL ) + if ( serial_steal_fn != NULL ) return -EBUSY; serial_steal_fn = fn; @@ -569,9 +576,6 @@ void console_endboot(void) /* Serial input is directed to DOM0 by default. */ switch_serial_input(); - - /* Now we implement the logging thresholds. */ - console_end_log_everything(); } void console_start_log_everything(void) diff --git a/xen/include/asm-ia64/config.h b/xen/include/asm-ia64/config.h index 063e6e33eb..5010a86e7b 100644 --- a/xen/include/asm-ia64/config.h +++ b/xen/include/asm-ia64/config.h @@ -183,11 +183,7 @@ void sort_main_extable(void); #define find_first_set_bit(x) (ffs(x)-1) // FIXME: Is this right??? // see drivers/char/console.c -#ifndef VALIDATE_VT #define OPT_CONSOLE_STR "com1" -#else -#define OPT_CONSOLE_STR "com2" -#endif #define __nocast diff --git a/xen/include/asm-ia64/domain.h b/xen/include/asm-ia64/domain.h index 2090908bf2..66f9caec2e 100644 --- a/xen/include/asm-ia64/domain.h +++ b/xen/include/asm-ia64/domain.h @@ -162,7 +162,6 @@ struct arch_vcpu { unsigned long irr[4]; /* Interrupt request register. */ unsigned long insvc[4]; /* Interrupt in service. */ unsigned long iva; - unsigned long dcr; unsigned long domain_itm; unsigned long domain_itm_last; @@ -175,6 +174,7 @@ struct arch_vcpu { unsigned long metaphysical_rr4; // from arch_domain (so is pinned) unsigned long metaphysical_saved_rr0; // from arch_domain (so is pinned) unsigned long metaphysical_saved_rr4; // from arch_domain (so is pinned) + unsigned long fp_psr; // used for lazy float register int breakimm; // from arch_domain (so is pinned) int starting_rid; /* first RID assigned to domain */ int ending_rid; /* one beyond highest RID assigned to domain */ @@ -199,9 +199,6 @@ struct arch_vcpu { struct page_info* vhpt_page; unsigned long vhpt_entries; #endif -#ifdef CONFIG_XEN_IA64_TLBFLUSH_CLOCK - u32 tlbflush_timestamp; -#endif #define INVALID_PROCESSOR INT_MAX int last_processor; }; diff --git a/xen/include/asm-ia64/flushtlb.h b/xen/include/asm-ia64/flushtlb.h index 0966d72711..b470ac1615 100644 --- a/xen/include/asm-ia64/flushtlb.h +++ b/xen/include/asm-ia64/flushtlb.h @@ -32,6 +32,7 @@ extern volatile u32 tlbflush_clock; #define tlbflush_current_time() tlbflush_clock u32 tlbflush_clock_inc_and_return(void); +void new_tlbflush_clock_period(void); static inline void tlbflush_update_time(volatile u32* time, u32 timestamp) diff --git a/xen/include/asm-ia64/kexec.h b/xen/include/asm-ia64/kexec.h deleted file mode 100644 index 45756e8f64..0000000000 --- a/xen/include/asm-ia64/kexec.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef __IA64_KEXEC_H__ -#define __IA64_KEXEC_H__ - -#include /* for printk() used in stub */ -#include -#include -#include - -static inline void machine_kexec(xen_kexec_image_t *image) -{ - printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__); -} - -#endif /* __IA64_KEXEC_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ - diff --git a/xen/include/asm-ia64/linux-xen/asm/README.origin b/xen/include/asm-ia64/linux-xen/asm/README.origin index 23aa5b3ef4..e843a71b92 100644 --- a/xen/include/asm-ia64/linux-xen/asm/README.origin +++ b/xen/include/asm-ia64/linux-xen/asm/README.origin @@ -18,6 +18,7 @@ meminit.h -> linux/include/asm-ia64/meminit.h numa.h -> linux/include/asm-ia64/numa.h page.h -> linux/include/asm-ia64/page.h pal.h -> linux/include/asm-ia64/pal.h +percpu.h -> linux/include/asm-ia64/percpu.h pgalloc.h -> linux/include/asm-ia64/pgalloc.h pgtable.h -> linux/include/asm-ia64/pgtable.h processor.h -> linux/include/asm-ia64/processor.h diff --git a/xen/include/asm-ia64/linux-xen/asm/io.h b/xen/include/asm-ia64/linux-xen/asm/io.h index 3ad22c0547..3182a944aa 100644 --- a/xen/include/asm-ia64/linux-xen/asm/io.h +++ b/xen/include/asm-ia64/linux-xen/asm/io.h @@ -49,7 +49,7 @@ #ifdef XEN /* Offset to IO port; do not catch error. */ -#define IO_SPACE_SPARSE_DECODING(off) ((((off) >> 12) << 2) | (off & 0x3)) +#define IO_SPACE_SPARSE_DECODING(off) ((((off) >> 12) << 2) | ((off) & 0x3)) #define IO_SPACE_SPARSE_PORTS_PER_PAGE (0x4 << (PAGE_SHIFT - 12)) #endif diff --git a/xen/include/asm-ia64/linux/asm/percpu.h b/xen/include/asm-ia64/linux-xen/asm/percpu.h similarity index 93% rename from xen/include/asm-ia64/linux/asm/percpu.h rename to xen/include/asm-ia64/linux-xen/asm/percpu.h index 2b14dee29c..4e11b3cd5d 100644 --- a/xen/include/asm-ia64/linux/asm/percpu.h +++ b/xen/include/asm-ia64/linux-xen/asm/percpu.h @@ -43,6 +43,9 @@ DECLARE_PER_CPU(unsigned long, local_per_cpu_offset); #define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu])) #define __get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __ia64_per_cpu_var(local_per_cpu_offset))) +#ifdef XEN +#define per_cpu_addr(var, cpu) (RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu])) +#endif extern void percpu_modcopy(void *pcpudst, const void *src, unsigned long size); extern void setup_per_cpu_areas (void); @@ -67,6 +70,8 @@ extern void *per_cpu_init(void); */ #define __ia64_per_cpu_var(var) (per_cpu__##var) +DECLARE_PER_CPU(struct vcpu *, fp_owner); + #endif /* !__ASSEMBLY__ */ #endif /* _ASM_IA64_PERCPU_H */ diff --git a/xen/include/asm-ia64/linux-xen/linux/efi.h b/xen/include/asm-ia64/linux-xen/linux/efi.h index 73781ec165..2eb12715a1 100644 --- a/xen/include/asm-ia64/linux-xen/linux/efi.h +++ b/xen/include/asm-ia64/linux-xen/linux/efi.h @@ -280,7 +280,11 @@ efi_guidcmp (efi_guid_t left, efi_guid_t right) static inline char * efi_guid_unparse(efi_guid_t *guid, char *out) { +#ifndef XEN sprintf(out, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", +#else + snprintf(out, 37, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", +#endif guid->b[3], guid->b[2], guid->b[1], guid->b[0], guid->b[5], guid->b[4], guid->b[7], guid->b[6], guid->b[8], guid->b[9], guid->b[10], guid->b[11], diff --git a/xen/include/asm-ia64/linux/asm/README.origin b/xen/include/asm-ia64/linux/asm/README.origin index 48ca126508..1167eab7d2 100644 --- a/xen/include/asm-ia64/linux/asm/README.origin +++ b/xen/include/asm-ia64/linux/asm/README.origin @@ -28,7 +28,6 @@ numnodes.h -> linux/include/asm-ia64/numnodes.h param.h -> linux/include/asm-ia64/param.h patch.h -> linux/include/asm-ia64/patch.h pci.h -> linux/include/asm-ia64/pci.h -percpu.h -> linux/include/asm-ia64/percpu.h rse.h -> linux/include/asm-ia64/rse.h sal.h -> linux/include/asm-ia64/sal.h sections.h -> linux/include/asm-ia64/sections.h diff --git a/xen/include/asm-ia64/vcpu.h b/xen/include/asm-ia64/vcpu.h index 1f0684263a..7b99f0b5bb 100644 --- a/xen/include/asm-ia64/vcpu.h +++ b/xen/include/asm-ia64/vcpu.h @@ -20,6 +20,7 @@ extern u64 cycle_to_ns(u64 cycle); #define VCPU(_v,_x) (_v->arch.privregs->_x) #define PSCB(_v,_x) VCPU(_v,_x) #define PSCBX(_v,_x) (_v->arch._x) +#define FP_PSR(_v) PSCBX(_v, fp_psr) #define SPURIOUS_VECTOR 0xf diff --git a/xen/include/asm-ia64/vmmu.h b/xen/include/asm-ia64/vmmu.h index 4b86a33711..905d122f68 100644 --- a/xen/include/asm-ia64/vmmu.h +++ b/xen/include/asm-ia64/vmmu.h @@ -271,6 +271,7 @@ extern thash_data_t *thash_find_next_overlap(thash_cb_t *hcb); * */ extern void thash_purge_entries(struct vcpu *v, u64 va, u64 ps); +extern void thash_purge_entries_remote(struct vcpu *v, u64 va, u64 ps); extern void thash_purge_and_insert(struct vcpu *v, u64 pte, u64 itir, u64 ifa, int type); /* @@ -295,7 +296,7 @@ extern u64 machine_thash(PTA pta, u64 va); extern void purge_machine_tc_by_domid(domid_t domid); extern void machine_tlb_insert(struct vcpu *d, thash_data_t *tlb); extern ia64_rr vmmu_get_rr(struct vcpu *vcpu, u64 va); -extern void init_domain_tlb(struct vcpu *d); +extern int init_domain_tlb(struct vcpu *d); extern void free_domain_tlb(struct vcpu *v); extern thash_data_t * vsa_thash(PTA vpta, u64 va, u64 vrr, u64 *tag); extern thash_data_t * vhpt_lookup(u64 va); diff --git a/xen/include/asm-ia64/vmx.h b/xen/include/asm-ia64/vmx.h index 4e0971278a..5cd0e8c9bf 100644 --- a/xen/include/asm-ia64/vmx.h +++ b/xen/include/asm-ia64/vmx.h @@ -31,7 +31,7 @@ extern void identify_vmx_feature(void); extern unsigned int vmx_enabled; extern void vmx_init_env(void); -extern void vmx_final_setup_guest(struct vcpu *v); +extern int vmx_final_setup_guest(struct vcpu *v); extern void vmx_save_state(struct vcpu *v); extern void vmx_load_state(struct vcpu *v); extern void vmx_setup_platform(struct domain *d); diff --git a/xen/include/asm-ia64/vmx_mm_def.h b/xen/include/asm-ia64/vmx_mm_def.h index 21cf118b54..4736908fda 100644 --- a/xen/include/asm-ia64/vmx_mm_def.h +++ b/xen/include/asm-ia64/vmx_mm_def.h @@ -103,7 +103,7 @@ #define VA_MATTR_WC 0x6 #define VA_MATTR_NATPAGE 0x7 -#define VRN_MASK 0xe000000000000000L +#define VRN_MASK 0xe000000000000000 #define PTA_BASE_MASK 0x3fffffffffffL #define PTA_BASE_SHIFT 15 #define VHPT_OFFSET_MASK 0x7fff @@ -114,6 +114,7 @@ #define HPA_MAPPING_ATTRIBUTE 0x61 //ED:0;AR:0;PL:0;D:1;A:1;P:1 #define VPN_2_VRN(vpn) ((vpn << PPN_SHIFT) >> IA64_VRN_SHIFT) +#ifndef __ASSEMBLY__ typedef enum { INSTRUCTION, DATA, REGISTER } miss_type; //typedef enum { MVHPT, STLB } vtlb_loc_type_t; @@ -169,5 +170,6 @@ bits_v(uint64_t v, uint32_t bs, uint32_t be) "M" ((len))); \ ret; \ }) +#endif #endif diff --git a/xen/include/asm-ia64/vmx_vcpu.h b/xen/include/asm-ia64/vmx_vcpu.h index 24b3b60578..fda5e82389 100644 --- a/xen/include/asm-ia64/vmx_vcpu.h +++ b/xen/include/asm-ia64/vmx_vcpu.h @@ -126,17 +126,12 @@ extern void dnat_page_consumption(VCPU * vcpu, uint64_t vadr); extern void data_page_not_present(VCPU * vcpu, u64 vadr); extern void inst_page_not_present(VCPU * vcpu, u64 vadr); extern void data_access_rights(VCPU * vcpu, u64 vadr); +extern void vmx_ia64_set_dcr(VCPU * v); /************************************************************************** VCPU control register access routines **************************************************************************/ -static inline IA64FAULT vmx_vcpu_get_dcr(VCPU * vcpu, u64 * pval) -{ - *pval = VCPU(vcpu, dcr); - return IA64_NO_FAULT; -} - static inline IA64FAULT vmx_vcpu_get_itm(VCPU * vcpu, u64 * pval) { *pval = VCPU(vcpu, itm); @@ -233,20 +228,6 @@ static inline IA64FAULT vmx_vcpu_get_lrr1(VCPU * vcpu, u64 * pval) return IA64_NO_FAULT; } -static inline IA64FAULT vmx_vcpu_set_dcr(VCPU * vcpu, u64 val) -{ - u64 mdcr, mask; - VCPU(vcpu, dcr) = val; - /* All vDCR bits will go to mDCR, except for be/pp/dm bits */ - mdcr = ia64_get_dcr(); - /* Machine dcr.dm masked to handle guest ld.s on tr mapped page */ - mask = IA64_DCR_BE | IA64_DCR_PP | IA64_DCR_DM; - mdcr = (mdcr & mask) | (val & (~mask)); - ia64_set_dcr(mdcr); - VMX(vcpu, mdcr) = mdcr; - return IA64_NO_FAULT; -} - static inline IA64FAULT vmx_vcpu_set_itm(VCPU * vcpu, u64 val) { vtm_set_itm(vcpu, val); diff --git a/xen/include/asm-ia64/vmx_vpd.h b/xen/include/asm-ia64/vmx_vpd.h index 8e4eb4f55c..e8876bb154 100644 --- a/xen/include/asm-ia64/vmx_vpd.h +++ b/xen/include/asm-ia64/vmx_vpd.h @@ -86,16 +86,7 @@ struct arch_vmx_struct { unsigned long cr_isr; /* for emulation */ unsigned long cause; unsigned long opcode; - -// unsigned long mrr5; -// unsigned long mrr6; -// unsigned long mrr7; - unsigned long mdcr; unsigned long mpta; -// unsigned long rfi_pfs; -// unsigned long rfi_iip; -// unsigned long rfi_ipsr; -// unsigned long rfi_ifs; unsigned long flags; unsigned long xen_port; unsigned char xtp; diff --git a/xen/include/asm-ia64/xenkregs.h b/xen/include/asm-ia64/xenkregs.h index d2dcd2bc84..4050bb700f 100644 --- a/xen/include/asm-ia64/xenkregs.h +++ b/xen/include/asm-ia64/xenkregs.h @@ -13,6 +13,10 @@ #define IA64_PSR_VM_BIT 46 #define IA64_PSR_VM (__IA64_UL(1) << IA64_PSR_VM_BIT) +#define IA64_DEFAULT_DCR_BITS (IA64_DCR_PP | IA64_DCR_LC | IA64_DCR_DM | \ + IA64_DCR_DP | IA64_DCR_DK | IA64_DCR_DX | \ + IA64_DCR_DR | IA64_DCR_DA | IA64_DCR_DD) + /* Interruption Function State */ #define IA64_IFS_V_BIT 63 #define IA64_IFS_V (__IA64_UL(1) << IA64_IFS_V_BIT) diff --git a/xen/include/asm-powerpc/kexec.h b/xen/include/asm-powerpc/kexec.h deleted file mode 100644 index f228972047..0000000000 --- a/xen/include/asm-powerpc/kexec.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _ASM_KEXEC_H__ -#define _ASM_KEXEC_H__ - -#include /* for printk() used in stub */ -#include -#include -#include - -static inline void machine_kexec(xen_kexec_image_t *image) -{ - printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__); -} - -#endif /* _ASM_KEXEC_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ - diff --git a/xen/include/asm-x86/config.h b/xen/include/asm-x86/config.h index 71e3dd8e4a..34cd754186 100644 --- a/xen/include/asm-x86/config.h +++ b/xen/include/asm-x86/config.h @@ -145,9 +145,9 @@ * Compatibility guest area layout: * 0x0000000000000000 - 0x00000000f57fffff [3928MB, PML4:0] * Guest-defined use. - * 0x0000000f58000000 - 0x00000000ffffffff [168MB, PML4:0] + * 0x00000000f5800000 - 0x00000000ffffffff [168MB, PML4:0] * Read-only machine-to-phys translation table (GUEST ACCESSIBLE). - * 0x0000000000000000 - 0x00000000ffffffff [508GB, PML4:0] + * 0x0000000100000000 - 0x0000007fffffffff [508GB, PML4:0] * Unused. * 0x0000008000000000 - 0x000000ffffffffff [512GB, 2^39 bytes, PML4:1] * Hypercall argument translation area. diff --git a/xen/include/asm-x86/cpufeature.h b/xen/include/asm-x86/cpufeature.h index a6f2f757bc..754c6dbf5a 100644 --- a/xen/include/asm-x86/cpufeature.h +++ b/xen/include/asm-x86/cpufeature.h @@ -93,6 +93,7 @@ #define X86_FEATURE_LAHF_LM (6*32+ 0) /* LAHF/SAHF in long mode */ #define X86_FEATURE_CMP_LEGACY (6*32+ 1) /* If yes HyperThreading not valid */ #define X86_FEATURE_SVME (6*32+ 2) /* Secure Virtual Machine */ +#define X86_FEATURE_FFXSR (6*32+25) /* FFXSR instruction optimizations */ #define cpu_has(c, bit) test_bit(bit, (c)->x86_capability) #define boot_cpu_has(bit) test_bit(bit, boot_cpu_data.x86_capability) diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index 83315353e1..3237f53e8e 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -58,19 +58,22 @@ extern void toggle_guest_mode(struct vcpu *); */ extern void hypercall_page_initialise(struct domain *d, void *); +/************************************************/ +/* shadow paging extension */ +/************************************************/ struct shadow_domain { - u32 mode; /* flags to control shadow operation */ spinlock_t lock; /* shadow domain lock */ int locker; /* processor which holds the lock */ const char *locker_function; /* Func that took it */ + unsigned int opt_flags; /* runtime tunable optimizations on/off */ + struct list_head pinned_shadows; + + /* Memory allocation */ struct list_head freelists[SHADOW_MAX_ORDER + 1]; struct list_head p2m_freelist; - struct list_head p2m_inuse; - struct list_head pinned_shadows; unsigned int total_pages; /* number of pages allocated */ unsigned int free_pages; /* number of pages on freelists */ - unsigned int p2m_pages; /* number of pages in p2m map */ - unsigned int opt_flags; /* runtime tunable optimizations on/off */ + unsigned int p2m_pages; /* number of pages allocates to p2m */ /* Shadow hashtable */ struct shadow_page_info **hash_table; @@ -85,6 +88,65 @@ struct shadow_domain { unsigned int dirty_count; }; +struct shadow_vcpu { +#if CONFIG_PAGING_LEVELS >= 3 + /* PAE guests: per-vcpu shadow top-level table */ + l3_pgentry_t l3table[4] __attribute__((__aligned__(32))); + /* PAE guests: per-vcpu cache of the top-level *guest* entries */ + l3_pgentry_t gl3e[4] __attribute__((__aligned__(32))); +#endif + /* Non-PAE guests: pointer to guest top-level pagetable */ + void *guest_vtable; + /* Last MFN that we emulated a write to. */ + unsigned long last_emulated_mfn; + /* MFN of the last shadow that we shot a writeable mapping in */ + unsigned long last_writeable_pte_smfn; +}; + +/************************************************/ +/* p2m handling */ +/************************************************/ + +struct p2m_domain { + /* Lock that protects updates to the p2m */ + spinlock_t lock; + int locker; /* processor which holds the lock */ + const char *locker_function; /* Func that took it */ + + /* Pages used to construct the p2m */ + struct list_head pages; + + /* Functions to call to get or free pages for the p2m */ + struct page_info * (*alloc_page )(struct domain *d); + void (*free_page )(struct domain *d, + struct page_info *pg); + + /* Highest guest frame that's ever been mapped in the p2m */ + unsigned long max_mapped_pfn; +}; + +/************************************************/ +/* common paging data structure */ +/************************************************/ +struct paging_domain { + u32 mode; /* flags to control paging operation */ + + /* extension for shadow paging support */ + struct shadow_domain shadow; + + /* Other paging assistance code will have structs here */ +}; + +struct paging_vcpu { + /* Pointers to mode-specific entry points. */ + struct paging_mode *mode; + /* HVM guest: paging enabled (CR0.PG)? */ + unsigned int translate_enabled:1; + + /* paging support extension */ + struct shadow_vcpu shadow; +}; + struct arch_domain { l1_pgentry_t *mm_perdomain_pt; @@ -108,12 +170,11 @@ struct arch_domain struct hvm_domain hvm_domain; - struct shadow_domain shadow; + struct paging_domain paging; + struct p2m_domain p2m ; /* Shadow translated domain: P2M mapping */ pagetable_t phys_table; - /* Highest guest frame that's ever been mapped in the p2m */ - unsigned long max_mapped_pfn; /* Pseudophysical e820 map (XENMEM_memory_map). */ struct e820entry e820[3]; @@ -139,21 +200,6 @@ struct pae_l3_cache { }; #define pae_l3_cache_init(c) ((void)0) #endif -struct shadow_vcpu { -#if CONFIG_PAGING_LEVELS >= 3 - /* PAE guests: per-vcpu shadow top-level table */ - l3_pgentry_t l3table[4] __attribute__((__aligned__(32))); -#endif - /* Pointers to mode-specific entry points. */ - struct shadow_paging_mode *mode; - /* Last MFN that we emulated a write to. */ - unsigned long last_emulated_mfn; - /* MFN of the last shadow that we shot a writeable mapping in */ - unsigned long last_writeable_pte_smfn; - /* HVM guest: paging enabled (CR0.PG)? */ - unsigned int translate_enabled:1; -}; - struct arch_vcpu { /* Needs 16-byte aligment for FXSAVE/FXRSTOR. */ @@ -200,12 +246,10 @@ struct arch_vcpu pagetable_t monitor_table; /* (MFN) hypervisor PT (for HVM) */ unsigned long cr3; /* (MA) value to install in HW CR3 */ - void *guest_vtable; /* virtual addr of pagetable */ - /* Current LDT details. */ unsigned long shadow_ldt_mapcnt; - struct shadow_vcpu shadow; + struct paging_vcpu paging; } __cacheline_aligned; /* shorthands to improve code legibility */ diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h index 1e8093dafa..125c73d2ce 100644 --- a/xen/include/asm-x86/hvm/hvm.h +++ b/xen/include/asm-x86/hvm/hvm.h @@ -153,6 +153,7 @@ void hvm_domain_destroy(struct domain *d); int hvm_vcpu_initialise(struct vcpu *v); void hvm_vcpu_destroy(struct vcpu *v); +void hvm_vcpu_reset(struct vcpu *vcpu); void hvm_send_assist_req(struct vcpu *v); diff --git a/xen/include/asm-x86/hvm/support.h b/xen/include/asm-x86/hvm/support.h index 6d57140fae..6fe753458c 100644 --- a/xen/include/asm-x86/hvm/support.h +++ b/xen/include/asm-x86/hvm/support.h @@ -221,23 +221,37 @@ typedef int (*hvm_save_handler) (struct domain *d, typedef int (*hvm_load_handler) (struct domain *d, hvm_domain_context_t *h); -/* Init-time function to declare a pair of handlers for a type */ +/* Init-time function to declare a pair of handlers for a type, + * and the maximum buffer space needed to save this type of state */ void hvm_register_savevm(uint16_t typecode, const char *name, hvm_save_handler save_state, - hvm_load_handler load_state); + hvm_load_handler load_state, + size_t size, int kind); -/* Syntactic sugar around that function */ -#define HVM_REGISTER_SAVE_RESTORE(_x, _save, _load) \ -static int __hvm_register_##_x##_save_and_restore(void) \ -{ \ - hvm_register_savevm(HVM_SAVE_CODE(_x), #_x, &_save, &_load); \ - return 0; \ -} \ +/* The space needed for saving can be per-domain or per-vcpu: */ +#define HVMSR_PER_DOM 0 +#define HVMSR_PER_VCPU 1 + +/* Syntactic sugar around that function: specify the max number of + * saves, and this calculates the size of buffer needed */ +#define HVM_REGISTER_SAVE_RESTORE(_x, _save, _load, _num, _k) \ +static int __hvm_register_##_x##_save_and_restore(void) \ +{ \ + hvm_register_savevm(HVM_SAVE_CODE(_x), \ + #_x, \ + &_save, \ + &_load, \ + (_num) * (HVM_SAVE_LENGTH(_x) \ + + sizeof (struct hvm_save_descriptor)), \ + _k); \ + return 0; \ +} \ __initcall(__hvm_register_##_x##_save_and_restore); /* Entry points for saving and restoring HVM domain state */ +size_t hvm_save_size(struct domain *d); int hvm_save(struct domain *d, hvm_domain_context_t *h); int hvm_load(struct domain *d, hvm_domain_context_t *h); diff --git a/xen/include/asm-x86/hvm/vlapic.h b/xen/include/asm-x86/hvm/vlapic.h index 4700f63fb5..6d174ebfd6 100644 --- a/xen/include/asm-x86/hvm/vlapic.h +++ b/xen/include/asm-x86/hvm/vlapic.h @@ -78,6 +78,8 @@ int cpu_get_apic_interrupt(struct vcpu *v, int *mode); int vlapic_init(struct vcpu *v); void vlapic_destroy(struct vcpu *v); +void vlapic_reset(struct vlapic *vlapic); + void vlapic_msr_set(struct vlapic *vlapic, uint64_t value); int vlapic_accept_pic_intr(struct vcpu *v); diff --git a/xen/include/asm-x86/hvm/vpt.h b/xen/include/asm-x86/hvm/vpt.h index 78c7b536d4..02bc3fa05c 100644 --- a/xen/include/asm-x86/hvm/vpt.h +++ b/xen/include/asm-x86/hvm/vpt.h @@ -94,14 +94,12 @@ typedef struct RTCState { struct periodic_time pt; } RTCState; -#define FREQUENCE_PMTIMER 3579545 +#define FREQUENCE_PMTIMER 3579545 /* Timer should run at 3.579545 MHz */ typedef struct PMTState { - uint32_t pm1_timer; - uint32_t pm1_status; - uint64_t last_gtime; - struct timer timer; - uint64_t scale; - struct vcpu *vcpu; + struct hvm_hw_pmtimer pm; /* 32bit timer value */ + struct vcpu *vcpu; /* Keeps sync with this vcpu's guest-time */ + uint64_t last_gtime; /* Last (guest) time we updated the timer */ + uint64_t scale; /* Multiplier to get from tsc to timer ticks */ } PMTState; struct pl_time { /* platform time */ @@ -134,8 +132,6 @@ void rtc_migrate_timers(struct vcpu *v); void rtc_deinit(struct domain *d); int is_rtc_periodic_irq(void *opaque); void pmtimer_init(struct vcpu *v, int base); -void pmtimer_migrate_timers(struct vcpu *v); -void pmtimer_deinit(struct domain *d); void hpet_migrate_timers(struct vcpu *v); void hpet_init(struct vcpu *v); diff --git a/xen/include/asm-x86/kexec.h b/xen/include/asm-x86/kexec.h deleted file mode 100644 index d137337da0..0000000000 --- a/xen/include/asm-x86/kexec.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __X86_KEXEC_H__ -#define __X86_KEXEC_H__ - -#ifdef __x86_64__ -#include -#else -#include -#endif - -#endif /* __X86_KEXEC_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h index 405a753b39..334d581479 100644 --- a/xen/include/asm-x86/mm.h +++ b/xen/include/asm-x86/mm.h @@ -246,6 +246,64 @@ pae_copy_root(struct vcpu *v, l3_pgentry_t *l3tab); int check_descriptor(const struct domain *, struct desc_struct *d); + +/****************************************************************************** + * With shadow pagetables, the different kinds of address start + * to get get confusing. + * + * Virtual addresses are what they usually are: the addresses that are used + * to accessing memory while the guest is running. The MMU translates from + * virtual addresses to machine addresses. + * + * (Pseudo-)physical addresses are the abstraction of physical memory the + * guest uses for allocation and so forth. For the purposes of this code, + * we can largely ignore them. + * + * Guest frame numbers (gfns) are the entries that the guest puts in its + * pagetables. For normal paravirtual guests, they are actual frame numbers, + * with the translation done by the guest. + * + * Machine frame numbers (mfns) are the entries that the hypervisor puts + * in the shadow page tables. + * + * Elsewhere in the xen code base, the name "gmfn" is generally used to refer + * to a "machine frame number, from the guest's perspective", or in other + * words, pseudo-physical frame numbers. However, in the shadow code, the + * term "gmfn" means "the mfn of a guest page"; this combines naturally with + * other terms such as "smfn" (the mfn of a shadow page), gl2mfn (the mfn of a + * guest L2 page), etc... + */ + +/* With this defined, we do some ugly things to force the compiler to + * give us type safety between mfns and gfns and other integers. + * TYPE_SAFE(int foo) defines a foo_t, and _foo() and foo_x() functions + * that translate beween int and foo_t. + * + * It does have some performance cost because the types now have + * a different storage attribute, so may not want it on all the time. */ + +#ifndef NDEBUG +#define TYPE_SAFETY 1 +#endif + +#ifdef TYPE_SAFETY +#define TYPE_SAFE(_type,_name) \ +typedef struct { _type _name; } _name##_t; \ +static inline _name##_t _##_name(_type n) { return (_name##_t) { n }; } \ +static inline _type _name##_x(_name##_t n) { return n._name; } +#else +#define TYPE_SAFE(_type,_name) \ +typedef _type _name##_t; \ +static inline _name##_t _##_name(_type n) { return n; } \ +static inline _type _name##_x(_name##_t n) { return n; } +#endif + +TYPE_SAFE(unsigned long,mfn); + +/* Macro for printk formats: use as printk("%"PRI_mfn"\n", mfn_x(foo)); */ +#define PRI_mfn "05lx" + + /* * The MPT (machine->physical mapping table) is an array of word-sized * values, indexed on machine frame number. It is expected that guest OSes @@ -269,13 +327,12 @@ int check_descriptor(const struct domain *, struct desc_struct *d); #endif #define get_gpfn_from_mfn(mfn) (machine_to_phys_mapping[(mfn)]) - #define mfn_to_gmfn(_d, mfn) \ - ( (shadow_mode_translate(_d)) \ + ( (paging_mode_translate(_d)) \ ? get_gpfn_from_mfn(mfn) \ : (mfn) ) -#define gmfn_to_mfn(_d, gpfn) mfn_x(sh_gfn_to_mfn(_d, gpfn)) +#define gmfn_to_mfn(_d, gpfn) mfn_x(gfn_to_mfn(_d, gpfn)) #define INVALID_MFN (~0UL) diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h new file mode 100644 index 0000000000..89c030977f --- /dev/null +++ b/xen/include/asm-x86/p2m.h @@ -0,0 +1,142 @@ +/****************************************************************************** + * include/asm-x86/paging.h + * + * physical-to-machine mappings for automatically-translated domains. + * + * Copyright (c) 2007 Advanced Micro Devices (Wei Huang) + * Parts of this code are Copyright (c) 2006 by XenSource Inc. + * Parts of this code are Copyright (c) 2006 by Michael A Fetterman + * Parts based on earlier work by Michael A Fetterman, Ian Pratt et al. + * + * 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _XEN_P2M_H +#define _XEN_P2M_H + + +/* The phys_to_machine_mapping is the reversed mapping of MPT for full + * virtualization. It is only used by shadow_mode_translate()==true + * guests, so we steal the address space that would have normally + * been used by the read-only MPT map. + */ +#define phys_to_machine_mapping ((l1_pgentry_t *)RO_MPT_VIRT_START) + + +/* Read the current domain's P2M table. */ +static inline mfn_t gfn_to_mfn_current(unsigned long gfn) +{ + l1_pgentry_t l1e = l1e_empty(); + int ret; + + if ( gfn > current->domain->arch.p2m.max_mapped_pfn ) + return _mfn(INVALID_MFN); + + /* Don't read off the end of the p2m table */ + ASSERT(gfn < (RO_MPT_VIRT_END - RO_MPT_VIRT_START) / sizeof(l1_pgentry_t)); + + ret = __copy_from_user(&l1e, + &phys_to_machine_mapping[gfn], + sizeof(l1e)); + + if ( (ret == 0) && (l1e_get_flags(l1e) & _PAGE_PRESENT) ) + return _mfn(l1e_get_pfn(l1e)); + + return _mfn(INVALID_MFN); +} + +/* Read another domain's P2M table, mapping pages as we go */ +mfn_t gfn_to_mfn_foreign(struct domain *d, unsigned long gpfn); + +/* General conversion function from gfn to mfn */ +static inline mfn_t gfn_to_mfn(struct domain *d, unsigned long gfn) +{ + if ( !paging_mode_translate(d) ) + return _mfn(gfn); + if ( likely(current->domain == d) ) + return gfn_to_mfn_current(gfn); + else + return gfn_to_mfn_foreign(d, gfn); +} + +/* General conversion function from mfn to gfn */ +static inline unsigned long mfn_to_gfn(struct domain *d, mfn_t mfn) +{ + if ( paging_mode_translate(d) ) + return get_gpfn_from_mfn(mfn_x(mfn)); + else + return mfn_x(mfn); +} + +/* Compatibility function for HVM code */ +static inline unsigned long get_mfn_from_gpfn(unsigned long pfn) +{ + return mfn_x(gfn_to_mfn_current(pfn)); +} + +/* Is this guest address an mmio one? (i.e. not defined in p2m map) */ +static inline int mmio_space(paddr_t gpa) +{ + unsigned long gfn = gpa >> PAGE_SHIFT; + return !mfn_valid(mfn_x(gfn_to_mfn_current(gfn))); +} + +/* Translate the frame number held in an l1e from guest to machine */ +static inline l1_pgentry_t +gl1e_to_ml1e(struct domain *d, l1_pgentry_t l1e) +{ + if ( unlikely(paging_mode_translate(d)) ) + l1e = l1e_from_pfn(gmfn_to_mfn(d, l1e_get_pfn(l1e)), + l1e_get_flags(l1e)); + return l1e; +} + + + +/* Init the datastructures for later use by the p2m code */ +void p2m_init(struct domain *d); + +/* Allocate a new p2m table for a domain. + * + * The alloc_page and free_page functions will be used to get memory to + * build the p2m, and to release it again at the end of day. + * + * Returns 0 for success or -errno. */ +int p2m_alloc_table(struct domain *d, + struct page_info * (*alloc_page)(struct domain *d), + void (*free_page)(struct domain *d, struct page_info *pg)); + +/* Return all the p2m resources to Xen. */ +void p2m_teardown(struct domain *d); + +/* Add a page to a domain's p2m table */ +void guest_physmap_add_page(struct domain *d, unsigned long gfn, + unsigned long mfn); + +/* Remove a page from a domain's p2m table */ +void guest_physmap_remove_page(struct domain *d, unsigned long gfn, + unsigned long mfn); + + +#endif /* _XEN_P2M_H */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/include/asm-x86/page.h b/xen/include/asm-x86/page.h index 53ddc287fc..31ec281920 100644 --- a/xen/include/asm-x86/page.h +++ b/xen/include/asm-x86/page.h @@ -208,8 +208,10 @@ typedef struct { u64 pfn; } pagetable_t; #define pagetable_get_paddr(x) ((paddr_t)(x).pfn << PAGE_SHIFT) #define pagetable_get_page(x) mfn_to_page((x).pfn) #define pagetable_get_pfn(x) ((x).pfn) +#define pagetable_get_mfn(x) _mfn(((x).pfn)) #define pagetable_is_null(x) ((x).pfn == 0) #define pagetable_from_pfn(pfn) ((pagetable_t) { (pfn) }) +#define pagetable_from_mfn(mfn) ((pagetable_t) { mfn_x(mfn) }) #define pagetable_from_page(pg) pagetable_from_pfn(page_to_mfn(pg)) #define pagetable_from_paddr(p) pagetable_from_pfn((p)>>PAGE_SHIFT) #define pagetable_null() pagetable_from_pfn(0) @@ -276,9 +278,6 @@ typedef struct { u64 pfn; } pagetable_t; #define __linear_l4_table \ ((l4_pgentry_t *)(__linear_l3_table + l3_linear_offset(LINEAR_PT_VIRT_START))) -#define linear_l1_table __linear_l1_table -#define linear_pg_table linear_l1_table -#define linear_l2_table(v) ((l2_pgentry_t *)(v)->arch.guest_vtable) #ifndef __ASSEMBLY__ #if CONFIG_PAGING_LEVELS == 3 diff --git a/xen/include/asm-x86/paging.h b/xen/include/asm-x86/paging.h new file mode 100644 index 0000000000..63ef49d693 --- /dev/null +++ b/xen/include/asm-x86/paging.h @@ -0,0 +1,376 @@ +/****************************************************************************** + * include/asm-x86/paging.h + * + * Common interface for paging support + * Copyright (c) 2007 Advanced Micro Devices (Wei Huang) + * Parts of this code are Copyright (c) 2006 by XenSource Inc. + * Parts of this code are Copyright (c) 2006 by Michael A Fetterman + * Parts based on earlier work by Michael A Fetterman, Ian Pratt et al. + * + * 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, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _XEN_PAGING_H +#define _XEN_PAGING_H + +#include +#include +#include +#include +#include +#include +#include + +/***************************************************************************** + * Macros to tell which paging mode a domain is in */ + +#define PG_SH_shift 20 +#define PG_HAP_shift 21 +/* We're in one of the shadow modes */ +#define PG_SH_enable (1U << PG_SH_shift) +#define PG_HAP_enable (1U << PG_HAP_shift) + +/* common paging mode bits */ +#define PG_mode_shift 10 +/* Refcounts based on shadow tables instead of guest tables */ +#define PG_refcounts (XEN_DOMCTL_SHADOW_ENABLE_REFCOUNT << PG_mode_shift) +/* Enable log dirty mode */ +#define PG_log_dirty (XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY << PG_mode_shift) +/* Xen does p2m translation, not guest */ +#define PG_translate (XEN_DOMCTL_SHADOW_ENABLE_TRANSLATE << PG_mode_shift) +/* Xen does not steal address space from the domain for its own booking; + * requires VT or similar mechanisms */ +#define PG_external (XEN_DOMCTL_SHADOW_ENABLE_EXTERNAL << PG_mode_shift) + +#define paging_mode_enabled(_d) ((_d)->arch.paging.mode) +#define paging_mode_shadow(_d) ((_d)->arch.paging.mode & PG_SH_enable) +#define paging_mode_hap(_d) ((_d)->arch.paging.mode & PG_HAP_enable) + +#define paging_mode_refcounts(_d) ((_d)->arch.paging.mode & PG_refcounts) +#define paging_mode_log_dirty(_d) ((_d)->arch.paging.mode & PG_log_dirty) +#define paging_mode_translate(_d) ((_d)->arch.paging.mode & PG_translate) +#define paging_mode_external(_d) ((_d)->arch.paging.mode & PG_external) + +/****************************************************************************** + * The equivalent for a particular vcpu of a shadowed domain. */ + +/* Is this vcpu using the P2M table to translate between GFNs and MFNs? + * + * This is true of translated HVM domains on a vcpu which has paging + * enabled. (HVM vcpus with paging disabled are using the p2m table as + * its paging table, so no translation occurs in this case.) + * It is also true for all vcpus of translated PV domains. */ +#define paging_vcpu_mode_translate(_v) ((_v)->arch.paging.translate_enabled) + + + +/***************************************************************************** + * Mode-specific entry points into the shadow code. + * + * These shouldn't be used directly by callers; rather use the functions + * below which will indirect through this table as appropriate. */ + +struct sh_emulate_ctxt; +struct shadow_paging_mode { + void (*detach_old_tables )(struct vcpu *v); + int (*x86_emulate_write )(struct vcpu *v, unsigned long va, + void *src, u32 bytes, + struct sh_emulate_ctxt *sh_ctxt); + int (*x86_emulate_cmpxchg )(struct vcpu *v, unsigned long va, + unsigned long old, + unsigned long new, + unsigned int bytes, + struct sh_emulate_ctxt *sh_ctxt); + int (*x86_emulate_cmpxchg8b )(struct vcpu *v, unsigned long va, + unsigned long old_lo, + unsigned long old_hi, + unsigned long new_lo, + unsigned long new_hi, + struct sh_emulate_ctxt *sh_ctxt); + mfn_t (*make_monitor_table )(struct vcpu *v); + void (*destroy_monitor_table )(struct vcpu *v, mfn_t mmfn); + int (*guess_wrmap )(struct vcpu *v, + unsigned long vaddr, mfn_t gmfn); + /* For outsiders to tell what mode we're in */ + unsigned int shadow_levels; +}; + + +/************************************************/ +/* common paging interface */ +/************************************************/ +struct paging_mode { + int (*page_fault )(struct vcpu *v, unsigned long va, + struct cpu_user_regs *regs); + int (*invlpg )(struct vcpu *v, unsigned long va); + paddr_t (*gva_to_gpa )(struct vcpu *v, unsigned long va); + unsigned long (*gva_to_gfn )(struct vcpu *v, unsigned long va); + void (*update_cr3 )(struct vcpu *v, int do_locking); + void (*update_paging_modes )(struct vcpu *v); + void (*write_p2m_entry )(struct vcpu *v, unsigned long gfn, + l1_pgentry_t *p, l1_pgentry_t new, + unsigned int level); + int (*write_guest_entry )(struct vcpu *v, intpte_t *p, + intpte_t new, mfn_t gmfn); + int (*cmpxchg_guest_entry )(struct vcpu *v, intpte_t *p, + intpte_t *old, intpte_t new, + mfn_t gmfn); + void * (*guest_map_l1e )(struct vcpu *v, unsigned long va, + unsigned long *gl1mfn); + void (*guest_get_eff_l1e )(struct vcpu *v, unsigned long va, + void *eff_l1e); + unsigned int guest_levels; + + /* paging support extension */ + struct shadow_paging_mode shadow; +}; + + +/***************************************************************************** + * Entry points into the paging-assistance code */ + +/* Initialize the paging resource for vcpu struct. It is called by + * vcpu_initialise() in domain.c */ +void paging_vcpu_init(struct vcpu *v); + +/* Set up the paging-assistance-specific parts of a domain struct at + * start of day. Called for every domain from arch_domain_create() */ +void paging_domain_init(struct domain *d); + +/* Handler for paging-control ops: operations from user-space to enable + * and disable ephemeral shadow modes (test mode and log-dirty mode) and + * manipulate the log-dirty bitmap. */ +int paging_domctl(struct domain *d, xen_domctl_shadow_op_t *sc, + XEN_GUEST_HANDLE(void) u_domctl); + +/* Call when destroying a domain */ +void paging_teardown(struct domain *d); + +/* Call once all of the references to the domain have gone away */ +void paging_final_teardown(struct domain *d); + +/* Enable an arbitrary paging-assistance mode. Call once at domain + * creation. */ +int paging_enable(struct domain *d, u32 mode); + + +/* Page fault handler + * Called from pagefault handler in Xen, and from the HVM trap handlers + * for pagefaults. Returns 1 if this fault was an artefact of the + * paging code (and the guest should retry) or 0 if it is not (and the + * fault should be handled elsewhere or passed to the guest). + * + * Note: under shadow paging, this function handles all page faults; + * however, for hardware-assisted paging, this function handles only + * host page faults (i.e. nested page faults). */ +static inline int +paging_fault(unsigned long va, struct cpu_user_regs *regs) +{ + struct vcpu *v = current; + return v->arch.paging.mode->page_fault(v, va, regs); +} + +/* Handle invlpg requests on vcpus. + * Returns 1 if the invlpg instruction should be issued on the hardware, + * or 0 if it's safe not to do so. */ +static inline int paging_invlpg(struct vcpu *v, unsigned long va) +{ + return v->arch.paging.mode->invlpg(v, va); +} + +/* Translate a guest virtual address to the physical address that the + * *guest* pagetables would map it to. */ +static inline paddr_t paging_gva_to_gpa(struct vcpu *v, unsigned long va) +{ + if ( unlikely(!paging_vcpu_mode_translate(v)) ) + return (paddr_t) va; + + return v->arch.paging.mode->gva_to_gpa(v, va); +} + +/* Translate a guest virtual address to the frame number that the + * *guest* pagetables would map it to. */ +static inline unsigned long paging_gva_to_gfn(struct vcpu *v, unsigned long va) +{ + if ( unlikely(!paging_vcpu_mode_translate(v)) ) + return va >> PAGE_SHIFT; + + return v->arch.paging.mode->gva_to_gfn(v, va); +} + +/* Update all the things that are derived from the guest's CR3. + * Called when the guest changes CR3; the caller can then use v->arch.cr3 + * as the value to load into the host CR3 to schedule this vcpu */ +static inline void paging_update_cr3(struct vcpu *v) +{ + v->arch.paging.mode->update_cr3(v, 1); +} + +/* Update all the things that are derived from the guest's CR0/CR3/CR4. + * Called to initialize paging structures if the paging mode + * has changed, and when bringing up a VCPU for the first time. */ +static inline void paging_update_paging_modes(struct vcpu *v) +{ + v->arch.paging.mode->update_paging_modes(v); +} + + +/* Write a new value into the guest pagetable, and update the + * paging-assistance state appropriately. Returns 0 if we page-faulted, + * 1 for success. */ +static inline int paging_write_guest_entry(struct vcpu *v, intpte_t *p, + intpte_t new, mfn_t gmfn) +{ + if ( unlikely(paging_mode_enabled(v->domain) + && v->arch.paging.mode != NULL) ) + return v->arch.paging.mode->write_guest_entry(v, p, new, gmfn); + else + return (!__copy_to_user(p, &new, sizeof(new))); +} + + +/* Cmpxchg a new value into the guest pagetable, and update the + * paging-assistance state appropriately. Returns 0 if we page-faulted, + * 1 if not. N.B. caller should check the value of "old" to see if the + * cmpxchg itself was successful. */ +static inline int paging_cmpxchg_guest_entry(struct vcpu *v, intpte_t *p, + intpte_t *old, intpte_t new, + mfn_t gmfn) +{ + if ( unlikely(paging_mode_enabled(v->domain) + && v->arch.paging.mode != NULL) ) + return v->arch.paging.mode->cmpxchg_guest_entry(v, p, old, new, gmfn); + else + return (!cmpxchg_user(p, *old, new)); +} + +/* Helper function that writes a pte in such a way that a concurrent read + * never sees a half-written entry that has _PAGE_PRESENT set */ +static inline void safe_write_pte(l1_pgentry_t *p, l1_pgentry_t new) +{ +#if CONFIG_PAGING_LEVELS == 3 + /* PAE machines write 64bit PTEs as two 32bit writes. */ + volatile unsigned long *d = (unsigned long *) p; + unsigned long *s = (unsigned long *) &new; + BUILD_BUG_ON(sizeof (l1_pgentry_t) != 2 * sizeof (unsigned long)); + d[0] = 0; + d[1] = s[1]; + d[0] = s[0]; +#else + *p = new; +#endif +} + +/* Atomically write a P2M entry and update the paging-assistance state + * appropriately. */ +static inline void paging_write_p2m_entry(struct domain *d, unsigned long gfn, + l1_pgentry_t *p, l1_pgentry_t new, + unsigned int level) +{ + struct vcpu *v = current; + if ( v->domain != d ) + v = d->vcpu[0]; + if ( likely(paging_mode_enabled(d) && v->arch.paging.mode != NULL) ) + { + return v->arch.paging.mode->write_p2m_entry(v, gfn, p, new, level); + } + else + safe_write_pte(p, new); +} + +/* Print paging-assistance info to the console */ +void paging_dump_domain_info(struct domain *d); +void paging_dump_vcpu_info(struct vcpu *v); + + +/***************************************************************************** + * Access to the guest pagetables */ + +/* Get a mapping of a PV guest's l1e for this virtual address. */ +static inline void * +guest_map_l1e(struct vcpu *v, unsigned long addr, unsigned long *gl1mfn) +{ + l2_pgentry_t l2e; + + if ( unlikely(paging_mode_translate(v->domain)) ) + return v->arch.paging.mode->guest_map_l1e(v, addr, gl1mfn); + + /* Find this l1e and its enclosing l1mfn in the linear map */ + if ( __copy_from_user(&l2e, + &__linear_l2_table[l2_linear_offset(addr)], + sizeof(l2_pgentry_t)) != 0 ) + return NULL; + /* Check flags that it will be safe to read the l1e */ + if ( (l2e_get_flags(l2e) & (_PAGE_PRESENT | _PAGE_PSE)) + != _PAGE_PRESENT ) + return NULL; + *gl1mfn = l2e_get_pfn(l2e); + return &__linear_l1_table[l1_linear_offset(addr)]; +} + +/* Pull down the mapping we got from guest_map_l1e() */ +static inline void +guest_unmap_l1e(struct vcpu *v, void *p) +{ + if ( unlikely(paging_mode_translate(v->domain)) ) + unmap_domain_page(p); +} + +/* Read the guest's l1e that maps this address. */ +static inline void +guest_get_eff_l1e(struct vcpu *v, unsigned long addr, void *eff_l1e) +{ + if ( likely(!paging_mode_translate(v->domain)) ) + { + ASSERT(!paging_mode_external(v->domain)); + if ( __copy_from_user(eff_l1e, + &__linear_l1_table[l1_linear_offset(addr)], + sizeof(l1_pgentry_t)) != 0 ) + *(l1_pgentry_t *)eff_l1e = l1e_empty(); + return; + } + + v->arch.paging.mode->guest_get_eff_l1e(v, addr, eff_l1e); +} + +/* Read the guest's l1e that maps this address, from the kernel-mode + * pagetables. */ +static inline void +guest_get_eff_kern_l1e(struct vcpu *v, unsigned long addr, void *eff_l1e) +{ +#if defined(__x86_64__) + int user_mode = !(v->arch.flags & TF_kernel_mode); +#define TOGGLE_MODE() if ( user_mode ) toggle_guest_mode(v) +#else +#define TOGGLE_MODE() ((void)0) +#endif + + TOGGLE_MODE(); + guest_get_eff_l1e(v, addr, eff_l1e); + TOGGLE_MODE(); +} + + + +#endif /* XEN_PAGING_H */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/include/asm-x86/shadow.h b/xen/include/asm-x86/shadow.h index 2afc0b0562..5a3dbfc72e 100644 --- a/xen/include/asm-x86/shadow.h +++ b/xen/include/asm-x86/shadow.h @@ -28,45 +28,26 @@ #include #include #include +#include +#include /***************************************************************************** - * Macros to tell which shadow paging mode a domain is in */ + * Macros to tell which shadow paging mode a domain is in*/ -#define SHM2_shift 10 -/* We're in one of the shadow modes */ -#define SHM2_enable (1U << SHM2_shift) -/* Refcounts based on shadow tables instead of guest tables */ -#define SHM2_refcounts (XEN_DOMCTL_SHADOW_ENABLE_REFCOUNT << SHM2_shift) -/* Enable log dirty mode */ -#define SHM2_log_dirty (XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY << SHM2_shift) -/* Xen does p2m translation, not guest */ -#define SHM2_translate (XEN_DOMCTL_SHADOW_ENABLE_TRANSLATE << SHM2_shift) -/* Xen does not steal address space from the domain for its own booking; - * requires VT or similar mechanisms */ -#define SHM2_external (XEN_DOMCTL_SHADOW_ENABLE_EXTERNAL << SHM2_shift) - -#define shadow_mode_enabled(_d) ((_d)->arch.shadow.mode) -#define shadow_mode_refcounts(_d) ((_d)->arch.shadow.mode & SHM2_refcounts) -#define shadow_mode_log_dirty(_d) ((_d)->arch.shadow.mode & SHM2_log_dirty) -#define shadow_mode_translate(_d) ((_d)->arch.shadow.mode & SHM2_translate) -#define shadow_mode_external(_d) ((_d)->arch.shadow.mode & SHM2_external) +#define shadow_mode_enabled(_d) paging_mode_shadow(_d) +#define shadow_mode_refcounts(_d) (paging_mode_shadow(_d) && \ + paging_mode_refcounts(_d)) +#define shadow_mode_log_dirty(_d) (paging_mode_shadow(_d) && \ + paging_mode_log_dirty(_d)) +#define shadow_mode_translate(_d) (paging_mode_shadow(_d) && \ + paging_mode_translate(_d)) +#define shadow_mode_external(_d) (paging_mode_shadow(_d) && \ + paging_mode_external(_d)) /* Xen traps & emulates all reads of all page table pages: * not yet supported */ #define shadow_mode_trap_reads(_d) ({ (void)(_d); 0; }) - -/****************************************************************************** - * The equivalent for a particular vcpu of a shadowed domain. */ - -/* Is this vcpu using the P2M table to translate between GFNs and MFNs? - * - * This is true of translated HVM domains on a vcpu which has paging - * enabled. (HVM vcpus with paging disabled are using the p2m table as - * its paging table, so no translation occurs in this case.) - * It is also true for all vcpus of translated PV domains. */ -#define shadow_vcpu_mode_translate(_v) ((_v)->arch.shadow.translate_enabled) - /* * 32on64 support */ @@ -76,122 +57,18 @@ #define pv_32bit_guest(_v) (!is_hvm_vcpu(_v)) #endif -/****************************************************************************** - * With shadow pagetables, the different kinds of address start - * to get get confusing. - * - * Virtual addresses are what they usually are: the addresses that are used - * to accessing memory while the guest is running. The MMU translates from - * virtual addresses to machine addresses. - * - * (Pseudo-)physical addresses are the abstraction of physical memory the - * guest uses for allocation and so forth. For the purposes of this code, - * we can largely ignore them. - * - * Guest frame numbers (gfns) are the entries that the guest puts in its - * pagetables. For normal paravirtual guests, they are actual frame numbers, - * with the translation done by the guest. - * - * Machine frame numbers (mfns) are the entries that the hypervisor puts - * in the shadow page tables. - * - * Elsewhere in the xen code base, the name "gmfn" is generally used to refer - * to a "machine frame number, from the guest's perspective", or in other - * words, pseudo-physical frame numbers. However, in the shadow code, the - * term "gmfn" means "the mfn of a guest page"; this combines naturally with - * other terms such as "smfn" (the mfn of a shadow page), gl2mfn (the mfn of a - * guest L2 page), etc... - */ - -/* With this defined, we do some ugly things to force the compiler to - * give us type safety between mfns and gfns and other integers. - * TYPE_SAFE(int foo) defines a foo_t, and _foo() and foo_x() functions - * that translate beween int and foo_t. - * - * It does have some performance cost because the types now have - * a different storage attribute, so may not want it on all the time. */ -#ifndef NDEBUG -#define TYPE_SAFETY 1 -#endif - -#ifdef TYPE_SAFETY -#define TYPE_SAFE(_type,_name) \ -typedef struct { _type _name; } _name##_t; \ -static inline _name##_t _##_name(_type n) { return (_name##_t) { n }; } \ -static inline _type _name##_x(_name##_t n) { return n._name; } -#else -#define TYPE_SAFE(_type,_name) \ -typedef _type _name##_t; \ -static inline _name##_t _##_name(_type n) { return n; } \ -static inline _type _name##_x(_name##_t n) { return n; } -#endif - -TYPE_SAFE(unsigned long,mfn) - -/* Macro for printk formats: use as printk("%"SH_PRI_mfn"\n", mfn_x(foo)); */ -#define SH_PRI_mfn "05lx" - - -/***************************************************************************** - * Mode-specific entry points into the shadow code. - * - * These shouldn't be used directly by callers; rather use the functions - * below which will indirect through this table as appropriate. */ - -struct sh_emulate_ctxt; -struct shadow_paging_mode { - int (*page_fault )(struct vcpu *v, unsigned long va, - struct cpu_user_regs *regs); - int (*invlpg )(struct vcpu *v, unsigned long va); - paddr_t (*gva_to_gpa )(struct vcpu *v, unsigned long va); - unsigned long (*gva_to_gfn )(struct vcpu *v, unsigned long va); - void (*update_cr3 )(struct vcpu *v, int do_locking); - int (*map_and_validate_gl1e )(struct vcpu *v, mfn_t gmfn, - void *new_guest_entry, u32 size); - int (*map_and_validate_gl2e )(struct vcpu *v, mfn_t gmfn, - void *new_guest_entry, u32 size); - int (*map_and_validate_gl2he)(struct vcpu *v, mfn_t gmfn, - void *new_guest_entry, u32 size); - int (*map_and_validate_gl3e )(struct vcpu *v, mfn_t gmfn, - void *new_guest_entry, u32 size); - int (*map_and_validate_gl4e )(struct vcpu *v, mfn_t gmfn, - void *new_guest_entry, u32 size); - void (*detach_old_tables )(struct vcpu *v); - int (*x86_emulate_write )(struct vcpu *v, unsigned long va, - void *src, u32 bytes, - struct sh_emulate_ctxt *sh_ctxt); - int (*x86_emulate_cmpxchg )(struct vcpu *v, unsigned long va, - unsigned long old, - unsigned long new, - unsigned int bytes, - struct sh_emulate_ctxt *sh_ctxt); - int (*x86_emulate_cmpxchg8b )(struct vcpu *v, unsigned long va, - unsigned long old_lo, - unsigned long old_hi, - unsigned long new_lo, - unsigned long new_hi, - struct sh_emulate_ctxt *sh_ctxt); - mfn_t (*make_monitor_table )(struct vcpu *v); - void (*destroy_monitor_table )(struct vcpu *v, mfn_t mmfn); - void * (*guest_map_l1e )(struct vcpu *v, unsigned long va, - unsigned long *gl1mfn); - void (*guest_get_eff_l1e )(struct vcpu *v, unsigned long va, - void *eff_l1e); - int (*guess_wrmap )(struct vcpu *v, - unsigned long vaddr, mfn_t gmfn); - /* For outsiders to tell what mode we're in */ - unsigned int shadow_levels; - unsigned int guest_levels; -}; - /***************************************************************************** * Entry points into the shadow code */ /* Set up the shadow-specific parts of a domain struct at start of day. - * Called for every domain from arch_domain_create() */ + * Called from paging_domain_init(). */ void shadow_domain_init(struct domain *d); +/* Setup the shadow-specific parts of a vcpu struct. It is called by + * paging_vcpu_init() in paging.c */ +void shadow_vcpu_init(struct vcpu *v); + /* Enable an arbitrary shadow mode. Call once at domain creation. */ int shadow_enable(struct domain *d, u32 mode); @@ -218,145 +95,21 @@ static inline void mark_dirty(struct domain *d, unsigned long gmfn) shadow_mark_dirty(d, _mfn(gmfn)); } -/* Handle page-faults caused by the shadow pagetable mechanisms. - * Called from pagefault handler in Xen, and from the HVM trap handlers - * for pagefaults. Returns 1 if this fault was an artefact of the - * shadow code (and the guest should retry) or 0 if it is not (and the - * fault should be handled elsewhere or passed to the guest). */ -static inline int shadow_fault(unsigned long va, struct cpu_user_regs *regs) -{ - struct vcpu *v = current; - perfc_incrc(shadow_fault); - return v->arch.shadow.mode->page_fault(v, va, regs); -} - -/* Handle invlpg requests on shadowed vcpus. - * Returns 1 if the invlpg instruction should be issued on the hardware, - * or 0 if it's safe not to do so. */ -static inline int shadow_invlpg(struct vcpu *v, unsigned long va) -{ - return v->arch.shadow.mode->invlpg(v, va); -} - -/* Translate a guest virtual address to the physical address that the - * *guest* pagetables would map it to. */ -static inline paddr_t shadow_gva_to_gpa(struct vcpu *v, unsigned long va) -{ - if ( unlikely(!shadow_vcpu_mode_translate(v)) ) - return (paddr_t) va; - return v->arch.shadow.mode->gva_to_gpa(v, va); -} - -/* Translate a guest virtual address to the frame number that the - * *guest* pagetables would map it to. */ -static inline unsigned long shadow_gva_to_gfn(struct vcpu *v, unsigned long va) -{ - if ( unlikely(!shadow_vcpu_mode_translate(v)) ) - return va >> PAGE_SHIFT; - return v->arch.shadow.mode->gva_to_gfn(v, va); -} - -/* Update all the things that are derived from the guest's CR3. - * Called when the guest changes CR3; the caller can then use v->arch.cr3 - * as the value to load into the host CR3 to schedule this vcpu */ -static inline void shadow_update_cr3(struct vcpu *v) -{ - v->arch.shadow.mode->update_cr3(v, 1); -} - /* Update all the things that are derived from the guest's CR0/CR3/CR4. * Called to initialize paging structures if the paging mode * has changed, and when bringing up a VCPU for the first time. */ void shadow_update_paging_modes(struct vcpu *v); -/***************************************************************************** - * Access to the guest pagetables */ - -/* Get a mapping of a PV guest's l1e for this virtual address. */ -static inline void * -guest_map_l1e(struct vcpu *v, unsigned long addr, unsigned long *gl1mfn) -{ - l2_pgentry_t l2e; - - if ( unlikely(shadow_mode_translate(v->domain)) ) - return v->arch.shadow.mode->guest_map_l1e(v, addr, gl1mfn); - - /* Find this l1e and its enclosing l1mfn in the linear map */ - if ( __copy_from_user(&l2e, - &__linear_l2_table[l2_linear_offset(addr)], - sizeof(l2_pgentry_t)) != 0 ) - return NULL; - /* Check flags that it will be safe to read the l1e */ - if ( (l2e_get_flags(l2e) & (_PAGE_PRESENT | _PAGE_PSE)) - != _PAGE_PRESENT ) - return NULL; - *gl1mfn = l2e_get_pfn(l2e); - return &__linear_l1_table[l1_linear_offset(addr)]; -} - -/* Pull down the mapping we got from guest_map_l1e() */ -static inline void -guest_unmap_l1e(struct vcpu *v, void *p) -{ - if ( unlikely(shadow_mode_translate(v->domain)) ) - unmap_domain_page(p); -} - -/* Read the guest's l1e that maps this address. */ -static inline void -guest_get_eff_l1e(struct vcpu *v, unsigned long addr, void *eff_l1e) -{ - if ( likely(!shadow_mode_translate(v->domain)) ) - { - ASSERT(!shadow_mode_external(v->domain)); - if ( __copy_from_user(eff_l1e, - &__linear_l1_table[l1_linear_offset(addr)], - sizeof(l1_pgentry_t)) != 0 ) - *(l1_pgentry_t *)eff_l1e = l1e_empty(); - return; - } - - v->arch.shadow.mode->guest_get_eff_l1e(v, addr, eff_l1e); -} - -/* Read the guest's l1e that maps this address, from the kernel-mode - * pagetables. */ -static inline void -guest_get_eff_kern_l1e(struct vcpu *v, unsigned long addr, void *eff_l1e) -{ -#if defined(__x86_64__) - int user_mode = !(v->arch.flags & TF_kernel_mode); -#define TOGGLE_MODE() if ( user_mode ) toggle_guest_mode(v) -#else -#define TOGGLE_MODE() ((void)0) -#endif - - TOGGLE_MODE(); - guest_get_eff_l1e(v, addr, eff_l1e); - TOGGLE_MODE(); -} - -/* Write a new value into the guest pagetable, and update the shadows - * appropriately. Returns 0 if we page-faulted, 1 for success. */ -int shadow_write_guest_entry(struct vcpu *v, intpte_t *p, - intpte_t new, mfn_t gmfn); - -/* Cmpxchg a new value into the guest pagetable, and update the shadows - * appropriately. Returns 0 if we page-faulted, 1 if not. - * N.B. caller should check the value of "old" to see if the - * cmpxchg itself was successful. */ -int shadow_cmpxchg_guest_entry(struct vcpu *v, intpte_t *p, - intpte_t *old, intpte_t new, mfn_t gmfn); - /* Remove all mappings of the guest page from the shadows. * This is called from common code. It does not flush TLBs. */ int sh_remove_all_mappings(struct vcpu *v, mfn_t target_mfn); static inline void shadow_drop_references(struct domain *d, struct page_info *p) { - /* See the comment about locking in sh_remove_all_mappings */ - sh_remove_all_mappings(d->vcpu[0], _mfn(page_to_mfn(p))); + if ( unlikely(shadow_mode_enabled(d)) ) + /* See the comment about locking in sh_remove_all_mappings */ + sh_remove_all_mappings(d->vcpu[0], _mfn(page_to_mfn(p))); } /* Remove all shadows of the guest mfn. */ @@ -367,99 +120,6 @@ static inline void shadow_remove_all_shadows(struct vcpu *v, mfn_t gmfn) sh_remove_shadows(v, gmfn, 0 /* Be thorough */, 1 /* Must succeed */); } -/**************************************************************************/ -/* Guest physmap (p2m) support - * - * The phys_to_machine_mapping is the reversed mapping of MPT for full - * virtualization. It is only used by shadow_mode_translate()==true - * guests, so we steal the address space that would have normally - * been used by the read-only MPT map. - */ -#define phys_to_machine_mapping ((l1_pgentry_t *)RO_MPT_VIRT_START) - -/* Add a page to a domain's p2m table */ -void shadow_guest_physmap_add_page(struct domain *d, unsigned long gfn, - unsigned long mfn); - -/* Remove a page from a domain's p2m table */ -void shadow_guest_physmap_remove_page(struct domain *d, unsigned long gfn, - unsigned long mfn); - -/* Aliases, called from common code. */ -#define guest_physmap_add_page shadow_guest_physmap_add_page -#define guest_physmap_remove_page shadow_guest_physmap_remove_page - -/* Read the current domain's P2M table. */ -static inline mfn_t sh_gfn_to_mfn_current(unsigned long gfn) -{ - l1_pgentry_t l1e = l1e_empty(); - int ret; - - if ( gfn > current->domain->arch.max_mapped_pfn ) - return _mfn(INVALID_MFN); - - /* Don't read off the end of the p2m table */ - ASSERT(gfn < (RO_MPT_VIRT_END - RO_MPT_VIRT_START) / sizeof(l1_pgentry_t)); - - ret = __copy_from_user(&l1e, - &phys_to_machine_mapping[gfn], - sizeof(l1e)); - - if ( (ret == 0) && (l1e_get_flags(l1e) & _PAGE_PRESENT) ) - return _mfn(l1e_get_pfn(l1e)); - - return _mfn(INVALID_MFN); -} - -/* Read another domain's P2M table, mapping pages as we go */ -mfn_t sh_gfn_to_mfn_foreign(struct domain *d, unsigned long gpfn); - -/* General conversion function from gfn to mfn */ -static inline mfn_t -sh_gfn_to_mfn(struct domain *d, unsigned long gfn) -{ - if ( !shadow_mode_translate(d) ) - return _mfn(gfn); - if ( likely(current->domain == d) ) - return sh_gfn_to_mfn_current(gfn); - else - return sh_gfn_to_mfn_foreign(d, gfn); -} - -/* Compatibility function for HVM code */ -static inline unsigned long get_mfn_from_gpfn(unsigned long pfn) -{ - return mfn_x(sh_gfn_to_mfn_current(pfn)); -} - -/* General conversion function from mfn to gfn */ -static inline unsigned long -sh_mfn_to_gfn(struct domain *d, mfn_t mfn) -{ - if ( shadow_mode_translate(d) ) - return get_gpfn_from_mfn(mfn_x(mfn)); - else - return mfn_x(mfn); -} - -/* Is this guest address an mmio one? (i.e. not defined in p2m map) */ -static inline int -mmio_space(paddr_t gpa) -{ - unsigned long gfn = gpa >> PAGE_SHIFT; - return !mfn_valid(mfn_x(sh_gfn_to_mfn_current(gfn))); -} - -/* Translate the frame number held in an l1e from guest to machine */ -static inline l1_pgentry_t -gl1e_to_ml1e(struct domain *d, l1_pgentry_t l1e) -{ - if ( unlikely(shadow_mode_translate(d)) ) - l1e = l1e_from_pfn(gmfn_to_mfn(d, l1e_get_pfn(l1e)), - l1e_get_flags(l1e)); - return l1e; -} - #endif /* _XEN_SHADOW_H */ /* diff --git a/xen/include/asm-x86/x86_32/kexec.h b/xen/include/asm-x86/x86_32/kexec.h deleted file mode 100644 index cb4ada715e..0000000000 --- a/xen/include/asm-x86/x86_32/kexec.h +++ /dev/null @@ -1,39 +0,0 @@ -/****************************************************************************** - * kexec.h - * - * Based heavily on machine_kexec.c and kexec.h from Linux 2.6.19-rc1 - * - */ - -#ifndef __X86_KEXEC_X86_32_H__ -#define __X86_KEXEC_X86_32_H__ - -#include -#include - -typedef asmlinkage void (*relocate_new_kernel_t)( - unsigned long indirection_page, - unsigned long page_list, - unsigned long start_address, - unsigned int has_pae); - -static inline void machine_kexec(xen_kexec_image_t *image) -{ - relocate_new_kernel_t rnk; - - rnk = (relocate_new_kernel_t) image->page_list[1]; - (*rnk)(image->indirection_page, (unsigned long)image->page_list, - image->start_address, (unsigned long)cpu_has_pae); -} - -#endif /* __X86_KEXEC_X86_32_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/xen/include/asm-x86/x86_64/kexec.h b/xen/include/asm-x86/x86_64/kexec.h deleted file mode 100644 index c54dbb9ba6..0000000000 --- a/xen/include/asm-x86/x86_64/kexec.h +++ /dev/null @@ -1,38 +0,0 @@ -/****************************************************************************** - * kexec.h - * - * Based heavily on machine_kexec.c and kexec.h from Linux 2.6.19-rc1 - * - */ - -#ifndef __X86_64_KEXEC_H__ -#define __X86_64_KEXEC_H__ - -#include -#include - -typedef void (*relocate_new_kernel_t)( - unsigned long indirection_page, - unsigned long page_list, - unsigned long start_address); - -static inline void machine_kexec(xen_kexec_image_t *image) -{ - relocate_new_kernel_t rnk; - - rnk = (relocate_new_kernel_t) image->page_list[1]; - (*rnk)(image->indirection_page, (unsigned long)image->page_list, - image->start_address); -} - -#endif /* __X86_64_KEXEC_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/xen/include/public/arch-ia64.h b/xen/include/public/arch-ia64.h index 49b9b15d77..b4dfea6285 100644 --- a/xen/include/public/arch-ia64.h +++ b/xen/include/public/arch-ia64.h @@ -37,6 +37,8 @@ #define DEFINE_XEN_GUEST_HANDLE(name) __DEFINE_XEN_GUEST_HANDLE(name, name) #define XEN_GUEST_HANDLE(name) __guest_handle_ ## name +#define XEN_GUEST_HANDLE_64(name) XEN_GUEST_HANDLE(name) +#define uint64_aligned_t uint64_t #define set_xen_guest_handle(hnd, val) do { (hnd).p = val; } while (0) #ifdef __XEN_TOOLS__ #define get_xen_guest_handle(val, hnd) do { val = (hnd).p; } while (0) @@ -63,10 +65,6 @@ DEFINE_XEN_GUEST_HANDLE(xen_pfn_t); #define VIRQ_MCA_CMC VIRQ_ARCH_1 /* MCA cmc interrupt */ #define VIRQ_MCA_CPE VIRQ_ARCH_2 /* MCA cpe interrupt */ -/* Arch specific callback irq definition */ -/* using Requester-ID(RID) as callback irq */ -#define IA64_CALLBACK_IRQ_RID (1 << 31) - /* Maximum number of virtual CPUs in multi-processor guests. */ /* WARNING: before changing this, check that shared_info fits on a page */ #define MAX_VIRT_CPUS 64 @@ -289,7 +287,9 @@ struct mapped_regs { unsigned char *interrupt_mask_addr; int pending_interruption; unsigned char vpsr_pp; - unsigned char reserved5_2[3]; + unsigned char vpsr_dfh; + unsigned char hpsr_dfh; + unsigned char hpsr_mfh; unsigned long reserved5_1[4]; int metaphysical_mode; // 1 = use metaphys mapping, 0 = use virtual int banknum; // 0 or 1, which virtual register bank is active diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index 93f44f3ba5..f7ea2d8acc 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -390,7 +390,8 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_settimeoffset_t); #define XEN_DOMCTL_sethvmcontext 34 typedef struct xen_domctl_hvmcontext { uint32_t size; /* IN/OUT: size of buffer / bytes filled */ - XEN_GUEST_HANDLE(uint8_t) buffer; /* IN/OUT */ + XEN_GUEST_HANDLE(uint8_t) buffer; /* IN/OUT: data, or call gethvmcontext + * with NULL buffer to get size req'd */ } xen_domctl_hvmcontext_t; DEFINE_XEN_GUEST_HANDLE(xen_domctl_hvmcontext_t); diff --git a/xen/include/public/hvm/save.h b/xen/include/public/hvm/save.h index 7ed26495c8..c6a856a558 100644 --- a/xen/include/public/hvm/save.h +++ b/xen/include/public/hvm/save.h @@ -382,10 +382,20 @@ struct hvm_hw_hpet { DECLARE_HVM_SAVE_TYPE(HPET, 12, struct hvm_hw_hpet); +/* + * PM timer + */ + +struct hvm_hw_pmtimer { + uint32_t timer; +}; + +DECLARE_HVM_SAVE_TYPE(PMTIMER, 13, struct hvm_hw_pmtimer); + /* * Largest type-code in use */ -#define HVM_SAVE_CODE_MAX 12 +#define HVM_SAVE_CODE_MAX 13 /* diff --git a/xen/include/xen/kexec.h b/xen/include/xen/kexec.h index be09c0a1ab..523846af06 100644 --- a/xen/include/xen/kexec.h +++ b/xen/include/xen/kexec.h @@ -25,6 +25,7 @@ int machine_kexec_load(int type, int slot, xen_kexec_image_t *image); void machine_kexec_unload(int type, int slot, xen_kexec_image_t *image); void machine_kexec_reserved(xen_kexec_reserve_t *reservation); void machine_reboot_kexec(xen_kexec_image_t *image); +void machine_kexec(xen_kexec_image_t *image); void kexec_crash(void); void kexec_crash_save_cpu(void); crash_xen_info_t *kexec_crash_save_info(void);