diff options
author | kaf24@scramble.cl.cam.ac.uk[kaf24] <kaf24@scramble.cl.cam.ac.uk[kaf24]> | 2004-03-10 13:44:42 +0000 |
---|---|---|
committer | kaf24@scramble.cl.cam.ac.uk[kaf24] <kaf24@scramble.cl.cam.ac.uk[kaf24]> | 2004-03-10 13:44:42 +0000 |
commit | 42e15e698253c63a62f8cdded56986373b55216f (patch) | |
tree | 5f93902f173e4f83990547a121e0cb15c50b2a57 | |
parent | 02a1394f7e5cd7b01c05f05a0a6b539d4edf490c (diff) | |
download | xen-42e15e698253c63a62f8cdded56986373b55216f.tar.gz xen-42e15e698253c63a62f8cdded56986373b55216f.tar.bz2 xen-42e15e698253c63a62f8cdded56986373b55216f.zip |
bitkeeper revision 1.772 (404f1bca1AESVwPe-EoPH5HymQhTXQ)
xen.patchE
60 files changed, 7932 insertions, 162 deletions
@@ -131,6 +131,7 @@ 3ddb79bcOftONV9h4QCxXOfiT0h91w xen/arch/i386/traps.c 3ddb79bc4nTpGQOe6_-MbyZzkhlhFQ xen/arch/i386/usercopy.c 3ddb79bcOMCu9-5mKpjIh5d0qqBDPg xen/arch/i386/xeno.lds +404f1b91uzXgPOtIhs8UZPGbZvlHfg xen/arch/x86_64/Rules.mk 3ddb79bdff-gj-jFGKjOejeHLqL8Lg xen/common/Makefile 3e397e66AyyD5fYraAySWuwi9uqSXg xen/common/ac_timer.c 3ddb79bdrqnW93GR9gZk1OJe1qK-iQ xen/common/brlock.c @@ -375,6 +376,7 @@ 3ddb79c3rM-Ote0Xn6Ytg8Y6YqAG-A xen/include/asm-i386/bitops.h 3ddb79c3pXaTAGGWSIZF9EnRV5PlRw xen/include/asm-i386/byteorder.h 3ddb79c3KhTI0F_Iw_hRL9QEyOVK-g xen/include/asm-i386/cache.h +404f1b920OQVnrbnXnySS-WxrH9Wzw xen/include/asm-i386/config.h 3ddb79c2LLt11EQHjrd6sB7FUqvFfA xen/include/asm-i386/cpufeature.h 3ddb79c2ADvRmdexd9y3AYK9_NTx-Q xen/include/asm-i386/current.h 3ddb79c2jFkPAZTDmU35L6IUssYMgQ xen/include/asm-i386/debugreg.h @@ -393,6 +395,7 @@ 3ddb79c2TKeScYHQZreTdHqYNLbehQ xen/include/asm-i386/io_apic.h 3ddb79c3S9Tga4XZRPrD4-aN3XIV6w xen/include/asm-i386/ioctl.h 3ddb79c2L7rTlFzazOLW1XuSZefpFw xen/include/asm-i386/irq.h +404f1b93OjLO4bFfBXYNaJdIqlNz-Q xen/include/asm-i386/ldt.h 3ddb79c3I98vWcQR8xEo34JMJ4Ahyw xen/include/asm-i386/mc146818rtc.h 3ddb79c3n_UbPuxlkNxvvLycClIkxA xen/include/asm-i386/mpspec.h 3ddb79c2wa0dA_LGigxOelSGbJ284Q xen/include/asm-i386/msr.h @@ -416,12 +419,64 @@ 3ddb79c4HugMq7IYGxcQKFBpKwKhzA xen/include/asm-i386/types.h 3ddb79c3M2n1ROZH6xk3HbyN4CPDqg xen/include/asm-i386/uaccess.h 3ddb79c3uPGcP_l_2xyGgBSWd5aC-Q xen/include/asm-i386/unaligned.h +404f1b95z0B0jb2IfvZJ7uvmYqsqpg xen/include/asm-x86_64/apic.h +404f1b95_OZH-rw_durHSa_Kgdo95A xen/include/asm-x86_64/apicdef.h +404f1b967UWSPkB0cwT9v-rilNzkHw xen/include/asm-x86_64/atomic.h +404f1b97UDomt73PizniyrCaxVRkXQ xen/include/asm-x86_64/bitops.h +404f1b98bhUJO45dacAaIRV7OE7P3A xen/include/asm-x86_64/byteorder.h +404f1b99W-dMUlFpsvt--tVpQvNgEQ xen/include/asm-x86_64/cache.h +404f1b9b_phpQlRnyiWqP6RodfZDpg xen/include/asm-x86_64/config.h +404f1b9cz7UV611DK6CTY1ZAiwGtTw xen/include/asm-x86_64/cpufeature.h +404f1b9ceJeGVaPNIENm2FkK0AgEOQ xen/include/asm-x86_64/current.h +404f1b9d854xae6HKv-9W8lLSgROdQ xen/include/asm-x86_64/debugreg.h +404f1b9eRm9rtcM29P5O2nrPFOGSow xen/include/asm-x86_64/delay.h +404f1b9fl6AQ_a-T1TDK3fuwTPXmHw xen/include/asm-x86_64/desc.h +404f1ba05mjpUREtosjzz3PPL5cTJA xen/include/asm-x86_64/dma.h +404f1ba13mnjeZT2ytPm0DB63703nA xen/include/asm-x86_64/domain_page.h +404f1ba2IXQ7E0x9NlqpR5hgYtC9RQ xen/include/asm-x86_64/elf.h +404f1ba31i0gS-cdqvd0RZX1HVnxsA xen/include/asm-x86_64/fixmap.h +404f1ba4KXQ_V7HOkenF04KRU7Tl7w xen/include/asm-x86_64/flushtlb.h +404f1ba5Sqzc22eXORShvCF9-rpMbA xen/include/asm-x86_64/hardirq.h +404f1ba6_nDjomU9HJVvUugj63LvEg xen/include/asm-x86_64/hdreg.h +404f1ba7Q-lF892SDZLWjJ62wmauSA xen/include/asm-x86_64/i387.h +404f1ba8yxfnHH0NWC1B-wmd6bK2wg xen/include/asm-x86_64/ide.h +404f1ba9_7NIylhSRmokesN8TNIiNg xen/include/asm-x86_64/io.h +404f1baaiXXy7vChbzKmluSyJ5LWIw xen/include/asm-x86_64/io_apic.h +404f1bab38sz6Fd2LyLPDD4mMYgd7w xen/include/asm-x86_64/ioctl.h +404f1baceMqjaYFs7oZoNsPkaZJ0WQ xen/include/asm-x86_64/irq.h +404f1badfXZJZ2sU8sh9PS2EZvd19Q xen/include/asm-x86_64/ldt.h +404f1bae_yI5vMg-_k4EySMERbbz2Q xen/include/asm-x86_64/mc146818rtc.h +404f1bafYfNwntXQGIggyj7D6YruJQ xen/include/asm-x86_64/mpspec.h +404f1bb0asrts1dyLQhyARCgzhL0NA xen/include/asm-x86_64/msr.h +404f1bb1LSCqrMDSfRAti5NdMQPJBQ xen/include/asm-x86_64/page.h +404f1bb2IUaGWD82SrQFaacyBixVFw xen/include/asm-x86_64/param.h +404f1bb3zSQfhMuQ24xNtq9Ed09jGw xen/include/asm-x86_64/pci.h +404f1bb41Yl-5ZjIWnG66HDCj6OIWA xen/include/asm-x86_64/pda.h +404f1bb5toGAnZVAlJ2fWWMv28DFJQ xen/include/asm-x86_64/pdb.h +404f1bb6pz982jtehZacFKhFUac0ug xen/include/asm-x86_64/pgalloc.h +404f1bb756fZfxk5HDx7J7BW3R-1jQ xen/include/asm-x86_64/processor.h +404f1bb86rAXB3aLS1vYdcqpJiEcyg xen/include/asm-x86_64/ptrace.h +404f1bb9K0pcyDrV4Ctva1HUczoueQ xen/include/asm-x86_64/rwlock.h +404f1bbaIdS7vc3sE032fQG6EnY8AQ xen/include/asm-x86_64/scatterlist.h +404f1bbbR5n83SiPof3joEPv9xWPPA xen/include/asm-x86_64/smp.h +404f1bbc67CEECfR8ATd7dPD1ajLng xen/include/asm-x86_64/smpboot.h +404f1bbdXaaPrIp5AUIjC8Hsp2H0Aw xen/include/asm-x86_64/softirq.h +404f1bbeomkO5YarnkIRWxVhlB5EJA xen/include/asm-x86_64/spinlock.h +404f1bbf82VK-kyDVBmR7CTvtTBKaw xen/include/asm-x86_64/string.h +404f1bc0laOnGpDxFpgdiuZpEyOOKw xen/include/asm-x86_64/system.h +404f1bc1FnfxOhmgWYHP97TPqA40Pw xen/include/asm-x86_64/time.h +404f1bc2mx9ZbazcdFh-AN70ZvNMJQ xen/include/asm-x86_64/timex.h +404f1bc3R2o0PIpQme8bDWeHcqHNGw xen/include/asm-x86_64/types.h +404f1bc4tWkB9Qr8RkKtZGW5eMQzhw xen/include/asm-x86_64/uaccess.h +404f1bc5idyWKKROGo_hvHVx58Gmkw xen/include/asm-x86_64/unaligned.h 400304fcmRQmDdFYEzDh0wcBba9alg xen/include/hypervisor-ifs/COPYING 3ddb79c2YTaZwOqWin9-QNgHge5RVw xen/include/hypervisor-ifs/block.h 3ddb79c2PMeWTK86y4C3F4MzHw4A1g xen/include/hypervisor-ifs/dom0_ops.h 3e6377eaioRoNm0m_HSDEAd4Vqrq_w xen/include/hypervisor-ifs/dom_mem_ops.h 403cd194j2pyLqXD8FJ-ukvZzkPenw xen/include/hypervisor-ifs/event_channel.h 3ddb79c25UE59iu4JJcbRalx95mvcg xen/include/hypervisor-ifs/hypervisor-if.h +404f1bc68SXxmv0zQpXBWGrCzSyp8w xen/include/hypervisor-ifs/if-i386/hypervisor-if-arch.h +404f1bc7IwU-qnH8mJeVu0YsNGMrcw xen/include/hypervisor-ifs/if-x86_64/hypervisor-if-arch.h 3ead095dE_VF-QA88rl_5cWYRWtRVQ xen/include/hypervisor-ifs/kbd.h 3ddb79c2oRPrzClk3zbTkRHlpumzKA xen/include/hypervisor-ifs/network.h 3f0d22cbroqp_BkoDPwkfRJhaw1LiQ xen/include/hypervisor-ifs/vbd.h @@ -26,3 +26,4 @@ clean: $(MAKE) -C xen clean $(MAKE) -C tools clean + ln -sf if-$(ARCH) include/hypervisor-ifs/if-arch diff --git a/xen/Makefile b/xen/Makefile index 4d2238af6b..fc4bc7f961 100644 --- a/xen/Makefile +++ b/xen/Makefile @@ -45,9 +45,10 @@ $(TARGET): delete-unfresh-files make-links $(GENERATED_FILES) make-links: delete-links ln -sf xeno include/linux ln -sf asm-$(ARCH) include/asm + ln -sf if-$(ARCH) include/hypervisor-ifs/if-arch delete-links: - rm -f include/linux include/asm + rm -f include/linux include/asm include/hypervisor-ifs/if-arch # Blow away kernel.o because build info is stored statically within it. delete-unfresh-files: diff --git a/xen/Rules.mk b/xen/Rules.mk index 82d459f933..3b26a5a92b 100644 --- a/xen/Rules.mk +++ b/xen/Rules.mk @@ -1,4 +1,4 @@ -ARCH := i386 +ARCH ?= i386 TARGET := $(BASEDIR)/xen HDRS := $(wildcard $(BASEDIR)/include/xeno/*.h) diff --git a/xen/arch/x86_64/Rules.mk b/xen/arch/x86_64/Rules.mk new file mode 100644 index 0000000000..56f5932b6d --- /dev/null +++ b/xen/arch/x86_64/Rules.mk @@ -0,0 +1,17 @@ +######################################## +# x86-specific definitions + +CC := gcc +LD := ld +# Linker should relocate monitor to this address +MONITOR_BASE := 0xFC500000 +# Bootloader should load monitor to this real address +LOAD_BASE := 0x00100000 +CFLAGS := -nostdinc -fno-builtin -fno-common -fno-strict-aliasing +CFLAGS += -iwithprefix include -O3 -Wall -DMONITOR_BASE=$(MONITOR_BASE) +CFLAGS += -fomit-frame-pointer -I$(BASEDIR)/include -D__KERNEL__ -DNDEBUG +#CFLAGS += -fomit-frame-pointer -I$(BASEDIR)/include -D__KERNEL__ +CFLAGS += -Wno-pointer-arith -Wredundant-decls +LDFLAGS := -T xeno.lds -N + + diff --git a/xen/include/asm-i386/config.h b/xen/include/asm-i386/config.h new file mode 100644 index 0000000000..bfd99a0725 --- /dev/null +++ b/xen/include/asm-i386/config.h @@ -0,0 +1,170 @@ +/****************************************************************************** + * config.h + * + * A Linux-style configuration list. + */ + +#ifndef __XENO_CONFIG_H__ +#define __XENO_CONFIG_H__ + +#define CONFIG_X86 1 + +#define CONFIG_SMP 1 +#define CONFIG_X86_LOCAL_APIC 1 +#define CONFIG_X86_IO_APIC 1 +#define CONFIG_X86_L1_CACHE_SHIFT 5 + +#define CONFIG_PCI 1 +#define CONFIG_PCI_BIOS 1 +#define CONFIG_PCI_DIRECT 1 + +#define CONFIG_IDE 1 +#define CONFIG_BLK_DEV_IDE 1 +#define CONFIG_BLK_DEV_IDEDMA 1 +#define CONFIG_BLK_DEV_IDEPCI 1 +#define CONFIG_IDEDISK_MULTI_MODE 1 +#define CONFIG_IDEDISK_STROKE 1 +#define CONFIG_IDEPCI_SHARE_IRQ 1 +#define CONFIG_BLK_DEV_IDEDMA_PCI 1 +#define CONFIG_IDEDMA_PCI_AUTO 1 +#define CONFIG_IDEDMA_AUTO 1 +#define CONFIG_IDEDMA_ONLYDISK 1 +#define CONFIG_BLK_DEV_IDE_MODES 1 +#define CONFIG_BLK_DEV_PIIX 1 + +#define CONFIG_SCSI 1 +#define CONFIG_SCSI_LOGGING 1 +#define CONFIG_BLK_DEV_SD 1 +#define CONFIG_SD_EXTRA_DEVS 40 +#define CONFIG_SCSI_MULTI_LUN 1 + +#define CONFIG_XEN_ATTENTION_KEY 1 + +#define HZ 100 + +/* + * Just to keep compiler happy. + * NB. DO NOT CHANGE SMP_CACHE_BYTES WITHOUT FIXING arch/i386/entry.S!!! + * It depends on size of irq_cpustat_t, for example, being 64 bytes. :-) + * Mmmm... so niiiiiice.... + */ +#define SMP_CACHE_BYTES 64 +#define NR_CPUS 16 +#define __cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES))) +#define ____cacheline_aligned __cacheline_aligned + +/*** Hypervisor owns top 64MB of virtual address space. ***/ +#define HYPERVISOR_VIRT_START (0xFC000000UL) + +/* + * First 4MB are mapped read-only for all. It's for the machine->physical + * mapping table (MPT table). The following are virtual addresses. + */ +#define READONLY_MPT_VIRT_START (HYPERVISOR_VIRT_START) +#define READONLY_MPT_VIRT_END (READONLY_MPT_VIRT_START + (4*1024*1024)) +/* + * Next 16MB is fixed monitor space, which is part of a 44MB direct-mapped + * memory region. The following are machine addresses. + */ +#define MAX_MONITOR_ADDRESS (16*1024*1024) +#define MAX_DMA_ADDRESS (16*1024*1024) +#define MAX_DIRECTMAP_ADDRESS (44*1024*1024) +/* And the virtual addresses for the direct-map region... */ +#define DIRECTMAP_VIRT_START (READONLY_MPT_VIRT_END) +#define DIRECTMAP_VIRT_END (DIRECTMAP_VIRT_START + MAX_DIRECTMAP_ADDRESS) +#define MONITOR_VIRT_START (DIRECTMAP_VIRT_START) +#define MONITOR_VIRT_END (MONITOR_VIRT_START + MAX_MONITOR_ADDRESS) +#define RDWR_MPT_VIRT_START (MONITOR_VIRT_END) +#define RDWR_MPT_VIRT_END (RDWR_MPT_VIRT_START + (4*1024*1024)) +#define FRAMETABLE_VIRT_START (RDWR_MPT_VIRT_END) +#define FRAMETABLE_VIRT_END (DIRECTMAP_VIRT_END) +/* Next 4MB of virtual address space is used as a linear p.t. mapping. */ +#define LINEAR_PT_VIRT_START (DIRECTMAP_VIRT_END) +#define LINEAR_PT_VIRT_END (LINEAR_PT_VIRT_START + (4*1024*1024)) +/* Next 4MB of virtual address space used for per-domain mappings (eg. GDT). */ +#define PERDOMAIN_VIRT_START (LINEAR_PT_VIRT_END) +#define PERDOMAIN_VIRT_END (PERDOMAIN_VIRT_START + (4*1024*1024)) +#define GDT_VIRT_START (PERDOMAIN_VIRT_START) +#define GDT_VIRT_END (GDT_VIRT_START + (64*1024)) +#define LDT_VIRT_START (GDT_VIRT_END) +#define LDT_VIRT_END (LDT_VIRT_START + (64*1024)) +/* Penultimate 4MB of virtual address space used for domain page mappings. */ +#define MAPCACHE_VIRT_START (PERDOMAIN_VIRT_END) +#define MAPCACHE_VIRT_END (MAPCACHE_VIRT_START + (4*1024*1024)) +/* Final 4MB of virtual address space used for ioremap(). */ +#define IOREMAP_VIRT_START (MAPCACHE_VIRT_END) +#define IOREMAP_VIRT_END (IOREMAP_VIRT_START + (4*1024*1024)) + +/* + * Amount of slack domain memory to leave in system, in megabytes. + * Prevents a hard out-of-memory crunch for thinsg like network receive. + */ +#define SLACK_DOMAIN_MEM_KILOBYTES 2048 + +/* Linkage for x86 */ +#define FASTCALL(x) x __attribute__((regparm(3))) +#define asmlinkage __attribute__((regparm(0))) +#define __ALIGN .align 16,0x90 +#define __ALIGN_STR ".align 16,0x90" +#define SYMBOL_NAME_STR(X) #X +#define SYMBOL_NAME(X) X +#define SYMBOL_NAME_LABEL(X) X##: +#ifdef __ASSEMBLY__ +#define ALIGN __ALIGN +#define ALIGN_STR __ALIGN_STR +#define ENTRY(name) \ + .globl SYMBOL_NAME(name); \ + ALIGN; \ + SYMBOL_NAME_LABEL(name) +#endif + +/* syslog levels ==> nothing! */ +#define KERN_NOTICE "" +#define KERN_WARNING "" +#define KERN_DEBUG "" +#define KERN_INFO "" +#define KERN_ERR "" +#define KERN_CRIT "" +#define KERN_EMERG "" +#define KERN_ALERT "" + +#define barrier() __asm__ __volatile__("": : :"memory") + +#define __HYPERVISOR_CS 0x0808 +#define __HYPERVISOR_DS 0x0810 + +#define NR_syscalls 256 + +#define offsetof(_p,_f) ((unsigned long)&(((_p *)0)->_f)) +#define struct_cpy(_x,_y) (memcpy((_x),(_y),sizeof(*(_x)))) + +#define dev_probe_lock() ((void)0) +#define dev_probe_unlock() ((void)0) + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +#define capable(_c) 0 + +#ifndef NDEBUG +#define DPRINTK(_f, _a...) printk("(file=%s, line=%d) " _f, \ + __FILE__ , __LINE__ , ## _a ) +#define MEMORY_GUARD +#define TRACE_BUFFER +#else +#define DPRINTK(_f, _a...) ((void)0) +#endif + +#ifndef __ASSEMBLY__ + +#include <xeno/compiler.h> + +extern unsigned long _end; /* standard ELF symbol */ +extern void __out_of_line_bug(int line) __attribute__((noreturn)); +#define out_of_line_bug() __out_of_line_bug(__LINE__) + +extern unsigned int opt_ser_baud; +#define SERIAL_ENABLED (opt_ser_baud != 0) + +#endif /* __ASSEMBLY__ */ + +#endif /* __XENO_CONFIG_H__ */ diff --git a/xen/include/asm-i386/ldt.h b/xen/include/asm-i386/ldt.h new file mode 100644 index 0000000000..4da2a15afc --- /dev/null +++ b/xen/include/asm-i386/ldt.h @@ -0,0 +1,29 @@ +#ifndef __ARCH_LDT_H +#define __ARCH_LDT_H + +#ifndef __ASSEMBLY__ + +static inline void load_LDT(struct task_struct *p) +{ + unsigned int cpu; + struct desc_struct *desc; + unsigned long ents; + + if ( (ents = p->mm.ldt_ents) == 0 ) + { + __asm__ __volatile__ ( "lldt %%ax" : : "a" (0) ); + } + else + { + cpu = smp_processor_id(); + desc = (struct desc_struct *)GET_GDT_ADDRESS(p) + __LDT(cpu); + desc->a = ((LDT_VIRT_START&0xffff)<<16) | (ents*8-1); + desc->b = (LDT_VIRT_START&(0xff<<24)) | 0x8200 | + ((LDT_VIRT_START&0xff0000)>>16); + __asm__ __volatile__ ( "lldt %%ax" : : "a" (__LDT(cpu)<<3) ); + } +} + +#endif /* !__ASSEMBLY__ */ + +#endif diff --git a/xen/include/asm-x86_64/apic.h b/xen/include/asm-x86_64/apic.h new file mode 100644 index 0000000000..705942596c --- /dev/null +++ b/xen/include/asm-x86_64/apic.h @@ -0,0 +1,98 @@ +#ifndef __ASM_APIC_H +#define __ASM_APIC_H + +#include <linux/config.h> +#include <asm/ptrace.h> +#include <asm/apicdef.h> +#include <asm/system.h> + +#ifdef CONFIG_X86_LOCAL_APIC + +#define APIC_DEBUG 0 + +#if APIC_DEBUG +#define Dprintk(x...) printk(x) +#else +#define Dprintk(x...) +#endif + +/* + * Basic functions accessing APICs. + */ + +static __inline void apic_write(unsigned long reg, unsigned long v) +{ + *((volatile unsigned long *)(APIC_BASE+reg)) = v; +} + +static __inline void apic_write_atomic(unsigned long reg, unsigned long v) +{ + xchg((volatile unsigned long *)(APIC_BASE+reg), v); +} + +static __inline unsigned long apic_read(unsigned long reg) +{ + return *((volatile unsigned long *)(APIC_BASE+reg)); +} + +static __inline__ void apic_wait_icr_idle(void) +{ + do { } while ( apic_read( APIC_ICR ) & APIC_ICR_BUSY ); +} + +#ifdef CONFIG_X86_GOOD_APIC +# define FORCE_READ_AROUND_WRITE 0 +# define apic_read_around(x) +# define apic_write_around(x,y) apic_write((x),(y)) +#else +# define FORCE_READ_AROUND_WRITE 1 +# define apic_read_around(x) apic_read(x) +# define apic_write_around(x,y) apic_write_atomic((x),(y)) +#endif + +static inline void ack_APIC_irq(void) +{ + /* + * ack_APIC_irq() actually gets compiled as a single instruction: + * - a single rmw on Pentium/82489DX + * - a single write on P6+ cores (CONFIG_X86_GOOD_APIC) + * ... yummie. + */ + + /* Docs say use 0 for future compatibility */ + apic_write_around(APIC_EOI, 0); +} + +extern int get_maxlvt(void); +extern void connect_bsp_APIC (void); +extern void disconnect_bsp_APIC (void); +extern void disable_local_APIC (void); +extern int verify_local_APIC (void); +extern void sync_Arb_IDs (void); +extern void init_bsp_APIC (void); +extern void setup_local_APIC (void); +extern void init_apic_mappings (void); +extern void setup_APIC_clocks (void); +extern void setup_apic_nmi_watchdog (void); +extern inline void nmi_watchdog_tick (struct pt_regs * regs); +extern int APIC_init_uniprocessor (void); +extern void disable_APIC_timer(void); +extern void enable_APIC_timer(void); + +//extern struct pm_dev *apic_pm_register(pm_dev_t, unsigned long, pm_callback); +//extern void apic_pm_unregister(struct pm_dev*); + +extern unsigned int watchdog_on; + +extern unsigned int apic_timer_irqs [NR_CPUS]; +extern int check_nmi_watchdog (void); + +extern unsigned int nmi_watchdog; +#define NMI_NONE 0 +#define NMI_IO_APIC 1 +#define NMI_LOCAL_APIC 2 +#define NMI_INVALID 3 + +#endif /* CONFIG_X86_LOCAL_APIC */ + +#endif /* __ASM_APIC_H */ diff --git a/xen/include/asm-x86_64/apicdef.h b/xen/include/asm-x86_64/apicdef.h new file mode 100644 index 0000000000..227bfca652 --- /dev/null +++ b/xen/include/asm-x86_64/apicdef.h @@ -0,0 +1,378 @@ +#ifndef __ASM_APICDEF_H +#define __ASM_APICDEF_H + +/* + * Constants for various Intel APICs. (local APIC, IOAPIC, etc.) + * + * Alan Cox <Alan.Cox@linux.org>, 1995. + * Ingo Molnar <mingo@redhat.com>, 1999, 2000 + */ + +#define APIC_DEFAULT_PHYS_BASE 0xfee00000 + +#define APIC_ID 0x20 +#define APIC_ID_MASK (0x0F<<24) +#define GET_APIC_ID(x) (((x)>>24)&0x0F) +#define APIC_LVR 0x30 +#define APIC_LVR_MASK 0xFF00FF +#define GET_APIC_VERSION(x) ((x)&0xFF) +#define GET_APIC_MAXLVT(x) (((x)>>16)&0xFF) +#define APIC_INTEGRATED(x) ((x)&0xF0) +#define APIC_TASKPRI 0x80 +#define APIC_TPRI_MASK 0xFF +#define APIC_ARBPRI 0x90 +#define APIC_ARBPRI_MASK 0xFF +#define APIC_PROCPRI 0xA0 +#define APIC_EOI 0xB0 +#define APIC_EIO_ACK 0x0 /* Write this to the EOI register */ +#define APIC_RRR 0xC0 +#define APIC_LDR 0xD0 +#define APIC_LDR_MASK (0xFF<<24) +#define GET_APIC_LOGICAL_ID(x) (((x)>>24)&0xFF) +#define SET_APIC_LOGICAL_ID(x) (((x)<<24)) +#define APIC_ALL_CPUS 0xFF +#define APIC_DFR 0xE0 +#define APIC_DFR_CLUSTER 0x0FFFFFFFul /* Clustered */ +#define APIC_DFR_FLAT 0xFFFFFFFFul /* Flat mode */ +#define APIC_SPIV 0xF0 +#define APIC_SPIV_FOCUS_DISABLED (1<<9) +#define APIC_SPIV_APIC_ENABLED (1<<8) +#define APIC_ISR 0x100 +#define APIC_TMR 0x180 +#define APIC_IRR 0x200 +#define APIC_ESR 0x280 +#define APIC_ESR_SEND_CS 0x00001 +#define APIC_ESR_RECV_CS 0x00002 +#define APIC_ESR_SEND_ACC 0x00004 +#define APIC_ESR_RECV_ACC 0x00008 +#define APIC_ESR_SENDILL 0x00020 +#define APIC_ESR_RECVILL 0x00040 +#define APIC_ESR_ILLREGA 0x00080 +#define APIC_ICR 0x300 +#define APIC_DEST_SELF 0x40000 +#define APIC_DEST_ALLINC 0x80000 +#define APIC_DEST_ALLBUT 0xC0000 +#define APIC_ICR_RR_MASK 0x30000 +#define APIC_ICR_RR_INVALID 0x00000 +#define APIC_ICR_RR_INPROG 0x10000 +#define APIC_ICR_RR_VALID 0x20000 +#define APIC_INT_LEVELTRIG 0x08000 +#define APIC_INT_ASSERT 0x04000 +#define APIC_ICR_BUSY 0x01000 +#define APIC_DEST_PHYSICAL 0x00000 +#define APIC_DEST_LOGICAL 0x00800 +#define APIC_DM_FIXED 0x00000 +#define APIC_DM_LOWEST 0x00100 +#define APIC_DM_SMI 0x00200 +#define APIC_DM_REMRD 0x00300 +#define APIC_DM_NMI 0x00400 +#define APIC_DM_INIT 0x00500 +#define APIC_DM_STARTUP 0x00600 +#define APIC_DM_EXTINT 0x00700 +#define APIC_VECTOR_MASK 0x000FF +#define APIC_ICR2 0x310 +#define GET_APIC_DEST_FIELD(x) (((x)>>24)&0xFF) +#define SET_APIC_DEST_FIELD(x) ((x)<<24) +#define APIC_LVTT 0x320 +#define APIC_LVTPC 0x340 +#define APIC_LVT0 0x350 +#define APIC_LVT_TIMER_BASE_MASK (0x3<<18) +#define GET_APIC_TIMER_BASE(x) (((x)>>18)&0x3) +#define SET_APIC_TIMER_BASE(x) (((x)<<18)) +#define APIC_TIMER_BASE_CLKIN 0x0 +#define APIC_TIMER_BASE_TMBASE 0x1 +#define APIC_TIMER_BASE_DIV 0x2 +#define APIC_LVT_TIMER_PERIODIC (1<<17) +#define APIC_LVT_MASKED (1<<16) +#define APIC_LVT_LEVEL_TRIGGER (1<<15) +#define APIC_LVT_REMOTE_IRR (1<<14) +#define APIC_INPUT_POLARITY (1<<13) +#define APIC_SEND_PENDING (1<<12) +#define GET_APIC_DELIVERY_MODE(x) (((x)>>8)&0x7) +#define SET_APIC_DELIVERY_MODE(x,y) (((x)&~0x700)|((y)<<8)) +#define APIC_MODE_FIXED 0x0 +#define APIC_MODE_NMI 0x4 +#define APIC_MODE_EXINT 0x7 +#define APIC_LVT1 0x360 +#define APIC_LVTERR 0x370 +#define APIC_TMICT 0x380 +#define APIC_TMCCT 0x390 +#define APIC_TDCR 0x3E0 +#define APIC_TDR_DIV_TMBASE (1<<2) +#define APIC_TDR_DIV_1 0xB +#define APIC_TDR_DIV_2 0x0 +#define APIC_TDR_DIV_4 0x1 +#define APIC_TDR_DIV_8 0x2 +#define APIC_TDR_DIV_16 0x3 +#define APIC_TDR_DIV_32 0x8 +#define APIC_TDR_DIV_64 0x9 +#define APIC_TDR_DIV_128 0xA + +#define APIC_BASE (fix_to_virt(FIX_APIC_BASE)) + +#ifdef CONFIG_X86_CLUSTERED_APIC +#define MAX_IO_APICS 32 +#else +#define MAX_IO_APICS 8 +#endif + + +/* + * The broadcast ID is 0xF for old APICs and 0xFF for xAPICs. SAPICs + * don't broadcast (yet?), but if they did, they might use 0xFFFF. + */ +#define APIC_BROADCAST_ID_XAPIC (0xFF) +#define APIC_BROADCAST_ID_APIC (0x0F) + +/* + * the local APIC register structure, memory mapped. Not terribly well + * tested, but we might eventually use this one in the future - the + * problem why we cannot use it right now is the P5 APIC, it has an + * errata which cannot take 8-bit reads and writes, only 32-bit ones ... + */ +#define u32 unsigned int + +#define lapic ((volatile struct local_apic *)APIC_BASE) + +struct local_apic { + +/*000*/ struct { u32 __reserved[4]; } __reserved_01; + +/*010*/ struct { u32 __reserved[4]; } __reserved_02; + +/*020*/ struct { /* APIC ID Register */ + u32 __reserved_1 : 24, + phys_apic_id : 4, + __reserved_2 : 4; + u32 __reserved[3]; + } id; + +/*030*/ const + struct { /* APIC Version Register */ + u32 version : 8, + __reserved_1 : 8, + max_lvt : 8, + __reserved_2 : 8; + u32 __reserved[3]; + } version; + +/*040*/ struct { u32 __reserved[4]; } __reserved_03; + +/*050*/ struct { u32 __reserved[4]; } __reserved_04; + +/*060*/ struct { u32 __reserved[4]; } __reserved_05; + +/*070*/ struct { u32 __reserved[4]; } __reserved_06; + +/*080*/ struct { /* Task Priority Register */ + u32 priority : 8, + __reserved_1 : 24; + u32 __reserved_2[3]; + } tpr; + +/*090*/ const + struct { /* Arbitration Priority Register */ + u32 priority : 8, + __reserved_1 : 24; + u32 __reserved_2[3]; + } apr; + +/*0A0*/ const + struct { /* Processor Priority Register */ + u32 priority : 8, + __reserved_1 : 24; + u32 __reserved_2[3]; + } ppr; + +/*0B0*/ struct { /* End Of Interrupt Register */ + u32 eoi; + u32 __reserved[3]; + } eoi; + +/*0C0*/ struct { u32 __reserved[4]; } __reserved_07; + +/*0D0*/ struct { /* Logical Destination Register */ + u32 __reserved_1 : 24, + logical_dest : 8; + u32 __reserved_2[3]; + } ldr; + +/*0E0*/ struct { /* Destination Format Register */ + u32 __reserved_1 : 28, + model : 4; + u32 __reserved_2[3]; + } dfr; + +/*0F0*/ struct { /* Spurious Interrupt Vector Register */ + u32 spurious_vector : 8, + apic_enabled : 1, + focus_cpu : 1, + __reserved_2 : 22; + u32 __reserved_3[3]; + } svr; + +/*100*/ struct { /* In Service Register */ +/*170*/ u32 bitfield; + u32 __reserved[3]; + } isr [8]; + +/*180*/ struct { /* Trigger Mode Register */ +/*1F0*/ u32 bitfield; + u32 __reserved[3]; + } tmr [8]; + +/*200*/ struct { /* Interrupt Request Register */ +/*270*/ u32 bitfield; + u32 __reserved[3]; + } irr [8]; + +/*280*/ union { /* Error Status Register */ + struct { + u32 send_cs_error : 1, + receive_cs_error : 1, + send_accept_error : 1, + receive_accept_error : 1, + __reserved_1 : 1, + send_illegal_vector : 1, + receive_illegal_vector : 1, + illegal_register_address : 1, + __reserved_2 : 24; + u32 __reserved_3[3]; + } error_bits; + struct { + u32 errors; + u32 __reserved_3[3]; + } all_errors; + } esr; + +/*290*/ struct { u32 __reserved[4]; } __reserved_08; + +/*2A0*/ struct { u32 __reserved[4]; } __reserved_09; + +/*2B0*/ struct { u32 __reserved[4]; } __reserved_10; + +/*2C0*/ struct { u32 __reserved[4]; } __reserved_11; + +/*2D0*/ struct { u32 __reserved[4]; } __reserved_12; + +/*2E0*/ struct { u32 __reserved[4]; } __reserved_13; + +/*2F0*/ struct { u32 __reserved[4]; } __reserved_14; + +/*300*/ struct { /* Interrupt Command Register 1 */ + u32 vector : 8, + delivery_mode : 3, + destination_mode : 1, + delivery_status : 1, + __reserved_1 : 1, + level : 1, + trigger : 1, + __reserved_2 : 2, + shorthand : 2, + __reserved_3 : 12; + u32 __reserved_4[3]; + } icr1; + +/*310*/ struct { /* Interrupt Command Register 2 */ + union { + u32 __reserved_1 : 24, + phys_dest : 4, + __reserved_2 : 4; + u32 __reserved_3 : 24, + logical_dest : 8; + } dest; + u32 __reserved_4[3]; + } icr2; + +/*320*/ struct { /* LVT - Timer */ + u32 vector : 8, + __reserved_1 : 4, + delivery_status : 1, + __reserved_2 : 3, + mask : 1, + timer_mode : 1, + __reserved_3 : 14; + u32 __reserved_4[3]; + } lvt_timer; + +/*330*/ struct { u32 __reserved[4]; } __reserved_15; + +/*340*/ struct { /* LVT - Performance Counter */ + u32 vector : 8, + delivery_mode : 3, + __reserved_1 : 1, + delivery_status : 1, + __reserved_2 : 3, + mask : 1, + __reserved_3 : 15; + u32 __reserved_4[3]; + } lvt_pc; + +/*350*/ struct { /* LVT - LINT0 */ + u32 vector : 8, + delivery_mode : 3, + __reserved_1 : 1, + delivery_status : 1, + polarity : 1, + remote_irr : 1, + trigger : 1, + mask : 1, + __reserved_2 : 15; + u32 __reserved_3[3]; + } lvt_lint0; + +/*360*/ struct { /* LVT - LINT1 */ + u32 vector : 8, + delivery_mode : 3, + __reserved_1 : 1, + delivery_status : 1, + polarity : 1, + remote_irr : 1, + trigger : 1, + mask : 1, + __reserved_2 : 15; + u32 __reserved_3[3]; + } lvt_lint1; + +/*370*/ struct { /* LVT - Error */ + u32 vector : 8, + __reserved_1 : 4, + delivery_status : 1, + __reserved_2 : 3, + mask : 1, + __reserved_3 : 15; + u32 __reserved_4[3]; + } lvt_error; + +/*380*/ struct { /* Timer Initial Count Register */ + u32 initial_count; + u32 __reserved_2[3]; + } timer_icr; + +/*390*/ const + struct { /* Timer Current Count Register */ + u32 curr_count; + u32 __reserved_2[3]; + } timer_ccr; + +/*3A0*/ struct { u32 __reserved[4]; } __reserved_16; + +/*3B0*/ struct { u32 __reserved[4]; } __reserved_17; + +/*3C0*/ struct { u32 __reserved[4]; } __reserved_18; + +/*3D0*/ struct { u32 __reserved[4]; } __reserved_19; + +/*3E0*/ struct { /* Timer Divide Configuration Register */ + u32 divisor : 4, + __reserved_1 : 28; + u32 __reserved_2[3]; + } timer_dcr; + +/*3F0*/ struct { u32 __reserved[4]; } __reserved_20; + +} __attribute__ ((packed)); + +#undef u32 + +#endif diff --git a/xen/include/asm-x86_64/atomic.h b/xen/include/asm-x86_64/atomic.h new file mode 100644 index 0000000000..9dcdca93f7 --- /dev/null +++ b/xen/include/asm-x86_64/atomic.h @@ -0,0 +1,195 @@ +#ifndef __ARCH_I386_ATOMIC__ +#define __ARCH_I386_ATOMIC__ + +#include <xeno/config.h> + +/* + * Atomic operations that C can't guarantee us. Useful for + * resource counting etc.. + */ + +#ifdef CONFIG_SMP +#define LOCK "lock ; " +#else +#define LOCK "" +#endif + +/* + * Make sure gcc doesn't try to be clever and move things around + * on us. We need to use _exactly_ the address the user gave us, + * not some alias that contains the same information. + */ +typedef struct { volatile int counter; } atomic_t; + +#define ATOMIC_INIT(i) { (i) } + +/** + * atomic_read - read atomic variable + * @v: pointer of type atomic_t + * + * Atomically reads the value of @v. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +#define atomic_read(v) ((v)->counter) + +/** + * atomic_set - set atomic variable + * @v: pointer of type atomic_t + * @i: required value + * + * Atomically sets the value of @v to @i. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +#define atomic_set(v,i) (((v)->counter) = (i)) + +/** + * atomic_add - add integer to atomic variable + * @i: integer value to add + * @v: pointer of type atomic_t + * + * Atomically adds @i to @v. Note that the guaranteed useful range + * of an atomic_t is only 24 bits. + */ +static __inline__ void atomic_add(int i, atomic_t *v) +{ + __asm__ __volatile__( + LOCK "addl %1,%0" + :"=m" (v->counter) + :"ir" (i), "m" (v->counter)); +} + +/** + * atomic_sub - subtract the atomic variable + * @i: integer value to subtract + * @v: pointer of type atomic_t + * + * Atomically subtracts @i from @v. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static __inline__ void atomic_sub(int i, atomic_t *v) +{ + __asm__ __volatile__( + LOCK "subl %1,%0" + :"=m" (v->counter) + :"ir" (i), "m" (v->counter)); +} + +/** + * atomic_sub_and_test - subtract value from variable and test result + * @i: integer value to subtract + * @v: pointer of type atomic_t + * + * Atomically subtracts @i from @v and returns + * true if the result is zero, or false for all + * other cases. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static __inline__ int atomic_sub_and_test(int i, atomic_t *v) +{ + unsigned char c; + + __asm__ __volatile__( + LOCK "subl %2,%0; sete %1" + :"=m" (v->counter), "=qm" (c) + :"ir" (i), "m" (v->counter) : "memory"); + return c; +} + +/** + * atomic_inc - increment atomic variable + * @v: pointer of type atomic_t + * + * Atomically increments @v by 1. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static __inline__ void atomic_inc(atomic_t *v) +{ + __asm__ __volatile__( + LOCK "incl %0" + :"=m" (v->counter) + :"m" (v->counter)); +} + +/** + * atomic_dec - decrement atomic variable + * @v: pointer of type atomic_t + * + * Atomically decrements @v by 1. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static __inline__ void atomic_dec(atomic_t *v) +{ + __asm__ __volatile__( + LOCK "decl %0" + :"=m" (v->counter) + :"m" (v->counter)); +} + +/** + * atomic_dec_and_test - decrement and test + * @v: pointer of type atomic_t + * + * Atomically decrements @v by 1 and + * returns true if the result is 0, or false for all other + * cases. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static __inline__ int atomic_dec_and_test(atomic_t *v) +{ + unsigned char c; + + __asm__ __volatile__( + LOCK "decl %0; sete %1" + :"=m" (v->counter), "=qm" (c) + :"m" (v->counter) : "memory"); + return c != 0; +} + +/** + * atomic_inc_and_test - increment and test + * @v: pointer of type atomic_t + * + * Atomically increments @v by 1 + * and returns true if the result is zero, or false for all + * other cases. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static __inline__ int atomic_inc_and_test(atomic_t *v) +{ + unsigned char c; + + __asm__ __volatile__( + LOCK "incl %0; sete %1" + :"=m" (v->counter), "=qm" (c) + :"m" (v->counter) : "memory"); + return c != 0; +} + +/** + * atomic_add_negative - add and test if negative + * @v: pointer of type atomic_t + * @i: integer value to add + * + * Atomically adds @i to @v and returns true + * if the result is negative, or false when + * result is greater than or equal to zero. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static __inline__ int atomic_add_negative(int i, atomic_t *v) +{ + unsigned char c; + + __asm__ __volatile__( + LOCK "addl %2,%0; sets %1" + :"=m" (v->counter), "=qm" (c) + :"ir" (i), "m" (v->counter) : "memory"); + return c; +} + +/* Atomic operations are already serializing on x86 */ +#define smp_mb__before_atomic_dec() barrier() +#define smp_mb__after_atomic_dec() barrier() +#define smp_mb__before_atomic_inc() barrier() +#define smp_mb__after_atomic_inc() barrier() + +#endif diff --git a/xen/include/asm-x86_64/bitops.h b/xen/include/asm-x86_64/bitops.h new file mode 100644 index 0000000000..73bcd8ef5f --- /dev/null +++ b/xen/include/asm-x86_64/bitops.h @@ -0,0 +1,368 @@ +#ifndef _I386_BITOPS_H +#define _I386_BITOPS_H + +/* + * Copyright 1992, Linus Torvalds. + */ + +#include <xeno/config.h> + +/* + * These have to be done with inline assembly: that way the bit-setting + * is guaranteed to be atomic. All bit operations return 0 if the bit + * was cleared before the operation and != 0 if it was not. + * + * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). + */ + +#ifdef CONFIG_SMP +#define LOCK_PREFIX "lock ; " +#else +#define LOCK_PREFIX "" +#endif + +#define ADDR (*(volatile long *) addr) + +/** + * set_bit - Atomically set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * This function is atomic and may not be reordered. See __set_bit() + * if you do not require the atomic guarantees. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static __inline__ void set_bit(int nr, volatile void * addr) +{ + __asm__ __volatile__( LOCK_PREFIX + "btsl %1,%0" + :"=m" (ADDR) + :"Ir" (nr)); +} + +/** + * __set_bit - Set a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * Unlike set_bit(), this function is non-atomic and may be reordered. + * If it's called on the same region of memory simultaneously, the effect + * may be that only one operation succeeds. + */ +static __inline__ void __set_bit(int nr, volatile void * addr) +{ + __asm__( + "btsl %1,%0" + :"=m" (ADDR) + :"Ir" (nr)); +} + +/** + * clear_bit - Clears a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * clear_bit() is atomic and may not be reordered. However, it does + * not contain a memory barrier, so if it is used for locking purposes, + * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit() + * in order to ensure changes are visible on other processors. + */ +static __inline__ void clear_bit(int nr, volatile void * addr) +{ + __asm__ __volatile__( LOCK_PREFIX + "btrl %1,%0" + :"=m" (ADDR) + :"Ir" (nr)); +} +#define smp_mb__before_clear_bit() barrier() +#define smp_mb__after_clear_bit() barrier() + +/** + * __change_bit - Toggle a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * + * Unlike change_bit(), this function is non-atomic and may be reordered. + * If it's called on the same region of memory simultaneously, the effect + * may be that only one operation succeeds. + */ +static __inline__ void __change_bit(int nr, volatile void * addr) +{ + __asm__ __volatile__( + "btcl %1,%0" + :"=m" (ADDR) + :"Ir" (nr)); +} + +/** + * change_bit - Toggle a bit in memory + * @nr: Bit to clear + * @addr: Address to start counting from + * + * change_bit() is atomic and may not be reordered. + * Note that @nr may be almost arbitrarily large; this function is not + * restricted to acting on a single-word quantity. + */ +static __inline__ void change_bit(int nr, volatile void * addr) +{ + __asm__ __volatile__( LOCK_PREFIX + "btcl %1,%0" + :"=m" (ADDR) + :"Ir" (nr)); +} + +/** + * test_and_set_bit - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +static __inline__ int test_and_set_bit(int nr, volatile void * addr) +{ + int oldbit; + + __asm__ __volatile__( LOCK_PREFIX + "btsl %2,%1\n\tsbbl %0,%0" + :"=r" (oldbit),"=m" (ADDR) + :"Ir" (nr) : "memory"); + return oldbit; +} + +/** + * __test_and_set_bit - Set a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered. + * If two examples of this operation race, one can appear to succeed + * but actually fail. You must protect multiple accesses with a lock. + */ +static __inline__ int __test_and_set_bit(int nr, volatile void * addr) +{ + int oldbit; + + __asm__( + "btsl %2,%1\n\tsbbl %0,%0" + :"=r" (oldbit),"=m" (ADDR) + :"Ir" (nr)); + return oldbit; +} + +/** + * test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +static __inline__ int test_and_clear_bit(int nr, volatile void * addr) +{ + int oldbit; + + __asm__ __volatile__( LOCK_PREFIX + "btrl %2,%1\n\tsbbl %0,%0" + :"=r" (oldbit),"=m" (ADDR) + :"Ir" (nr) : "memory"); + return oldbit; +} + +/** + * __test_and_clear_bit - Clear a bit and return its old value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is non-atomic and can be reordered. + * If two examples of this operation race, one can appear to succeed + * but actually fail. You must protect multiple accesses with a lock. + */ +static __inline__ int __test_and_clear_bit(int nr, volatile void * addr) +{ + int oldbit; + + __asm__( + "btrl %2,%1\n\tsbbl %0,%0" + :"=r" (oldbit),"=m" (ADDR) + :"Ir" (nr)); + return oldbit; +} + +/* WARNING: non atomic and it can be reordered! */ +static __inline__ int __test_and_change_bit(int nr, volatile void * addr) +{ + int oldbit; + + __asm__ __volatile__( + "btcl %2,%1\n\tsbbl %0,%0" + :"=r" (oldbit),"=m" (ADDR) + :"Ir" (nr) : "memory"); + return oldbit; +} + +/** + * test_and_change_bit - Change a bit and return its new value + * @nr: Bit to set + * @addr: Address to count from + * + * This operation is atomic and cannot be reordered. + * It also implies a memory barrier. + */ +static __inline__ int test_and_change_bit(int nr, volatile void * addr) +{ + int oldbit; + + __asm__ __volatile__( LOCK_PREFIX + "btcl %2,%1\n\tsbbl %0,%0" + :"=r" (oldbit),"=m" (ADDR) + :"Ir" (nr) : "memory"); + return oldbit; +} + + +static __inline__ int constant_test_bit(int nr, const volatile void * addr) +{ + return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0; +} + +static __inline__ int variable_test_bit(int nr, volatile void * addr) +{ + int oldbit; + + __asm__ __volatile__( + "btl %2,%1\n\tsbbl %0,%0" + :"=r" (oldbit) + :"m" (ADDR),"Ir" (nr)); + return oldbit; +} + +#define test_bit(nr,addr) \ +(__builtin_constant_p(nr) ? \ + constant_test_bit((nr),(addr)) : \ + variable_test_bit((nr),(addr))) + +/** + * find_first_zero_bit - find the first zero bit in a memory region + * @addr: The address to start the search at + * @size: The maximum size to search + * + * Returns the bit-number of the first zero bit, not the number of the byte + * containing a bit. + */ +static __inline__ int find_first_zero_bit(void * addr, unsigned size) +{ + int d0, d1, d2; + int res; + + if (!size) + return 0; + /* This looks at memory. Mark it volatile to tell gcc not to move it around */ + __asm__ __volatile__( + "movl $-1,%%eax\n\t" + "xorl %%edx,%%edx\n\t" + "repe; scasl\n\t" + "je 1f\n\t" + "xorl -4(%%edi),%%eax\n\t" + "subl $4,%%edi\n\t" + "bsfl %%eax,%%edx\n" + "1:\tsubl %%ebx,%%edi\n\t" + "shll $3,%%edi\n\t" + "addl %%edi,%%edx" + :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2) + :"1" ((size + 31) >> 5), "2" (addr), "b" (addr)); + return res; +} + +/** + * find_next_zero_bit - find the first zero bit in a memory region + * @addr: The address to base the search on + * @offset: The bitnumber to start searching at + * @size: The maximum size to search + */ +static __inline__ int find_next_zero_bit (void * addr, int size, int offset) +{ + unsigned long * p = ((unsigned long *) addr) + (offset >> 5); + int set = 0, bit = offset & 31, res; + + if (bit) { + /* + * Look for zero in first byte + */ + __asm__("bsfl %1,%0\n\t" + "jne 1f\n\t" + "movl $32, %0\n" + "1:" + : "=r" (set) + : "r" (~(*p >> bit))); + if (set < (32 - bit)) + return set + offset; + set = 32 - bit; + p++; + } + /* + * No zero yet, search remaining full bytes for a zero + */ + res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr)); + return (offset + set + res); +} + +/** + * ffz - find first zero in word. + * @word: The word to search + * + * Undefined if no zero exists, so code should check against ~0UL first. + */ +static __inline__ unsigned long ffz(unsigned long word) +{ + __asm__("bsfl %1,%0" + :"=r" (word) + :"r" (~word)); + return word; +} + +/** + * ffs - find first bit set + * @x: the word to search + * + * This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ +static __inline__ int ffs(int x) +{ + int r; + + __asm__("bsfl %1,%0\n\t" + "jnz 1f\n\t" + "movl $-1,%0\n" + "1:" : "=r" (r) : "g" (x)); + return r+1; +} + +/** + * hweightN - returns the hamming weight of a N-bit word + * @x: the word to weigh + * + * The Hamming Weight of a number is the total number of bits set in it. + */ + +#define hweight32(x) generic_hweight32(x) +#define hweight16(x) generic_hweight16(x) +#define hweight8(x) generic_hweight8(x) + +#define ext2_set_bit __test_and_set_bit +#define ext2_clear_bit __test_and_clear_bit +#define ext2_test_bit test_bit +#define ext2_find_first_zero_bit find_first_zero_bit +#define ext2_find_next_zero_bit find_next_zero_bit + +/* Bitmap functions for the minix filesystem. */ +#define minix_test_and_set_bit(nr,addr) __test_and_set_bit(nr,addr) +#define minix_set_bit(nr,addr) __set_bit(nr,addr) +#define minix_test_and_clear_bit(nr,addr) __test_and_clear_bit(nr,addr) +#define minix_test_bit(nr,addr) test_bit(nr,addr) +#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size) + +#endif /* _I386_BITOPS_H */ diff --git a/xen/include/asm-x86_64/byteorder.h b/xen/include/asm-x86_64/byteorder.h new file mode 100644 index 0000000000..bbfb629fae --- /dev/null +++ b/xen/include/asm-x86_64/byteorder.h @@ -0,0 +1,47 @@ +#ifndef _I386_BYTEORDER_H +#define _I386_BYTEORDER_H + +#include <asm/types.h> + +#ifdef __GNUC__ + +/* For avoiding bswap on i386 */ +#ifdef __KERNEL__ +#include <linux/config.h> +#endif + +static __inline__ __const__ __u32 ___arch__swab32(__u32 x) +{ +#ifdef CONFIG_X86_BSWAP + __asm__("bswap %0" : "=r" (x) : "0" (x)); +#else + __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */ + "rorl $16,%0\n\t" /* swap words */ + "xchgb %b0,%h0" /* swap higher bytes */ + :"=q" (x) + : "0" (x)); +#endif + return x; +} + +static __inline__ __const__ __u16 ___arch__swab16(__u16 x) +{ + __asm__("xchgb %b0,%h0" /* swap bytes */ \ + : "=q" (x) \ + : "0" (x)); \ + return x; +} + +#define __arch__swab32(x) ___arch__swab32(x) +#define __arch__swab16(x) ___arch__swab16(x) + +#if !defined(__STRICT_ANSI__) || defined(__KERNEL__) +# define __BYTEORDER_HAS_U64__ +# define __SWAB_64_THRU_32__ +#endif + +#endif /* __GNUC__ */ + +#include <linux/byteorder/little_endian.h> + +#endif /* _I386_BYTEORDER_H */ diff --git a/xen/include/asm-x86_64/cache.h b/xen/include/asm-x86_64/cache.h new file mode 100644 index 0000000000..502c8ba7a6 --- /dev/null +++ b/xen/include/asm-x86_64/cache.h @@ -0,0 +1,13 @@ +/* + * include/asm-i386/cache.h + */ +#ifndef __ARCH_I386_CACHE_H +#define __ARCH_I386_CACHE_H + +#include <xeno/config.h> + +/* L1 cache line size */ +#define L1_CACHE_SHIFT (CONFIG_X86_L1_CACHE_SHIFT) +#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) + +#endif diff --git a/xen/include/asm-x86_64/config.h b/xen/include/asm-x86_64/config.h new file mode 100644 index 0000000000..bfd99a0725 --- /dev/null +++ b/xen/include/asm-x86_64/config.h @@ -0,0 +1,170 @@ +/****************************************************************************** + * config.h + * + * A Linux-style configuration list. + */ + +#ifndef __XENO_CONFIG_H__ +#define __XENO_CONFIG_H__ + +#define CONFIG_X86 1 + +#define CONFIG_SMP 1 +#define CONFIG_X86_LOCAL_APIC 1 +#define CONFIG_X86_IO_APIC 1 +#define CONFIG_X86_L1_CACHE_SHIFT 5 + +#define CONFIG_PCI 1 +#define CONFIG_PCI_BIOS 1 +#define CONFIG_PCI_DIRECT 1 + +#define CONFIG_IDE 1 +#define CONFIG_BLK_DEV_IDE 1 +#define CONFIG_BLK_DEV_IDEDMA 1 +#define CONFIG_BLK_DEV_IDEPCI 1 +#define CONFIG_IDEDISK_MULTI_MODE 1 +#define CONFIG_IDEDISK_STROKE 1 +#define CONFIG_IDEPCI_SHARE_IRQ 1 +#define CONFIG_BLK_DEV_IDEDMA_PCI 1 +#define CONFIG_IDEDMA_PCI_AUTO 1 +#define CONFIG_IDEDMA_AUTO 1 +#define CONFIG_IDEDMA_ONLYDISK 1 +#define CONFIG_BLK_DEV_IDE_MODES 1 +#define CONFIG_BLK_DEV_PIIX 1 + +#define CONFIG_SCSI 1 +#define CONFIG_SCSI_LOGGING 1 +#define CONFIG_BLK_DEV_SD 1 +#define CONFIG_SD_EXTRA_DEVS 40 +#define CONFIG_SCSI_MULTI_LUN 1 + +#define CONFIG_XEN_ATTENTION_KEY 1 + +#define HZ 100 + +/* + * Just to keep compiler happy. + * NB. DO NOT CHANGE SMP_CACHE_BYTES WITHOUT FIXING arch/i386/entry.S!!! + * It depends on size of irq_cpustat_t, for example, being 64 bytes. :-) + * Mmmm... so niiiiiice.... + */ +#define SMP_CACHE_BYTES 64 +#define NR_CPUS 16 +#define __cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES))) +#define ____cacheline_aligned __cacheline_aligned + +/*** Hypervisor owns top 64MB of virtual address space. ***/ +#define HYPERVISOR_VIRT_START (0xFC000000UL) + +/* + * First 4MB are mapped read-only for all. It's for the machine->physical + * mapping table (MPT table). The following are virtual addresses. + */ +#define READONLY_MPT_VIRT_START (HYPERVISOR_VIRT_START) +#define READONLY_MPT_VIRT_END (READONLY_MPT_VIRT_START + (4*1024*1024)) +/* + * Next 16MB is fixed monitor space, which is part of a 44MB direct-mapped + * memory region. The following are machine addresses. + */ +#define MAX_MONITOR_ADDRESS (16*1024*1024) +#define MAX_DMA_ADDRESS (16*1024*1024) +#define MAX_DIRECTMAP_ADDRESS (44*1024*1024) +/* And the virtual addresses for the direct-map region... */ +#define DIRECTMAP_VIRT_START (READONLY_MPT_VIRT_END) +#define DIRECTMAP_VIRT_END (DIRECTMAP_VIRT_START + MAX_DIRECTMAP_ADDRESS) +#define MONITOR_VIRT_START (DIRECTMAP_VIRT_START) +#define MONITOR_VIRT_END (MONITOR_VIRT_START + MAX_MONITOR_ADDRESS) +#define RDWR_MPT_VIRT_START (MONITOR_VIRT_END) +#define RDWR_MPT_VIRT_END (RDWR_MPT_VIRT_START + (4*1024*1024)) +#define FRAMETABLE_VIRT_START (RDWR_MPT_VIRT_END) +#define FRAMETABLE_VIRT_END (DIRECTMAP_VIRT_END) +/* Next 4MB of virtual address space is used as a linear p.t. mapping. */ +#define LINEAR_PT_VIRT_START (DIRECTMAP_VIRT_END) +#define LINEAR_PT_VIRT_END (LINEAR_PT_VIRT_START + (4*1024*1024)) +/* Next 4MB of virtual address space used for per-domain mappings (eg. GDT). */ +#define PERDOMAIN_VIRT_START (LINEAR_PT_VIRT_END) +#define PERDOMAIN_VIRT_END (PERDOMAIN_VIRT_START + (4*1024*1024)) +#define GDT_VIRT_START (PERDOMAIN_VIRT_START) +#define GDT_VIRT_END (GDT_VIRT_START + (64*1024)) +#define LDT_VIRT_START (GDT_VIRT_END) +#define LDT_VIRT_END (LDT_VIRT_START + (64*1024)) +/* Penultimate 4MB of virtual address space used for domain page mappings. */ +#define MAPCACHE_VIRT_START (PERDOMAIN_VIRT_END) +#define MAPCACHE_VIRT_END (MAPCACHE_VIRT_START + (4*1024*1024)) +/* Final 4MB of virtual address space used for ioremap(). */ +#define IOREMAP_VIRT_START (MAPCACHE_VIRT_END) +#define IOREMAP_VIRT_END (IOREMAP_VIRT_START + (4*1024*1024)) + +/* + * Amount of slack domain memory to leave in system, in megabytes. + * Prevents a hard out-of-memory crunch for thinsg like network receive. + */ +#define SLACK_DOMAIN_MEM_KILOBYTES 2048 + +/* Linkage for x86 */ +#define FASTCALL(x) x __attribute__((regparm(3))) +#define asmlinkage __attribute__((regparm(0))) +#define __ALIGN .align 16,0x90 +#define __ALIGN_STR ".align 16,0x90" +#define SYMBOL_NAME_STR(X) #X +#define SYMBOL_NAME(X) X +#define SYMBOL_NAME_LABEL(X) X##: +#ifdef __ASSEMBLY__ +#define ALIGN __ALIGN +#define ALIGN_STR __ALIGN_STR +#define ENTRY(name) \ + .globl SYMBOL_NAME(name); \ + ALIGN; \ + SYMBOL_NAME_LABEL(name) +#endif + +/* syslog levels ==> nothing! */ +#define KERN_NOTICE "" +#define KERN_WARNING "" +#define KERN_DEBUG "" +#define KERN_INFO "" +#define KERN_ERR "" +#define KERN_CRIT "" +#define KERN_EMERG "" +#define KERN_ALERT "" + +#define barrier() __asm__ __volatile__("": : :"memory") + +#define __HYPERVISOR_CS 0x0808 +#define __HYPERVISOR_DS 0x0810 + +#define NR_syscalls 256 + +#define offsetof(_p,_f) ((unsigned long)&(((_p *)0)->_f)) +#define struct_cpy(_x,_y) (memcpy((_x),(_y),sizeof(*(_x)))) + +#define dev_probe_lock() ((void)0) +#define dev_probe_unlock() ((void)0) + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +#define capable(_c) 0 + +#ifndef NDEBUG +#define DPRINTK(_f, _a...) printk("(file=%s, line=%d) " _f, \ + __FILE__ , __LINE__ , ## _a ) +#define MEMORY_GUARD +#define TRACE_BUFFER +#else +#define DPRINTK(_f, _a...) ((void)0) +#endif + +#ifndef __ASSEMBLY__ + +#include <xeno/compiler.h> + +extern unsigned long _end; /* standard ELF symbol */ +extern void __out_of_line_bug(int line) __attribute__((noreturn)); +#define out_of_line_bug() __out_of_line_bug(__LINE__) + +extern unsigned int opt_ser_baud; +#define SERIAL_ENABLED (opt_ser_baud != 0) + +#endif /* __ASSEMBLY__ */ + +#endif /* __XENO_CONFIG_H__ */ diff --git a/xen/include/asm-x86_64/cpufeature.h b/xen/include/asm-x86_64/cpufeature.h new file mode 100644 index 0000000000..85b8b43974 --- /dev/null +++ b/xen/include/asm-x86_64/cpufeature.h @@ -0,0 +1,76 @@ +/* + * cpufeature.h + * + * Defines x86 CPU feature bits + */ + +#ifndef __ASM_I386_CPUFEATURE_H +#define __ASM_I386_CPUFEATURE_H + +/* Sample usage: CPU_FEATURE_P(cpu.x86_capability, FPU) */ +#define CPU_FEATURE_P(CAP, FEATURE) test_bit(CAP, X86_FEATURE_##FEATURE ##_BIT) + +#define NCAPINTS 4 /* Currently we have 4 32-bit words worth of info */ + +/* Intel-defined CPU features, CPUID level 0x00000001, word 0 */ +#define X86_FEATURE_FPU (0*32+ 0) /* Onboard FPU */ +#define X86_FEATURE_VME (0*32+ 1) /* Virtual Mode Extensions */ +#define X86_FEATURE_DE (0*32+ 2) /* Debugging Extensions */ +#define X86_FEATURE_PSE (0*32+ 3) /* Page Size Extensions */ +#define X86_FEATURE_TSC (0*32+ 4) /* Time Stamp Counter */ +#define X86_FEATURE_MSR (0*32+ 5) /* Model-Specific Registers, RDMSR, WRMSR */ +#define X86_FEATURE_PAE (0*32+ 6) /* Physical Address Extensions */ +#define X86_FEATURE_MCE (0*32+ 7) /* Machine Check Architecture */ +#define X86_FEATURE_CX8 (0*32+ 8) /* CMPXCHG8 instruction */ +#define X86_FEATURE_APIC (0*32+ 9) /* Onboard APIC */ +#define X86_FEATURE_SEP (0*32+11) /* SYSENTER/SYSEXIT */ +#define X86_FEATURE_MTRR (0*32+12) /* Memory Type Range Registers */ +#define X86_FEATURE_PGE (0*32+13) /* Page Global Enable */ +#define X86_FEATURE_MCA (0*32+14) /* Machine Check Architecture */ +#define X86_FEATURE_CMOV (0*32+15) /* CMOV instruction (FCMOVCC and FCOMI too if FPU present) */ +#define X86_FEATURE_PAT (0*32+16) /* Page Attribute Table */ +#define X86_FEATURE_PSE36 (0*32+17) /* 36-bit PSEs */ +#define X86_FEATURE_PN (0*32+18) /* Processor serial number */ +#define X86_FEATURE_CLFLSH (0*32+19) /* Supports the CLFLUSH instruction */ +#define X86_FEATURE_DTES (0*32+21) /* Debug Trace Store */ +#define X86_FEATURE_ACPI (0*32+22) /* ACPI via MSR */ +#define X86_FEATURE_MMX (0*32+23) /* Multimedia Extensions */ +#define X86_FEATURE_FXSR (0*32+24) /* FXSAVE and FXRSTOR instructions (fast save and restore */ + /* of FPU context), and CR4.OSFXSR available */ +#define X86_FEATURE_XMM (0*32+25) /* Streaming SIMD Extensions */ +#define X86_FEATURE_XMM2 (0*32+26) /* Streaming SIMD Extensions-2 */ +#define X86_FEATURE_SELFSNOOP (0*32+27) /* CPU self snoop */ +#define X86_FEATURE_HT (0*32+28) /* Hyper-Threading */ +#define X86_FEATURE_ACC (0*32+29) /* Automatic clock control */ +#define X86_FEATURE_IA64 (0*32+30) /* IA-64 processor */ + +/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */ +/* Don't duplicate feature flags which are redundant with Intel! */ +#define X86_FEATURE_SYSCALL (1*32+11) /* SYSCALL/SYSRET */ +#define X86_FEATURE_MMXEXT (1*32+22) /* AMD MMX extensions */ +#define X86_FEATURE_LM (1*32+29) /* Long Mode (x86-64) */ +#define X86_FEATURE_3DNOWEXT (1*32+30) /* AMD 3DNow! extensions */ +#define X86_FEATURE_3DNOW (1*32+31) /* 3DNow! */ + +/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */ +#define X86_FEATURE_RECOVERY (2*32+ 0) /* CPU in recovery mode */ +#define X86_FEATURE_LONGRUN (2*32+ 1) /* Longrun power control */ +#define X86_FEATURE_LRTI (2*32+ 3) /* LongRun table interface */ + +/* Other features, Linux-defined mapping, word 3 */ +/* This range is used for feature bits which conflict or are synthesized */ +#define X86_FEATURE_CXMMX (3*32+ 0) /* Cyrix MMX extensions */ +#define X86_FEATURE_K6_MTRR (3*32+ 1) /* AMD K6 nonstandard MTRRs */ +#define X86_FEATURE_CYRIX_ARR (3*32+ 2) /* Cyrix ARRs (= MTRRs) */ +#define X86_FEATURE_CENTAUR_MCR (3*32+ 3) /* Centaur MCRs (= MTRRs) */ + +#define cpu_has(c, bit) test_bit(bit, (c)->x86_capability) + +#endif /* __ASM_I386_CPUFEATURE_H */ + +/* + * Local Variables: + * mode:c + * comment-column:42 + * End: + */ diff --git a/xen/include/asm-x86_64/current.h b/xen/include/asm-x86_64/current.h new file mode 100644 index 0000000000..ee5b4b8516 --- /dev/null +++ b/xen/include/asm-x86_64/current.h @@ -0,0 +1,52 @@ +#ifndef _I386_CURRENT_H +#define _I386_CURRENT_H + +struct task_struct; + +#define STACK_RESERVED \ + (sizeof(execution_context_t) + sizeof(struct task_struct *)) + +static inline struct task_struct * get_current(void) +{ + struct task_struct *current; + __asm__ ( "orl %%esp,%0; andl $~3,%0; movl (%0),%0" + : "=r" (current) : "0" (STACK_SIZE-4) ); + return current; +} + +#define current get_current() + +static inline void set_current(struct task_struct *p) +{ + __asm__ ( "orl %%esp,%0; andl $~3,%0; movl %1,(%0)" + : : "r" (STACK_SIZE-4), "r" (p) ); +} + +static inline execution_context_t *get_execution_context(void) +{ + execution_context_t *execution_context; + __asm__ ( "andl %%esp,%0; addl %2,%0" + : "=r" (execution_context) + : "0" (~(STACK_SIZE-1)), "i" (STACK_SIZE-STACK_RESERVED) ); + return execution_context; +} + +static inline unsigned long get_stack_top(void) +{ + unsigned long p; + __asm__ ( "orl %%esp,%0; andl $~3,%0" + : "=r" (p) : "0" (STACK_SIZE-4) ); + return p; +} + +#define schedule_tail(_p) \ + __asm__ __volatile__ ( \ + "andl %%esp,%0; addl %2,%0; movl %0,%%esp; jmp *%1" \ + : : "r" (~(STACK_SIZE-1)), \ + "r" (unlikely(is_idle_task((_p))) ? \ + continue_cpu_idle_loop : \ + continue_nonidle_task), \ + "i" (STACK_SIZE-STACK_RESERVED) ) + + +#endif /* !(_I386_CURRENT_H) */ diff --git a/xen/include/asm-x86_64/debugreg.h b/xen/include/asm-x86_64/debugreg.h new file mode 100644 index 0000000000..f0b2b06ae0 --- /dev/null +++ b/xen/include/asm-x86_64/debugreg.h @@ -0,0 +1,64 @@ +#ifndef _I386_DEBUGREG_H +#define _I386_DEBUGREG_H + + +/* Indicate the register numbers for a number of the specific + debug registers. Registers 0-3 contain the addresses we wish to trap on */ +#define DR_FIRSTADDR 0 /* u_debugreg[DR_FIRSTADDR] */ +#define DR_LASTADDR 3 /* u_debugreg[DR_LASTADDR] */ + +#define DR_STATUS 6 /* u_debugreg[DR_STATUS] */ +#define DR_CONTROL 7 /* u_debugreg[DR_CONTROL] */ + +/* Define a few things for the status register. We can use this to determine + which debugging register was responsible for the trap. The other bits + are either reserved or not of interest to us. */ + +#define DR_TRAP0 (0x1) /* db0 */ +#define DR_TRAP1 (0x2) /* db1 */ +#define DR_TRAP2 (0x4) /* db2 */ +#define DR_TRAP3 (0x8) /* db3 */ + +#define DR_STEP (0x4000) /* single-step */ +#define DR_SWITCH (0x8000) /* task switch */ + +/* Now define a bunch of things for manipulating the control register. + The top two bytes of the control register consist of 4 fields of 4 + bits - each field corresponds to one of the four debug registers, + and indicates what types of access we trap on, and how large the data + field is that we are looking at */ + +#define DR_CONTROL_SHIFT 16 /* Skip this many bits in ctl register */ +#define DR_CONTROL_SIZE 4 /* 4 control bits per register */ + +#define DR_RW_EXECUTE (0x0) /* Settings for the access types to trap on */ +#define DR_RW_WRITE (0x1) +#define DR_RW_READ (0x3) + +#define DR_LEN_1 (0x0) /* Settings for data length to trap on */ +#define DR_LEN_2 (0x4) +#define DR_LEN_4 (0xC) + +/* The low byte to the control register determine which registers are + enabled. There are 4 fields of two bits. One bit is "local", meaning + that the processor will reset the bit after a task switch and the other + is global meaning that we have to explicitly reset the bit. With linux, + you can use either one, since we explicitly zero the register when we enter + kernel mode. */ + +#define DR_LOCAL_ENABLE_SHIFT 0 /* Extra shift to the local enable bit */ +#define DR_GLOBAL_ENABLE_SHIFT 1 /* Extra shift to the global enable bit */ +#define DR_ENABLE_SIZE 2 /* 2 enable bits per register */ + +#define DR_LOCAL_ENABLE_MASK (0x55) /* Set local bits for all 4 regs */ +#define DR_GLOBAL_ENABLE_MASK (0xAA) /* Set global bits for all 4 regs */ + +/* The second byte to the control register has a few special things. + We can slow the instruction pipeline for instructions coming via the + gdt or the ldt if we want to. I am not sure why this is an advantage */ + +#define DR_CONTROL_RESERVED (0xFC00) /* Reserved by Intel */ +#define DR_LOCAL_SLOWDOWN (0x100) /* Local slow the pipeline */ +#define DR_GLOBAL_SLOWDOWN (0x200) /* Global slow the pipeline */ + +#endif diff --git a/xen/include/asm-x86_64/delay.h b/xen/include/asm-x86_64/delay.h new file mode 100644 index 0000000000..9e0adb4a27 --- /dev/null +++ b/xen/include/asm-x86_64/delay.h @@ -0,0 +1,14 @@ +#ifndef _I386_DELAY_H +#define _I386_DELAY_H + +/* + * Copyright (C) 1993 Linus Torvalds + * + * Delay routines calling functions in arch/i386/lib/delay.c + */ + +extern unsigned long ticks_per_usec; +extern void __udelay(unsigned long usecs); +#define udelay(n) __udelay(n) + +#endif /* defined(_I386_DELAY_H) */ diff --git a/xen/include/asm-x86_64/desc.h b/xen/include/asm-x86_64/desc.h new file mode 100644 index 0000000000..780f9c8728 --- /dev/null +++ b/xen/include/asm-x86_64/desc.h @@ -0,0 +1,58 @@ +#ifndef __ARCH_DESC_H +#define __ARCH_DESC_H + +#define LDT_ENTRY_SIZE 8 + +#define __DOUBLEFAULT_TSS_ENTRY FIRST_RESERVED_GDT_ENTRY + +#define __FIRST_TSS_ENTRY (FIRST_RESERVED_GDT_ENTRY + 8) +#define __FIRST_LDT_ENTRY (__FIRST_TSS_ENTRY + 1) + +#define __TSS(n) (((n)<<1) + __FIRST_TSS_ENTRY) +#define __LDT(n) (((n)<<1) + __FIRST_LDT_ENTRY) + +#define load_TR(n) __asm__ __volatile__ ("ltr %%ax" : : "a" (__TSS(n)<<3) ) + +/* + * Guest OS must provide its own code selectors, or use the one we provide. The + * RPL must be 1, as we only create bounce frames to ring 1. Any LDT selector + * value is okay. Note that checking only the RPL is insufficient: if the + * selector is poked into an interrupt, trap or call gate then the RPL is + * ignored when the gate is accessed. + */ +#define VALID_SEL(_s) \ + (((((_s)>>3) < FIRST_RESERVED_GDT_ENTRY) || \ + (((_s)>>3) > LAST_RESERVED_GDT_ENTRY) || \ + ((_s)&4)) && \ + (((_s)&3) == 1)) +#define VALID_CODESEL(_s) ((_s) == FLAT_RING1_CS || VALID_SEL(_s)) + +/* These are bitmasks for the first 32 bits of a descriptor table entry. */ +#define _SEGMENT_TYPE (15<< 8) +#define _SEGMENT_S ( 1<<12) /* System descriptor (yes iff S==0) */ +#define _SEGMENT_DPL ( 3<<13) /* Descriptor Privilege Level */ +#define _SEGMENT_P ( 1<<15) /* Segment Present */ +#define _SEGMENT_G ( 1<<23) /* Granularity */ + +#ifndef __ASSEMBLY__ +struct desc_struct { + unsigned long a,b; +}; + +extern struct desc_struct gdt_table[]; +extern struct desc_struct *idt, *gdt; + +struct Xgt_desc_struct { + unsigned short size; + unsigned long address __attribute__((packed)); +}; + +#define idt_descr (*(struct Xgt_desc_struct *)((char *)&idt - 2)) +#define gdt_descr (*(struct Xgt_desc_struct *)((char *)&gdt - 2)) + +extern void set_intr_gate(unsigned int irq, void * addr); +extern void set_tss_desc(unsigned int n, void *addr); + +#endif /* !__ASSEMBLY__ */ + +#endif diff --git a/xen/include/asm-x86_64/dma.h b/xen/include/asm-x86_64/dma.h new file mode 100644 index 0000000000..f24c90a7bd --- /dev/null +++ b/xen/include/asm-x86_64/dma.h @@ -0,0 +1,301 @@ +/* $Id: dma.h,v 1.7 1992/12/14 00:29:34 root Exp root $ + * linux/include/asm/dma.h: Defines for using and allocating dma channels. + * Written by Hennus Bergman, 1992. + * High DMA channel support & info by Hannu Savolainen + * and John Boyd, Nov. 1992. + */ + +#ifndef _ASM_DMA_H +#define _ASM_DMA_H + +#include <linux/config.h> +#include <linux/spinlock.h> /* And spinlocks */ +#include <asm/io.h> /* need byte IO */ +#include <linux/delay.h> + + +#ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER +#define dma_outb outb_p +#else +#define dma_outb outb +#endif + +#define dma_inb inb + +/* + * NOTES about DMA transfers: + * + * controller 1: channels 0-3, byte operations, ports 00-1F + * controller 2: channels 4-7, word operations, ports C0-DF + * + * - ALL registers are 8 bits only, regardless of transfer size + * - channel 4 is not used - cascades 1 into 2. + * - channels 0-3 are byte - addresses/counts are for physical bytes + * - channels 5-7 are word - addresses/counts are for physical words + * - transfers must not cross physical 64K (0-3) or 128K (5-7) boundaries + * - transfer count loaded to registers is 1 less than actual count + * - controller 2 offsets are all even (2x offsets for controller 1) + * - page registers for 5-7 don't use data bit 0, represent 128K pages + * - page registers for 0-3 use bit 0, represent 64K pages + * + * DMA transfers are limited to the lower 16MB of _physical_ memory. + * Note that addresses loaded into registers must be _physical_ addresses, + * not logical addresses (which may differ if paging is active). + * + * Address mapping for channels 0-3: + * + * A23 ... A16 A15 ... A8 A7 ... A0 (Physical addresses) + * | ... | | ... | | ... | + * | ... | | ... | | ... | + * | ... | | ... | | ... | + * P7 ... P0 A7 ... A0 A7 ... A0 + * | Page | Addr MSB | Addr LSB | (DMA registers) + * + * Address mapping for channels 5-7: + * + * A23 ... A17 A16 A15 ... A9 A8 A7 ... A1 A0 (Physical addresses) + * | ... | \ \ ... \ \ \ ... \ \ + * | ... | \ \ ... \ \ \ ... \ (not used) + * | ... | \ \ ... \ \ \ ... \ + * P7 ... P1 (0) A7 A6 ... A0 A7 A6 ... A0 + * | Page | Addr MSB | Addr LSB | (DMA registers) + * + * Again, channels 5-7 transfer _physical_ words (16 bits), so addresses + * and counts _must_ be word-aligned (the lowest address bit is _ignored_ at + * the hardware level, so odd-byte transfers aren't possible). + * + * Transfer count (_not # bytes_) is limited to 64K, represented as actual + * count - 1 : 64K => 0xFFFF, 1 => 0x0000. Thus, count is always 1 or more, + * and up to 128K bytes may be transferred on channels 5-7 in one operation. + * + */ + +#define MAX_DMA_CHANNELS 8 + +#if 0 +/* The maximum address that we can perform a DMA transfer to on this platform */ +#define MAX_DMA_ADDRESS (PAGE_OFFSET+0x1000000) +#endif + + +/* 8237 DMA controllers */ +#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */ +#define IO_DMA2_BASE 0xC0 /* 16 bit master DMA, ch 4(=slave input)..7 */ + +/* DMA controller registers */ +#define DMA1_CMD_REG 0x08 /* command register (w) */ +#define DMA1_STAT_REG 0x08 /* status register (r) */ +#define DMA1_REQ_REG 0x09 /* request register (w) */ +#define DMA1_MASK_REG 0x0A /* single-channel mask (w) */ +#define DMA1_MODE_REG 0x0B /* mode register (w) */ +#define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */ +#define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */ +#define DMA1_RESET_REG 0x0D /* Master Clear (w) */ +#define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */ +#define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */ + +#define DMA2_CMD_REG 0xD0 /* command register (w) */ +#define DMA2_STAT_REG 0xD0 /* status register (r) */ +#define DMA2_REQ_REG 0xD2 /* request register (w) */ +#define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */ +#define DMA2_MODE_REG 0xD6 /* mode register (w) */ +#define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */ +#define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */ +#define DMA2_RESET_REG 0xDA /* Master Clear (w) */ +#define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */ +#define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */ + +#define DMA_ADDR_0 0x00 /* DMA address registers */ +#define DMA_ADDR_1 0x02 +#define DMA_ADDR_2 0x04 +#define DMA_ADDR_3 0x06 +#define DMA_ADDR_4 0xC0 +#define DMA_ADDR_5 0xC4 +#define DMA_ADDR_6 0xC8 +#define DMA_ADDR_7 0xCC + +#define DMA_CNT_0 0x01 /* DMA count registers */ +#define DMA_CNT_1 0x03 +#define DMA_CNT_2 0x05 +#define DMA_CNT_3 0x07 +#define DMA_CNT_4 0xC2 +#define DMA_CNT_5 0xC6 +#define DMA_CNT_6 0xCA +#define DMA_CNT_7 0xCE + +#define DMA_PAGE_0 0x87 /* DMA page registers */ +#define DMA_PAGE_1 0x83 +#define DMA_PAGE_2 0x81 +#define DMA_PAGE_3 0x82 +#define DMA_PAGE_5 0x8B +#define DMA_PAGE_6 0x89 +#define DMA_PAGE_7 0x8A + +#define DMA_MODE_READ 0x44 /* I/O to memory, no autoinit, increment, single mode */ +#define DMA_MODE_WRITE 0x48 /* memory to I/O, no autoinit, increment, single mode */ +#define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */ + +#define DMA_AUTOINIT 0x10 + + +extern spinlock_t dma_spin_lock; + +static __inline__ unsigned long claim_dma_lock(void) +{ + unsigned long flags; + spin_lock_irqsave(&dma_spin_lock, flags); + return flags; +} + +static __inline__ void release_dma_lock(unsigned long flags) +{ + spin_unlock_irqrestore(&dma_spin_lock, flags); +} + +/* enable/disable a specific DMA channel */ +static __inline__ void enable_dma(unsigned int dmanr) +{ + if (dmanr<=3) + dma_outb(dmanr, DMA1_MASK_REG); + else + dma_outb(dmanr & 3, DMA2_MASK_REG); +} + +static __inline__ void disable_dma(unsigned int dmanr) +{ + if (dmanr<=3) + dma_outb(dmanr | 4, DMA1_MASK_REG); + else + dma_outb((dmanr & 3) | 4, DMA2_MASK_REG); +} + +/* Clear the 'DMA Pointer Flip Flop'. + * Write 0 for LSB/MSB, 1 for MSB/LSB access. + * Use this once to initialize the FF to a known state. + * After that, keep track of it. :-) + * --- In order to do that, the DMA routines below should --- + * --- only be used while holding the DMA lock ! --- + */ +static __inline__ void clear_dma_ff(unsigned int dmanr) +{ + if (dmanr<=3) + dma_outb(0, DMA1_CLEAR_FF_REG); + else + dma_outb(0, DMA2_CLEAR_FF_REG); +} + +/* set mode (above) for a specific DMA channel */ +static __inline__ void set_dma_mode(unsigned int dmanr, char mode) +{ + if (dmanr<=3) + dma_outb(mode | dmanr, DMA1_MODE_REG); + else + dma_outb(mode | (dmanr&3), DMA2_MODE_REG); +} + +/* Set only the page register bits of the transfer address. + * This is used for successive transfers when we know the contents of + * the lower 16 bits of the DMA current address register, but a 64k boundary + * may have been crossed. + */ +static __inline__ void set_dma_page(unsigned int dmanr, char pagenr) +{ + switch(dmanr) { + case 0: + dma_outb(pagenr, DMA_PAGE_0); + break; + case 1: + dma_outb(pagenr, DMA_PAGE_1); + break; + case 2: + dma_outb(pagenr, DMA_PAGE_2); + break; + case 3: + dma_outb(pagenr, DMA_PAGE_3); + break; + case 5: + dma_outb(pagenr & 0xfe, DMA_PAGE_5); + break; + case 6: + dma_outb(pagenr & 0xfe, DMA_PAGE_6); + break; + case 7: + dma_outb(pagenr & 0xfe, DMA_PAGE_7); + break; + } +} + + +/* Set transfer address & page bits for specific DMA channel. + * Assumes dma flipflop is clear. + */ +static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int a) +{ + set_dma_page(dmanr, a>>16); + if (dmanr <= 3) { + dma_outb( a & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ); + dma_outb( (a>>8) & 0xff, ((dmanr&3)<<1) + IO_DMA1_BASE ); + } else { + dma_outb( (a>>1) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); + dma_outb( (a>>9) & 0xff, ((dmanr&3)<<2) + IO_DMA2_BASE ); + } +} + + +/* Set transfer size (max 64k for DMA1..3, 128k for DMA5..7) for + * a specific DMA channel. + * You must ensure the parameters are valid. + * NOTE: from a manual: "the number of transfers is one more + * than the initial word count"! This is taken into account. + * Assumes dma flip-flop is clear. + * NOTE 2: "count" represents _bytes_ and must be even for channels 5-7. + */ +static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count) +{ + count--; + if (dmanr <= 3) { + dma_outb( count & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); + dma_outb( (count>>8) & 0xff, ((dmanr&3)<<1) + 1 + IO_DMA1_BASE ); + } else { + dma_outb( (count>>1) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); + dma_outb( (count>>9) & 0xff, ((dmanr&3)<<2) + 2 + IO_DMA2_BASE ); + } +} + + +/* Get DMA residue count. After a DMA transfer, this + * should return zero. Reading this while a DMA transfer is + * still in progress will return unpredictable results. + * If called before the channel has been used, it may return 1. + * Otherwise, it returns the number of _bytes_ left to transfer. + * + * Assumes DMA flip-flop is clear. + */ +static __inline__ int get_dma_residue(unsigned int dmanr) +{ + unsigned int io_port = (dmanr<=3)? ((dmanr&3)<<1) + 1 + IO_DMA1_BASE + : ((dmanr&3)<<2) + 2 + IO_DMA2_BASE; + + /* using short to get 16-bit wrap around */ + unsigned short count; + + count = 1 + dma_inb(io_port); + count += dma_inb(io_port) << 8; + + return (dmanr<=3)? count : (count<<1); +} + + +/* These are in kernel/dma.c: */ +extern int request_dma(unsigned int dmanr, const char * device_id); /* reserve a DMA channel */ +extern void free_dma(unsigned int dmanr); /* release it again */ + +/* From PCI */ + +#ifdef CONFIG_PCI +extern int isa_dma_bridge_buggy; +#else +#define isa_dma_bridge_buggy (0) +#endif + +#endif /* _ASM_DMA_H */ diff --git a/xen/include/asm-x86_64/domain_page.h b/xen/include/asm-x86_64/domain_page.h new file mode 100644 index 0000000000..1d38d8b310 --- /dev/null +++ b/xen/include/asm-x86_64/domain_page.h @@ -0,0 +1,29 @@ +/****************************************************************************** + * domain_page.h + * + * Allow temporary mapping of domain page frames into Xen space. + */ + +#ifndef __ASM_DOMAIN_PAGE_H__ +#define __ASM_DOMAIN_PAGE_H__ + +#include <xeno/config.h> +#include <xeno/sched.h> + +extern unsigned long *mapcache; +#define MAPCACHE_ENTRIES 1024 + +/* + * Maps a given physical address, returning corresponding virtual address. + * The entire page containing that VA is now accessible until a + * corresponding call to unmap_domain_mem(). + */ +extern void *map_domain_mem(unsigned long pa); + +/* + * Pass a VA within a page previously mapped with map_domain_mem(). + * That page will then be removed from the mapping lists. + */ +extern void unmap_domain_mem(void *va); + +#endif /* __ASM_DOMAIN_PAGE_H__ */ diff --git a/xen/include/asm-x86_64/elf.h b/xen/include/asm-x86_64/elf.h new file mode 100644 index 0000000000..ded22856d0 --- /dev/null +++ b/xen/include/asm-x86_64/elf.h @@ -0,0 +1,233 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1996 Erich Boleyn <erich@uruk.org> + * Copyright (C) 2001 Free Software Foundation, 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* 32-bit data types */ + +typedef unsigned long Elf32_Addr; +typedef unsigned short Elf32_Half; +typedef unsigned long Elf32_Off; +typedef signed long Elf32_Sword; +typedef unsigned long Elf32_Word; +/* "unsigned char" already exists */ + +/* ELF header */ +typedef struct +{ + +#define EI_NIDENT 16 + + /* first four characters are defined below */ +#define EI_MAG0 0 +#define ELFMAG0 0x7f +#define EI_MAG1 1 +#define ELFMAG1 'E' +#define EI_MAG2 2 +#define ELFMAG2 'L' +#define EI_MAG3 3 +#define ELFMAG3 'F' + +#define EI_CLASS 4 /* data sizes */ +#define ELFCLASS32 1 /* i386 -- up to 32-bit data sizes present */ + +#define EI_DATA 5 /* data type and ordering */ +#define ELFDATA2LSB 1 /* i386 -- LSB 2's complement */ + +#define EI_VERSION 6 /* version number. "e_version" must be the same */ +#define EV_CURRENT 1 /* current version number */ + +#define EI_PAD 7 /* from here in is just padding */ + +#define EI_BRAND 8 /* start of OS branding (This is + obviously illegal against the ELF + standard.) */ + + unsigned char e_ident[EI_NIDENT]; /* basic identification block */ + +#define ET_EXEC 2 /* we only care about executable types */ + Elf32_Half e_type; /* file types */ + +#define EM_386 3 /* i386 -- obviously use this one */ + Elf32_Half e_machine; /* machine types */ + Elf32_Word e_version; /* use same as "EI_VERSION" above */ + Elf32_Addr e_entry; /* entry point of the program */ + Elf32_Off e_phoff; /* program header table file offset */ + Elf32_Off e_shoff; /* section header table file offset */ + Elf32_Word e_flags; /* flags */ + Elf32_Half e_ehsize; /* elf header size in bytes */ + Elf32_Half e_phentsize; /* program header entry size */ + Elf32_Half e_phnum; /* number of entries in program header */ + Elf32_Half e_shentsize; /* section header entry size */ + Elf32_Half e_shnum; /* number of entries in section header */ + +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff + Elf32_Half e_shstrndx; /* section header table index */ +} +Elf32_Ehdr; + + +#define BOOTABLE_I386_ELF(h) \ + ((h.e_ident[EI_MAG0] == ELFMAG0) & (h.e_ident[EI_MAG1] == ELFMAG1) \ + & (h.e_ident[EI_MAG2] == ELFMAG2) & (h.e_ident[EI_MAG3] == ELFMAG3) \ + & (h.e_ident[EI_CLASS] == ELFCLASS32) & (h.e_ident[EI_DATA] == ELFDATA2LSB) \ + & (h.e_ident[EI_VERSION] == EV_CURRENT) & (h.e_type == ET_EXEC) \ + & (h.e_machine == EM_386) & (h.e_version == EV_CURRENT)) + +/* section table - ? */ +typedef struct +{ + Elf32_Word sh_name; /* Section name (string tbl index) */ + Elf32_Word sh_type; /* Section type */ + Elf32_Word sh_flags; /* Section flags */ + Elf32_Addr sh_addr; /* Section virtual addr at execution */ + Elf32_Off sh_offset; /* Section file offset */ + Elf32_Word sh_size; /* Section size in bytes */ + Elf32_Word sh_link; /* Link to another section */ + Elf32_Word sh_info; /* Additional section information */ + Elf32_Word sh_addralign; /* Section alignment */ + Elf32_Word sh_entsize; /* Entry size if section holds table */ +} +Elf32_Shdr; + +/* symbol table - page 4-25, figure 4-15 */ +typedef struct +{ + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} +Elf32_Sym; + +/* symbol type and binding attributes - page 4-26 */ + +#define ELF32_ST_BIND(i) ((i) >> 4) +#define ELF32_ST_TYPE(i) ((i) & 0xf) +#define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf)) + +/* symbol binding - page 4-26, figure 4-16 */ + +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 +#define STB_LOPROC 13 +#define STB_HIPROC 15 + +/* symbol types - page 4-28, figure 4-17 */ + +#define STT_NOTYPE 0 +#define STT_OBJECT 1 +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 +#define STT_LOPROC 13 +#define STT_HIPROC 15 + + +/* Macros to split/combine relocation type and symbol page 4-32 */ + +#define ELF32_R_SYM(__i) ((__i)>>8) +#define ELF32_R_TYPE(__i) ((unsigned char) (__i)) +#define ELF32_R_INFO(__s, __t) (((__s)<<8) + (unsigned char) (__t)) + + +/* program header - page 5-2, figure 5-1 */ + +typedef struct +{ + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} +Elf32_Phdr; + +/* segment types - page 5-3, figure 5-2 */ + +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 + +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff + +/* segment permissions - page 5-6 */ + +#define PF_X 0x1 +#define PF_W 0x2 +#define PF_R 0x4 +#define PF_MASKPROC 0xf0000000 + + +/* dynamic structure - page 5-15, figure 5-9 */ + +typedef struct +{ + Elf32_Sword d_tag; + union + { + Elf32_Word d_val; + Elf32_Addr d_ptr; + } + d_un; +} +Elf32_Dyn; + +/* Dynamic array tags - page 5-16, figure 5-10. */ + +#define DT_NULL 0 +#define DT_NEEDED 1 +#define DT_PLTRELSZ 2 +#define DT_PLTGOT 3 +#define DT_HASH 4 +#define DT_STRTAB 5 +#define DT_SYMTAB 6 +#define DT_RELA 7 +#define DT_RELASZ 8 +#define DT_RELAENT 9 +#define DT_STRSZ 10 +#define DT_SYMENT 11 +#define DT_INIT 12 +#define DT_FINI 13 +#define DT_SONAME 14 +#define DT_RPATH 15 +#define DT_SYMBOLIC 16 +#define DT_REL 17 +#define DT_RELSZ 18 +#define DT_RELENT 19 +#define DT_PLTREL 20 +#define DT_DEBUG 21 +#define DT_TEXTREL 22 +#define DT_JMPREL 23 diff --git a/xen/include/asm-x86_64/fixmap.h b/xen/include/asm-x86_64/fixmap.h new file mode 100644 index 0000000000..b0f455a5af --- /dev/null +++ b/xen/include/asm-x86_64/fixmap.h @@ -0,0 +1,107 @@ +/* + * fixmap.h: compile-time virtual memory allocation + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1998 Ingo Molnar + * + * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999 + */ + +#ifndef _ASM_FIXMAP_H +#define _ASM_FIXMAP_H + +#include <xeno/config.h> +#include <asm/apicdef.h> +#include <asm/page.h> + +/* + * Here we define all the compile-time 'special' virtual + * addresses. The point is to have a constant address at + * compile time, but to set the physical address only + * in the boot process. We allocate these special addresses + * from the end of virtual memory (0xfffff000) backwards. + * Also this lets us do fail-safe vmalloc(), we + * can guarantee that these special addresses and + * vmalloc()-ed addresses never overlap. + * + * these 'compile-time allocated' memory buffers are + * fixed-size 4k pages. (or larger if used with an increment + * highger than 1) use fixmap_set(idx,phys) to associate + * physical memory with fixmap indices. + * + * TLB entries of such buffers will not be flushed across + * task switches. + */ + +/* + * on UP currently we will have no trace of the fixmap mechanizm, + * no page table allocations, etc. This might change in the + * future, say framebuffers for the console driver(s) could be + * fix-mapped? + */ +enum fixed_addresses { +#ifdef CONFIG_X86_LOCAL_APIC + FIX_APIC_BASE, /* local (CPU) APIC) -- required for SMP or not */ +#endif +#ifdef CONFIG_X86_IO_APIC + FIX_IO_APIC_BASE_0, + FIX_IO_APIC_BASE_END = FIX_IO_APIC_BASE_0 + MAX_IO_APICS-1, +#endif +#ifdef CONFIG_HIGHMEM + FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */ + FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1, +#endif + __end_of_fixed_addresses +}; + +extern void __set_fixmap (enum fixed_addresses idx, + l1_pgentry_t entry); + +#define set_fixmap(idx, phys) \ + __set_fixmap(idx, mk_l1_pgentry(phys|PAGE_HYPERVISOR)) +/* + * Some hardware wants to get fixmapped without caching. + */ +#define set_fixmap_nocache(idx, phys) \ + __set_fixmap(idx, mk_l1_pgentry(phys|PAGE_HYPERVISOR_NOCACHE)) +/* + * used by vmalloc.c. + * + * Leave one empty page between vmalloc'ed areas and + * the start of the fixmap, and leave one page empty + * at the top of mem.. + */ +#define FIXADDR_TOP (0xffffe000UL) +#define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) +#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) + +#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT)) + +extern void __this_fixmap_does_not_exist(void); + +/* + * 'index to address' translation. If anyone tries to use the idx + * directly without tranlation, we catch the bug with a NULL-deference + * kernel oops. Illegal ranges of incoming indices are caught too. + */ +static inline unsigned long fix_to_virt(const unsigned int idx) +{ + /* + * this branch gets completely eliminated after inlining, + * except when someone tries to use fixaddr indices in an + * illegal way. (such as mixing up address types or using + * out-of-range indices). + * + * If it doesn't get removed, the linker will complain + * loudly with a reasonably clear error message.. + */ + if (idx >= __end_of_fixed_addresses) + __this_fixmap_does_not_exist(); + + return __fix_to_virt(idx); +} + +#endif diff --git a/xen/include/asm-x86_64/flushtlb.h b/xen/include/asm-x86_64/flushtlb.h new file mode 100644 index 0000000000..49760ef70c --- /dev/null +++ b/xen/include/asm-x86_64/flushtlb.h @@ -0,0 +1,39 @@ +/****************************************************************************** + * flushtlb.h + * + * TLB flushes are timestamped using a global virtual 'clock' which ticks + * on any TLB flush on any processor. + * + * Copyright (c) 2003, K A Fraser + */ + +#ifndef __FLUSHTLB_H__ +#define __FLUSHTLB_H__ + +#include <xeno/smp.h> + +/* + * Every GLOBAL_FLUSH_PERIOD ticks of the tlbflush clock, every TLB in the + * system is guaranteed to have been flushed. + */ +#define GLOBAL_FLUSH_PERIOD (1<<16) + +/* + * '_cpu_stamp' is the current timestamp for the CPU we are testing. + * '_lastuse_stamp' is a timestamp taken when the PFN we are testing was last + * used for a purpose that may have caused the CPU's TLB to become tainted. + */ +#define NEED_FLUSH(_cpu_stamp, _lastuse_stamp) \ + (((_cpu_stamp) <= (_lastuse_stamp)) && \ + (((_lastuse_stamp) - (_cpu_stamp)) <= (2*GLOBAL_FLUSH_PERIOD))) + +extern unsigned long tlbflush_mask; +extern unsigned long tlbflush_clock; +extern unsigned long tlbflush_time[NR_CPUS]; + +extern void new_tlbflush_clock_period(void); + +extern void write_cr3_counted(unsigned long pa); +extern void flush_tlb_counted(void); + +#endif /* __FLUSHTLB_H__ */ diff --git a/xen/include/asm-x86_64/hardirq.h b/xen/include/asm-x86_64/hardirq.h new file mode 100644 index 0000000000..9afe12e2ab --- /dev/null +++ b/xen/include/asm-x86_64/hardirq.h @@ -0,0 +1,90 @@ +#ifndef __ASM_HARDIRQ_H +#define __ASM_HARDIRQ_H + +#include <xeno/config.h> +#include <xeno/irq.h> + +/* assembly code in softirq.h is sensitive to the offsets of these fields */ +typedef struct { + unsigned int __softirq_pending; + unsigned int __local_irq_count; + unsigned int __local_bh_count; + unsigned int __syscall_count; + unsigned int __nmi_count; + unsigned long idle_timestamp; +} ____cacheline_aligned irq_cpustat_t; + +#include <xeno/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ + +/* + * Are we in an interrupt context? Either doing bottom half + * or hardware interrupt processing? + */ +#define in_interrupt() ({ int __cpu = smp_processor_id(); \ + (local_irq_count(__cpu) + local_bh_count(__cpu) != 0); }) + +#define in_irq() (local_irq_count(smp_processor_id()) != 0) + +#ifndef CONFIG_SMP + +#define hardirq_trylock(cpu) (local_irq_count(cpu) == 0) +#define hardirq_endlock(cpu) do { } while (0) + +#define irq_enter(cpu, irq) (local_irq_count(cpu)++) +#define irq_exit(cpu, irq) (local_irq_count(cpu)--) + +#define synchronize_irq() barrier() + +#else + +#include <asm/atomic.h> +#include <asm/smp.h> + +extern unsigned char global_irq_holder; +extern unsigned volatile long global_irq_lock; /* long for set_bit -RR */ + +static inline int irqs_running (void) +{ + int i; + + for (i = 0; i < smp_num_cpus; i++) + if (local_irq_count(i)) + return 1; + return 0; +} + +static inline void release_irqlock(int cpu) +{ + /* if we didn't own the irq lock, just ignore.. */ + if (global_irq_holder == (unsigned char) cpu) { + global_irq_holder = 0xff; + clear_bit(0,&global_irq_lock); + } +} + +static inline void irq_enter(int cpu, int irq) +{ + ++local_irq_count(cpu); + + while (test_bit(0,&global_irq_lock)) { + cpu_relax(); + } +} + +static inline void irq_exit(int cpu, int irq) +{ + --local_irq_count(cpu); +} + +static inline int hardirq_trylock(int cpu) +{ + return !local_irq_count(cpu) && !test_bit(0,&global_irq_lock); +} + +#define hardirq_endlock(cpu) do { } while (0) + +extern void synchronize_irq(void); + +#endif /* CONFIG_SMP */ + +#endif /* __ASM_HARDIRQ_H */ diff --git a/xen/include/asm-x86_64/hdreg.h b/xen/include/asm-x86_64/hdreg.h new file mode 100644 index 0000000000..1ad5c07394 --- /dev/null +++ b/xen/include/asm-x86_64/hdreg.h @@ -0,0 +1,12 @@ +/* + * linux/include/asm-i386/hdreg.h + * + * Copyright (C) 1994-1996 Linus Torvalds & authors + */ + +#ifndef __ASMi386_HDREG_H +#define __ASMi386_HDREG_H + +typedef unsigned short ide_ioreg_t; + +#endif /* __ASMi386_HDREG_H */ diff --git a/xen/include/asm-x86_64/i387.h b/xen/include/asm-x86_64/i387.h new file mode 100644 index 0000000000..5a3f0fd5e6 --- /dev/null +++ b/xen/include/asm-x86_64/i387.h @@ -0,0 +1,38 @@ +/* + * include/asm-i386/i387.h + * + * Copyright (C) 1994 Linus Torvalds + * + * Pentium III FXSR, SSE support + * General FPU state handling cleanups + * Gareth Hughes <gareth@valinux.com>, May 2000 + */ + +#ifndef __ASM_I386_I387_H +#define __ASM_I386_I387_H + +#include <xeno/sched.h> +#include <asm/processor.h> + +extern void init_fpu(void); +extern void save_init_fpu( struct task_struct *tsk ); +extern void restore_fpu( struct task_struct *tsk ); + +#define unlazy_fpu( tsk ) do { \ + if ( test_bit(PF_USEDFPU, &tsk->flags) ) \ + save_init_fpu( tsk ); \ +} while (0) + +#define clear_fpu( tsk ) do { \ + if ( test_and_clear_bit(PF_USEDFPU, &tsk->flags) ) { \ + asm volatile("fwait"); \ + stts(); \ + } \ +} while (0) + +#define load_mxcsr( val ) do { \ + unsigned long __mxcsr = ((unsigned long)(val) & 0xffbf); \ + asm volatile( "ldmxcsr %0" : : "m" (__mxcsr) ); \ +} while (0) + +#endif /* __ASM_I386_I387_H */ diff --git a/xen/include/asm-x86_64/ide.h b/xen/include/asm-x86_64/ide.h new file mode 100644 index 0000000000..6642abf467 --- /dev/null +++ b/xen/include/asm-x86_64/ide.h @@ -0,0 +1,128 @@ +/* + * linux/include/asm-i386/ide.h + * + * Copyright (C) 1994-1996 Linus Torvalds & authors + */ + +/* + * This file contains the i386 architecture specific IDE code. + */ + +#ifndef __ASMi386_IDE_H +#define __ASMi386_IDE_H + +#ifdef __KERNEL__ + +#include <linux/config.h> + +#ifndef MAX_HWIFS +# ifdef CONFIG_BLK_DEV_IDEPCI +#define MAX_HWIFS 10 +# else +#define MAX_HWIFS 6 +# endif +#endif + +#define ide__sti() __sti() + +static __inline__ int ide_default_irq(ide_ioreg_t base) +{ + switch (base) { + case 0x1f0: return 14; + case 0x170: return 15; + case 0x1e8: return 11; + case 0x168: return 10; + case 0x1e0: return 8; + case 0x160: return 12; + default: + return 0; + } +} + +static __inline__ ide_ioreg_t ide_default_io_base(int index) +{ + switch (index) { + case 0: return 0x1f0; + case 1: return 0x170; + case 2: return 0x1e8; + case 3: return 0x168; + case 4: return 0x1e0; + case 5: return 0x160; + default: + return 0; + } +} + +static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq) +{ + ide_ioreg_t reg = data_port; + int i; + + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { + hw->io_ports[i] = reg; + reg += 1; + } + if (ctrl_port) { + hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; + } else { + hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206; + } + if (irq != NULL) + *irq = 0; + hw->io_ports[IDE_IRQ_OFFSET] = 0; +} + +static __inline__ void ide_init_default_hwifs(void) +{ +#ifndef CONFIG_BLK_DEV_IDEPCI + hw_regs_t hw; + int index; + + for(index = 0; index < MAX_HWIFS; index++) { + ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL); + hw.irq = ide_default_irq(ide_default_io_base(index)); + ide_register_hw(&hw, NULL); + } +#endif /* CONFIG_BLK_DEV_IDEPCI */ +} + +typedef union { + unsigned all : 8; /* all of the bits together */ + struct { + unsigned head : 4; /* always zeros here */ + unsigned unit : 1; /* drive select number, 0 or 1 */ + unsigned bit5 : 1; /* always 1 */ + unsigned lba : 1; /* using LBA instead of CHS */ + unsigned bit7 : 1; /* always 1 */ + } b; +} select_t; + +typedef union { + unsigned all : 8; /* all of the bits together */ + struct { + unsigned bit0 : 1; + unsigned nIEN : 1; /* device INTRQ to host */ + unsigned SRST : 1; /* host soft reset bit */ + unsigned bit3 : 1; /* ATA-2 thingy */ + unsigned reserved456 : 3; + unsigned HOB : 1; /* 48-bit address ordering */ + } b; +} control_t; + +#define ide_request_irq(irq,hand,flg,dev,id) request_irq((irq),(hand),(flg),(dev),(id)) +#define ide_free_irq(irq,dev_id) free_irq((irq), (dev_id)) +#define ide_check_region(from,extent) check_region((from), (extent)) +#define ide_request_region(from,extent,name) request_region((from), (extent), (name)) +#define ide_release_region(from,extent) release_region((from), (extent)) + +/* + * The following are not needed for the non-m68k ports + */ +#define ide_ack_intr(hwif) (1) +#define ide_fix_driveid(id) do {} while (0) +#define ide_release_lock(lock) do {} while (0) +#define ide_get_lock(lock, hdlr, data) do {} while (0) + +#endif /* __KERNEL__ */ + +#endif /* __ASMi386_IDE_H */ diff --git a/xen/include/asm-x86_64/io.h b/xen/include/asm-x86_64/io.h new file mode 100644 index 0000000000..8260e8de95 --- /dev/null +++ b/xen/include/asm-x86_64/io.h @@ -0,0 +1,284 @@ +#ifndef _ASM_IO_H +#define _ASM_IO_H + +#include <xeno/config.h> +#include <asm/page.h> + +#define IO_SPACE_LIMIT 0xffff + +/*#include <linux/vmalloc.h>*/ + +/* + * Temporary debugging check to catch old code using + * unmapped ISA addresses. Will be removed in 2.4. + */ +#if CONFIG_DEBUG_IOVIRT + extern void *__io_virt_debug(unsigned long x, const char *file, int line); + extern unsigned long __io_phys_debug(unsigned long x, const char *file, int line); + #define __io_virt(x) __io_virt_debug((unsigned long)(x), __FILE__, __LINE__) +//#define __io_phys(x) __io_phys_debug((unsigned long)(x), __FILE__, __LINE__) +#else + #define __io_virt(x) ((void *)(x)) +//#define __io_phys(x) __pa(x) +#endif + + +/** + * virt_to_phys - map virtual addresses to physical + * @address: address to remap + * + * The returned physical address is the physical (CPU) mapping for + * the memory address given. It is only valid to use this function on + * addresses directly mapped or allocated via kmalloc. + * + * This function does not give bus mappings for DMA transfers. In + * almost all conceivable cases a device driver should not be using + * this function + */ + +static inline unsigned long virt_to_phys(volatile void * address) +{ + return __pa(address); +} + +/** + * phys_to_virt - map physical address to virtual + * @address: address to remap + * + * The returned virtual address is a current CPU mapping for + * the memory address given. It is only valid to use this function on + * addresses that have a kernel mapping + * + * This function does not handle bus mappings for DMA transfers. In + * almost all conceivable cases a device driver should not be using + * this function + */ + +static inline void * phys_to_virt(unsigned long address) +{ + return __va(address); +} + +/* + * Change "struct pfn_info" to physical address. + */ +#ifdef CONFIG_HIGHMEM64G +#define page_to_phys(page) ((u64)(page - frame_table) << PAGE_SHIFT) +#else +#define page_to_phys(page) ((page - frame_table) << PAGE_SHIFT) +#endif + +#define page_to_pfn(_page) ((unsigned long)((_page) - frame_table)) +#define page_to_virt(_page) phys_to_virt(page_to_phys(_page)) + + +extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags); + +static inline void * ioremap (unsigned long offset, unsigned long size) +{ + return __ioremap(offset, size, 0); +} + +/* + * This one maps high address device memory and turns off caching for that area. + * it's useful if some control registers are in such an area and write combining + * or read caching is not desirable: + */ +static inline void * ioremap_nocache (unsigned long offset, unsigned long size) +{ + return __ioremap(offset, size, _PAGE_PCD); +} + +extern void iounmap(void *addr); + +/* + * IO bus memory addresses are also 1:1 with the physical address + */ +#define virt_to_bus virt_to_phys +#define bus_to_virt phys_to_virt +#define page_to_bus page_to_phys + +/* + * readX/writeX() are used to access memory mapped devices. On some + * architectures the memory mapped IO stuff needs to be accessed + * differently. On the x86 architecture, we just read/write the + * memory location directly. + */ + +#define readb(addr) (*(volatile unsigned char *) __io_virt(addr)) +#define readw(addr) (*(volatile unsigned short *) __io_virt(addr)) +#define readl(addr) (*(volatile unsigned int *) __io_virt(addr)) +#define __raw_readb readb +#define __raw_readw readw +#define __raw_readl readl + +#define writeb(b,addr) (*(volatile unsigned char *) __io_virt(addr) = (b)) +#define writew(b,addr) (*(volatile unsigned short *) __io_virt(addr) = (b)) +#define writel(b,addr) (*(volatile unsigned int *) __io_virt(addr) = (b)) +#define __raw_writeb writeb +#define __raw_writew writew +#define __raw_writel writel + +#define memset_io(a,b,c) memset(__io_virt(a),(b),(c)) +#define memcpy_fromio(a,b,c) memcpy((a),__io_virt(b),(c)) +#define memcpy_toio(a,b,c) memcpy(__io_virt(a),(b),(c)) + +/* + * ISA space is 'always mapped' on a typical x86 system, no need to + * explicitly ioremap() it. The fact that the ISA IO space is mapped + * to PAGE_OFFSET is pure coincidence - it does not mean ISA values + * are physical addresses. The following constant pointer can be + * used as the IO-area pointer (it can be iounmapped as well, so the + * analogy with PCI is quite large): + */ +#define __ISA_IO_base ((char *)(PAGE_OFFSET)) + +#define isa_readb(a) readb(__ISA_IO_base + (a)) +#define isa_readw(a) readw(__ISA_IO_base + (a)) +#define isa_readl(a) readl(__ISA_IO_base + (a)) +#define isa_writeb(b,a) writeb(b,__ISA_IO_base + (a)) +#define isa_writew(w,a) writew(w,__ISA_IO_base + (a)) +#define isa_writel(l,a) writel(l,__ISA_IO_base + (a)) +#define isa_memset_io(a,b,c) memset_io(__ISA_IO_base + (a),(b),(c)) +#define isa_memcpy_fromio(a,b,c) memcpy_fromio((a),__ISA_IO_base + (b),(c)) +#define isa_memcpy_toio(a,b,c) memcpy_toio(__ISA_IO_base + (a),(b),(c)) + + +/* + * Again, i386 does not require mem IO specific function. + */ + +#define eth_io_copy_and_sum(a,b,c,d) eth_copy_and_sum((a),__io_virt(b),(c),(d)) +#define isa_eth_io_copy_and_sum(a,b,c,d) eth_copy_and_sum((a),__io_virt(__ISA_IO_base + (b)),(c),(d)) + +static inline int check_signature(unsigned long io_addr, + const unsigned char *signature, int length) +{ + int retval = 0; + do { + if (readb(io_addr) != *signature) + goto out; + io_addr++; + signature++; + length--; + } while (length); + retval = 1; +out: + return retval; +} + +static inline int isa_check_signature(unsigned long io_addr, + const unsigned char *signature, int length) +{ + int retval = 0; + do { + if (isa_readb(io_addr) != *signature) + goto out; + io_addr++; + signature++; + length--; + } while (length); + retval = 1; +out: + return retval; +} + +/* + * Cache management + * + * This needed for two cases + * 1. Out of order aware processors + * 2. Accidentally out of order processors (PPro errata #51) + */ + +#if defined(CONFIG_X86_OOSTORE) || defined(CONFIG_X86_PPRO_FENCE) + +static inline void flush_write_buffers(void) +{ + __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory"); +} + +#define dma_cache_inv(_start,_size) flush_write_buffers() +#define dma_cache_wback(_start,_size) flush_write_buffers() +#define dma_cache_wback_inv(_start,_size) flush_write_buffers() + +#else + +/* Nothing to do */ + +#define dma_cache_inv(_start,_size) do { } while (0) +#define dma_cache_wback(_start,_size) do { } while (0) +#define dma_cache_wback_inv(_start,_size) do { } while (0) +#define flush_write_buffers() + +#endif + +#ifdef SLOW_IO_BY_JUMPING +#define __SLOW_DOWN_IO "\njmp 1f\n1:\tjmp 1f\n1:" +#else +#define __SLOW_DOWN_IO "\noutb %%al,$0x80" +#endif + +#ifdef REALLY_SLOW_IO +#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO +#else +#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO +#endif + + +/* + * Talk about misusing macros.. + */ +#define __OUT1(s,x) \ +static inline void out##s(unsigned x value, unsigned short port) { + +#define __OUT2(s,s1,s2) \ +__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1" + +#define __OUT(s,s1,x) \ +__OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); } \ +__OUT1(s##_p,x) __OUT2(s,s1,"w") __FULL_SLOW_DOWN_IO : : "a" (value), "Nd" (port));} + +#define __IN1(s) \ +static inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v; + +#define __IN2(s,s1,s2) \ +__asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0" + +#define __IN(s,s1,i...) \ +__IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \ +__IN1(s##_p) __IN2(s,s1,"w") __FULL_SLOW_DOWN_IO : "=a" (_v) : "Nd" (port) ,##i ); return _v; } + +#define __INS(s) \ +static inline void ins##s(unsigned short port, void * addr, unsigned long count) \ +{ __asm__ __volatile__ ("rep ; ins" #s \ +: "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); } + +#define __OUTS(s) \ +static inline void outs##s(unsigned short port, const void * addr, unsigned long count) \ +{ __asm__ __volatile__ ("rep ; outs" #s \ +: "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); } + +#define RETURN_TYPE unsigned char +__IN(b,"") +#undef RETURN_TYPE +#define RETURN_TYPE unsigned short +__IN(w,"") +#undef RETURN_TYPE +#define RETURN_TYPE unsigned int +__IN(l,"") +#undef RETURN_TYPE + +__OUT(b,"b",char) +__OUT(w,"w",short) +__OUT(l,,int) + +__INS(b) +__INS(w) +__INS(l) + +__OUTS(b) +__OUTS(w) +__OUTS(l) + +#endif diff --git a/xen/include/asm-x86_64/io_apic.h b/xen/include/asm-x86_64/io_apic.h new file mode 100644 index 0000000000..44916209a8 --- /dev/null +++ b/xen/include/asm-x86_64/io_apic.h @@ -0,0 +1,148 @@ +#ifndef __ASM_IO_APIC_H +#define __ASM_IO_APIC_H + +#include <xeno/config.h> +#include <xeno/types.h> + +/* + * Intel IO-APIC support for SMP and UP systems. + * + * Copyright (C) 1997, 1998, 1999, 2000 Ingo Molnar + */ + +#ifdef CONFIG_X86_IO_APIC + +#define APIC_MISMATCH_DEBUG + +#define IO_APIC_BASE(idx) \ + ((volatile int *)(__fix_to_virt(FIX_IO_APIC_BASE_0 + idx) \ + + (mp_ioapics[idx].mpc_apicaddr & ~PAGE_MASK))) + +/* + * The structure of the IO-APIC: + */ +struct IO_APIC_reg_00 { + __u32 __reserved_2 : 24, + ID : 4, + __reserved_1 : 4; +} __attribute__ ((packed)); + +struct IO_APIC_reg_01 { + __u32 version : 8, + __reserved_2 : 7, + PRQ : 1, + entries : 8, + __reserved_1 : 8; +} __attribute__ ((packed)); + +struct IO_APIC_reg_02 { + __u32 __reserved_2 : 24, + arbitration : 4, + __reserved_1 : 4; +} __attribute__ ((packed)); + +/* + * # of IO-APICs and # of IRQ routing registers + */ +extern int nr_ioapics; +extern int nr_ioapic_registers[MAX_IO_APICS]; + +enum ioapic_irq_destination_types { + dest_Fixed = 0, + dest_LowestPrio = 1, + dest_SMI = 2, + dest__reserved_1 = 3, + dest_NMI = 4, + dest_INIT = 5, + dest__reserved_2 = 6, + dest_ExtINT = 7 +}; + +struct IO_APIC_route_entry { + __u32 vector : 8, + delivery_mode : 3, /* 000: FIXED + * 001: lowest prio + * 111: ExtINT + */ + dest_mode : 1, /* 0: physical, 1: logical */ + delivery_status : 1, + polarity : 1, + irr : 1, + trigger : 1, /* 0: edge, 1: level */ + mask : 1, /* 0: enabled, 1: disabled */ + __reserved_2 : 15; + + union { struct { __u32 + __reserved_1 : 24, + physical_dest : 4, + __reserved_2 : 4; + } physical; + + struct { __u32 + __reserved_1 : 24, + logical_dest : 8; + } logical; + } dest; + +} __attribute__ ((packed)); + +/* + * MP-BIOS irq configuration table structures: + */ + +/* I/O APIC entries */ +extern struct mpc_config_ioapic mp_ioapics[MAX_IO_APICS]; + +/* # of MP IRQ source entries */ +extern int mp_irq_entries; + +/* MP IRQ source entries */ +extern struct mpc_config_intsrc *mp_irqs; + +/* non-0 if default (table-less) MP configuration */ +extern int mpc_default_type; + +static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) +{ + *IO_APIC_BASE(apic) = reg; + return *(IO_APIC_BASE(apic)+4); +} + +static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value) +{ + *IO_APIC_BASE(apic) = reg; + *(IO_APIC_BASE(apic)+4) = value; +} + +/* + * Re-write a value: to be used for read-modify-write + * cycles where the read already set up the index register. + */ +static inline void io_apic_modify(unsigned int apic, unsigned int value) +{ + *(IO_APIC_BASE(apic)+4) = value; +} + +/* + * Synchronize the IO-APIC and the CPU by doing + * a dummy read from the IO-APIC + */ +static inline void io_apic_sync(unsigned int apic) +{ + (void) *(IO_APIC_BASE(apic)+4); +} + +/* 1 if "noapic" boot option passed */ +extern int skip_ioapic_setup; + +/* + * If we use the IO-APIC for IRQ routing, disable automatic + * assignment of PCI IRQ's. + */ +#define io_apic_assign_pci_irqs (mp_irq_entries && !skip_ioapic_setup) + +#else /* !CONFIG_X86_IO_APIC */ +#define io_apic_assign_pci_irqs 0 +#endif + +#endif diff --git a/xen/include/asm-x86_64/ioctl.h b/xen/include/asm-x86_64/ioctl.h new file mode 100644 index 0000000000..c75f20ade6 --- /dev/null +++ b/xen/include/asm-x86_64/ioctl.h @@ -0,0 +1,75 @@ +/* $Id: ioctl.h,v 1.5 1993/07/19 21:53:50 root Exp root $ + * + * linux/ioctl.h for Linux by H.H. Bergman. + */ + +#ifndef _ASMI386_IOCTL_H +#define _ASMI386_IOCTL_H + +/* ioctl command encoding: 32 bits total, command in lower 16 bits, + * size of the parameter structure in the lower 14 bits of the + * upper 16 bits. + * Encoding the size of the parameter structure in the ioctl request + * is useful for catching programs compiled with old versions + * and to avoid overwriting user space outside the user buffer area. + * The highest 2 bits are reserved for indicating the ``access mode''. + * NOTE: This limits the max parameter size to 16kB -1 ! + */ + +/* + * The following is for compatibility across the various Linux + * platforms. The i386 ioctl numbering scheme doesn't really enforce + * a type field. De facto, however, the top 8 bits of the lower 16 + * bits are indeed used as a type field, so we might just as well make + * this explicit here. Please be sure to use the decoding macros + * below from now on. + */ +#define _IOC_NRBITS 8 +#define _IOC_TYPEBITS 8 +#define _IOC_SIZEBITS 14 +#define _IOC_DIRBITS 2 + +#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1) +#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1) +#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1) +#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1) + +#define _IOC_NRSHIFT 0 +#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS) +#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS) +#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS) + +/* + * Direction bits. + */ +#define _IOC_NONE 0U +#define _IOC_WRITE 1U +#define _IOC_READ 2U + +#define _IOC(dir,type,nr,size) \ + (((dir) << _IOC_DIRSHIFT) | \ + ((type) << _IOC_TYPESHIFT) | \ + ((nr) << _IOC_NRSHIFT) | \ + ((size) << _IOC_SIZESHIFT)) + +/* used to create numbers */ +#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) +#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)) +#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) +#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size)) + +/* used to decode ioctl numbers.. */ +#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) +#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK) +#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK) +#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) + +/* ...and for the drivers/sound files... */ + +#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT) +#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT) +#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT) +#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT) +#define IOCSIZE_SHIFT (_IOC_SIZESHIFT) + +#endif /* _ASMI386_IOCTL_H */ diff --git a/xen/include/asm-x86_64/irq.h b/xen/include/asm-x86_64/irq.h new file mode 100644 index 0000000000..d88429df4a --- /dev/null +++ b/xen/include/asm-x86_64/irq.h @@ -0,0 +1,204 @@ +#ifndef _ASM_HW_IRQ_H +#define _ASM_HW_IRQ_H + +/* (C) 1992, 1993 Linus Torvalds, (C) 1997 Ingo Molnar */ + +#include <xeno/config.h> +#include <asm/atomic.h> + +#define SA_INTERRUPT 0x20000000 +#define SA_SHIRQ 0x04000000 +#define SA_NOPROFILE 0x02000000 + +#define SA_SAMPLE_RANDOM 0 /* Linux driver compatibility */ + +#define TIMER_IRQ 0 + +extern void disable_irq(unsigned int); +extern void disable_irq_nosync(unsigned int); +extern void enable_irq(unsigned int); + +/* + * IDT vectors usable for external interrupt sources start + * at 0x20: + */ +#define FIRST_EXTERNAL_VECTOR 0x30 + +#define NR_IRQS (256 - FIRST_EXTERNAL_VECTOR) + +#define HYPERVISOR_CALL_VECTOR 0x82 + +/* + * Vectors 0x30-0x3f are used for ISA interrupts. + */ + +/* + * Special IRQ vectors used by the SMP architecture, 0xf0-0xff + * + * some of the following vectors are 'rare', they are merged + * into a single vector (CALL_FUNCTION_VECTOR) to save vector space. + * TLB, reschedule and local APIC vectors are performance-critical. + * + * Vectors 0xf0-0xfa are free (reserved for future Linux use). + */ +#define SPURIOUS_APIC_VECTOR 0xff +#define ERROR_APIC_VECTOR 0xfe +#define INVALIDATE_TLB_VECTOR 0xfd +#define EVENT_CHECK_VECTOR 0xfc +#define CALL_FUNCTION_VECTOR 0xfb +#define KDB_VECTOR 0xfa + +/* + * Local APIC timer IRQ vector is on a different priority level, + * to work around the 'lost local interrupt if more than 2 IRQ + * sources per level' errata. + */ +#define LOCAL_TIMER_VECTOR 0xef + +/* + * First APIC vector available to drivers: (vectors 0x40-0xee) + * we start at 0x41 to spread out vectors evenly between priority + * levels. (0x82 is the syscall vector) + */ +#define FIRST_DEVICE_VECTOR 0x41 +#define FIRST_SYSTEM_VECTOR 0xef + +extern int irq_vector[NR_IRQS]; +#define IO_APIC_VECTOR(irq) irq_vector[irq] + +/* + * Various low-level irq details needed by irq.c, process.c, + * time.c, io_apic.c and smp.c + * + * Interrupt entry/exit code at both C and assembly level + */ + +extern void mask_irq(unsigned int irq); +extern void unmask_irq(unsigned int irq); +extern void disable_8259A_irq(unsigned int irq); +extern void enable_8259A_irq(unsigned int irq); +extern int i8259A_irq_pending(unsigned int irq); +extern void make_8259A_irq(unsigned int irq); +extern void init_8259A(int aeoi); +extern void FASTCALL(send_IPI_self(int vector)); +extern void init_VISWS_APIC_irqs(void); +extern void setup_IO_APIC(void); +extern void disable_IO_APIC(void); +extern void print_IO_APIC(void); +extern int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn); +extern void send_IPI(int dest, int vector); + +extern unsigned long io_apic_irqs; + +extern atomic_t irq_err_count; +extern atomic_t irq_mis_count; + +extern char _stext, _etext; + +#define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs)) + +#define __STR(x) #x +#define STR(x) __STR(x) + +#define SAVE_ALL \ + "cld\n\t" \ + "pushl %gs\n\t" \ + "pushl %fs\n\t" \ + "pushl %es\n\t" \ + "pushl %ds\n\t" \ + "pushl %eax\n\t" \ + "pushl %ebp\n\t" \ + "pushl %edi\n\t" \ + "pushl %esi\n\t" \ + "pushl %edx\n\t" \ + "pushl %ecx\n\t" \ + "pushl %ebx\n\t" \ + "movl $" STR(__HYPERVISOR_DS) ",%edx\n\t" \ + "movl %edx,%ds\n\t" \ + "movl %edx,%es\n\t" \ + "movl %edx,%fs\n\t" \ + "movl %edx,%gs\n\t" + +#define IRQ_NAME2(nr) nr##_interrupt(void) +#define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr) + +/* + * SMP has a few special interrupts for IPI messages + */ + + /* there is a second layer of macro just to get the symbolic + name for the vector evaluated. This change is for RTLinux */ +#define BUILD_SMP_INTERRUPT(x,v) XBUILD_SMP_INTERRUPT(x,v) +#define XBUILD_SMP_INTERRUPT(x,v)\ +asmlinkage void x(void); \ +asmlinkage void call_##x(void); \ +__asm__( \ +"\n"__ALIGN_STR"\n" \ +SYMBOL_NAME_STR(x) ":\n\t" \ + "pushl $"#v"-256\n\t" \ + SAVE_ALL \ + SYMBOL_NAME_STR(call_##x)":\n\t" \ + "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \ + "jmp ret_from_intr\n"); + +#define BUILD_SMP_TIMER_INTERRUPT(x,v) XBUILD_SMP_TIMER_INTERRUPT(x,v) +#define XBUILD_SMP_TIMER_INTERRUPT(x,v) \ +asmlinkage void x(struct pt_regs * regs); \ +asmlinkage void call_##x(void); \ +__asm__( \ +"\n"__ALIGN_STR"\n" \ +SYMBOL_NAME_STR(x) ":\n\t" \ + "pushl $"#v"-256\n\t" \ + SAVE_ALL \ + "movl %esp,%eax\n\t" \ + "pushl %eax\n\t" \ + SYMBOL_NAME_STR(call_##x)":\n\t" \ + "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \ + "addl $4,%esp\n\t" \ + "jmp ret_from_intr\n"); + +#define BUILD_COMMON_IRQ() \ +asmlinkage void call_do_IRQ(void); \ +__asm__( \ + "\n" __ALIGN_STR"\n" \ + "common_interrupt:\n\t" \ + SAVE_ALL \ + SYMBOL_NAME_STR(call_do_IRQ)":\n\t" \ + "call " SYMBOL_NAME_STR(do_IRQ) "\n\t" \ + "jmp ret_from_intr\n"); + +/* + * subtle. orig_eax is used by the signal code to distinct between + * system calls and interrupted 'random user-space'. Thus we have + * to put a negative value into orig_eax here. (the problem is that + * both system calls and IRQs want to have small integer numbers in + * orig_eax, and the syscall code has won the optimization conflict ;) + * + * Subtle as a pigs ear. VY + */ + +#define BUILD_IRQ(nr) \ +asmlinkage void IRQ_NAME(nr); \ +__asm__( \ +"\n"__ALIGN_STR"\n" \ +SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \ + "pushl $"#nr"-256\n\t" \ + "jmp common_interrupt"); + +extern unsigned long prof_cpu_mask; +extern unsigned int * prof_buffer; +extern unsigned long prof_len; +extern unsigned long prof_shift; + +#include <xeno/irq.h> + +#ifdef CONFIG_SMP /*more of this file should probably be ifdefed SMP */ +static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) { + if (IO_APIC_IRQ(i)) + send_IPI_self(IO_APIC_VECTOR(i)); +} +#else +static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {} +#endif + +#endif /* _ASM_HW_IRQ_H */ diff --git a/xen/include/asm-x86_64/ldt.h b/xen/include/asm-x86_64/ldt.h new file mode 100644 index 0000000000..7a345ceb40 --- /dev/null +++ b/xen/include/asm-x86_64/ldt.h @@ -0,0 +1,39 @@ +#ifndef __ARCH_LDT_H +#define __ARCH_LDT_H + +#ifndef __ASSEMBLY__ + +static inline void load_LDT(struct task_struct *p) +{ + unsigned long ents; + + if ( (ents = p->mm.ldt_ents) == 0 ) + { + __asm__ __volatile__ ( "lldt %%rax" : : "a" (0) ); + } + else + { + unsigned int cpu; + struct ldttss_desc *desc; + + cpu = smp_processor_id(); + desc = (struct desc_struct *)((char *)GET_GDT_ADDRESS(p) + __CPU_DESC_INDEX(cpu, ldt)); + desc->limit0 = ents*8-1; + desc->base0 = LDT_VIRT_START&0xffff; + desc->base1 = (LDT_VIRT_START&0xff0000)>>16; + desc->type = DESC_LDT; + desc->dpl = 0; + desc->p = 1; + desc->limit = 0; + desc->zero0 = 0; + desc->g = 0; + desc->base2 = (LDT_VIRST_START&0xff000000)>>24; + desc->base3 = LDT_VIRT_START>>32; + desc->zero1 = 0; + __load_LDT(cpu); + } +} + +#endif /* !__ASSEMBLY__ */ + +#endif diff --git a/xen/include/asm-x86_64/mc146818rtc.h b/xen/include/asm-x86_64/mc146818rtc.h new file mode 100644 index 0000000000..03a4efa9e8 --- /dev/null +++ b/xen/include/asm-x86_64/mc146818rtc.h @@ -0,0 +1,113 @@ +/* + * Machine dependent access functions for RTC registers. + */ +#ifndef _ASM_MC146818RTC_H +#define _ASM_MC146818RTC_H + +#include <asm/io.h> +#include <xeno/spinlock.h> + +extern spinlock_t rtc_lock; /* serialize CMOS RAM access */ + +/********************************************************************** + * register summary + **********************************************************************/ +#define RTC_SECONDS 0 +#define RTC_SECONDS_ALARM 1 +#define RTC_MINUTES 2 +#define RTC_MINUTES_ALARM 3 +#define RTC_HOURS 4 +#define RTC_HOURS_ALARM 5 +/* RTC_*_alarm is always true if 2 MSBs are set */ +# define RTC_ALARM_DONT_CARE 0xC0 + +#define RTC_DAY_OF_WEEK 6 +#define RTC_DAY_OF_MONTH 7 +#define RTC_MONTH 8 +#define RTC_YEAR 9 + +/* control registers - Moto names + */ +#define RTC_REG_A 10 +#define RTC_REG_B 11 +#define RTC_REG_C 12 +#define RTC_REG_D 13 + +/********************************************************************** + * register details + **********************************************************************/ +#define RTC_FREQ_SELECT RTC_REG_A + +/* update-in-progress - set to "1" 244 microsecs before RTC goes off the bus, + * reset after update (may take 1.984ms @ 32768Hz RefClock) is complete, + * totalling to a max high interval of 2.228 ms. + */ +# define RTC_UIP 0x80 +# define RTC_DIV_CTL 0x70 + /* divider control: refclock values 4.194 / 1.049 MHz / 32.768 kHz */ +# define RTC_REF_CLCK_4MHZ 0x00 +# define RTC_REF_CLCK_1MHZ 0x10 +# define RTC_REF_CLCK_32KHZ 0x20 + /* 2 values for divider stage reset, others for "testing purposes only" */ +# define RTC_DIV_RESET1 0x60 +# define RTC_DIV_RESET2 0x70 + /* Periodic intr. / Square wave rate select. 0=none, 1=32.8kHz,... 15=2Hz */ +# define RTC_RATE_SELECT 0x0F + +/**********************************************************************/ +#define RTC_CONTROL RTC_REG_B +# define RTC_SET 0x80 /* disable updates for clock setting */ +# define RTC_PIE 0x40 /* periodic interrupt enable */ +# define RTC_AIE 0x20 /* alarm interrupt enable */ +# define RTC_UIE 0x10 /* update-finished interrupt enable */ +# define RTC_SQWE 0x08 /* enable square-wave output */ +# define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */ +# define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */ +# define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */ + +/**********************************************************************/ +#define RTC_INTR_FLAGS RTC_REG_C +/* caution - cleared by read */ +# define RTC_IRQF 0x80 /* any of the following 3 is active */ +# define RTC_PF 0x40 +# define RTC_AF 0x20 +# define RTC_UF 0x10 + +/**********************************************************************/ +#define RTC_VALID RTC_REG_D +# define RTC_VRT 0x80 /* valid RAM and time */ +/**********************************************************************/ + +/* example: !(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) + * determines if the following two #defines are needed + */ +#ifndef BCD_TO_BIN +#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10) +#endif + +#ifndef BIN_TO_BCD +#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10) +#endif + + +#ifndef RTC_PORT +#define RTC_PORT(x) (0x70 + (x)) +#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */ +#endif + +/* + * The yet supported machines all access the RTC index register via + * an ISA port access but the way to access the date register differs ... + */ +#define CMOS_READ(addr) ({ \ +outb_p((addr),RTC_PORT(0)); \ +inb_p(RTC_PORT(1)); \ +}) +#define CMOS_WRITE(val, addr) ({ \ +outb_p((addr),RTC_PORT(0)); \ +outb_p((val),RTC_PORT(1)); \ +}) + +#define RTC_IRQ 8 + +#endif /* _ASM_MC146818RTC_H */ diff --git a/xen/include/asm-x86_64/mpspec.h b/xen/include/asm-x86_64/mpspec.h new file mode 100644 index 0000000000..7ca70f41a8 --- /dev/null +++ b/xen/include/asm-x86_64/mpspec.h @@ -0,0 +1,217 @@ +#ifndef __ASM_MPSPEC_H +#define __ASM_MPSPEC_H + + +/* + * Structure definitions for SMP machines following the + * Intel Multiprocessing Specification 1.1 and 1.4. + */ + +/* + * This tag identifies where the SMP configuration + * information is. + */ + +#define SMP_MAGIC_IDENT (('_'<<24)|('P'<<16)|('M'<<8)|'_') + +/* + * a maximum of 16 APICs with the current APIC ID architecture. + * xAPICs can have up to 256. SAPICs have 16 ID bits. + */ +#ifdef CONFIG_X86_CLUSTERED_APIC +#define MAX_APICS 256 +#else +#define MAX_APICS 16 +#endif + +#define MAX_MPC_ENTRY 1024 + +struct intel_mp_floating +{ + char mpf_signature[4]; /* "_MP_" */ + unsigned long mpf_physptr; /* Configuration table address */ + unsigned char mpf_length; /* Our length (paragraphs) */ + unsigned char mpf_specification;/* Specification version */ + unsigned char mpf_checksum; /* Checksum (makes sum 0) */ + unsigned char mpf_feature1; /* Standard or configuration ? */ + unsigned char mpf_feature2; /* Bit7 set for IMCR|PIC */ + unsigned char mpf_feature3; /* Unused (0) */ + unsigned char mpf_feature4; /* Unused (0) */ + unsigned char mpf_feature5; /* Unused (0) */ +}; + +struct mp_config_table +{ + char mpc_signature[4]; +#define MPC_SIGNATURE "PCMP" + unsigned short mpc_length; /* Size of table */ + char mpc_spec; /* 0x01 */ + char mpc_checksum; + char mpc_oem[8]; + char mpc_productid[12]; + unsigned long mpc_oemptr; /* 0 if not present */ + unsigned short mpc_oemsize; /* 0 if not present */ + unsigned short mpc_oemcount; + unsigned long mpc_lapic; /* APIC address */ + unsigned long reserved; +}; + +/* Followed by entries */ + +#define MP_PROCESSOR 0 +#define MP_BUS 1 +#define MP_IOAPIC 2 +#define MP_INTSRC 3 +#define MP_LINTSRC 4 +#define MP_TRANSLATION 192 /* Used by IBM NUMA-Q to describe node locality */ + +struct mpc_config_processor +{ + unsigned char mpc_type; + unsigned char mpc_apicid; /* Local APIC number */ + unsigned char mpc_apicver; /* Its versions */ + unsigned char mpc_cpuflag; +#define CPU_ENABLED 1 /* Processor is available */ +#define CPU_BOOTPROCESSOR 2 /* Processor is the BP */ + unsigned long mpc_cpufeature; +#define CPU_STEPPING_MASK 0x0F +#define CPU_MODEL_MASK 0xF0 +#define CPU_FAMILY_MASK 0xF00 + unsigned long mpc_featureflag; /* CPUID feature value */ + unsigned long mpc_reserved[2]; +}; + +struct mpc_config_bus +{ + unsigned char mpc_type; + unsigned char mpc_busid; + unsigned char mpc_bustype[6] __attribute((packed)); +}; + +/* List of Bus Type string values, Intel MP Spec. */ +#define BUSTYPE_EISA "EISA" +#define BUSTYPE_ISA "ISA" +#define BUSTYPE_INTERN "INTERN" /* Internal BUS */ +#define BUSTYPE_MCA "MCA" +#define BUSTYPE_VL "VL" /* Local bus */ +#define BUSTYPE_PCI "PCI" +#define BUSTYPE_PCMCIA "PCMCIA" +#define BUSTYPE_CBUS "CBUS" +#define BUSTYPE_CBUSII "CBUSII" +#define BUSTYPE_FUTURE "FUTURE" +#define BUSTYPE_MBI "MBI" +#define BUSTYPE_MBII "MBII" +#define BUSTYPE_MPI "MPI" +#define BUSTYPE_MPSA "MPSA" +#define BUSTYPE_NUBUS "NUBUS" +#define BUSTYPE_TC "TC" +#define BUSTYPE_VME "VME" +#define BUSTYPE_XPRESS "XPRESS" + +struct mpc_config_ioapic +{ + unsigned char mpc_type; + unsigned char mpc_apicid; + unsigned char mpc_apicver; + unsigned char mpc_flags; +#define MPC_APIC_USABLE 0x01 + unsigned long mpc_apicaddr; +}; + +struct mpc_config_intsrc +{ + unsigned char mpc_type; + unsigned char mpc_irqtype; + unsigned short mpc_irqflag; + unsigned char mpc_srcbus; + unsigned char mpc_srcbusirq; + unsigned char mpc_dstapic; + unsigned char mpc_dstirq; +}; + +enum mp_irq_source_types { + mp_INT = 0, + mp_NMI = 1, + mp_SMI = 2, + mp_ExtINT = 3 +}; + +#define MP_IRQDIR_DEFAULT 0 +#define MP_IRQDIR_HIGH 1 +#define MP_IRQDIR_LOW 3 + + +struct mpc_config_lintsrc +{ + unsigned char mpc_type; + unsigned char mpc_irqtype; + unsigned short mpc_irqflag; + unsigned char mpc_srcbusid; + unsigned char mpc_srcbusirq; + unsigned char mpc_destapic; +#define MP_APIC_ALL 0xFF + unsigned char mpc_destapiclint; +}; + +struct mp_config_oemtable +{ + char oem_signature[4]; +#define MPC_OEM_SIGNATURE "_OEM" + unsigned short oem_length; /* Size of table */ + char oem_rev; /* 0x01 */ + char oem_checksum; + char mpc_oem[8]; +}; + +struct mpc_config_translation +{ + unsigned char mpc_type; + unsigned char trans_len; + unsigned char trans_type; + unsigned char trans_quad; + unsigned char trans_global; + unsigned char trans_local; + unsigned short trans_reserved; +}; + +/* + * Default configurations + * + * 1 2 CPU ISA 82489DX + * 2 2 CPU EISA 82489DX neither IRQ 0 timer nor IRQ 13 DMA chaining + * 3 2 CPU EISA 82489DX + * 4 2 CPU MCA 82489DX + * 5 2 CPU ISA+PCI + * 6 2 CPU EISA+PCI + * 7 2 CPU MCA+PCI + */ + +#ifdef CONFIG_MULTIQUAD +#define MAX_IRQ_SOURCES 512 +#else /* !CONFIG_MULTIQUAD */ +#define MAX_IRQ_SOURCES 256 +#endif /* CONFIG_MULTIQUAD */ + +#define MAX_MP_BUSSES 32 +enum mp_bustype { + MP_BUS_ISA = 1, + MP_BUS_EISA, + MP_BUS_PCI, + MP_BUS_MCA +}; +extern int *mp_bus_id_to_type; +extern int *mp_bus_id_to_node; +extern int *mp_bus_id_to_local; +extern int *mp_bus_id_to_pci_bus; +extern int quad_local_to_mp_bus_id [NR_CPUS/4][4]; + +extern unsigned int boot_cpu_physical_apicid; +extern int smp_found_config; +extern void find_smp_config (void); +extern void get_smp_config (void); +extern int apic_version [MAX_APICS]; +extern int mp_current_pci_id; +extern unsigned long mp_lapic_addr; + +#endif + diff --git a/xen/include/asm-x86_64/msr.h b/xen/include/asm-x86_64/msr.h new file mode 100644 index 0000000000..45ec765e6e --- /dev/null +++ b/xen/include/asm-x86_64/msr.h @@ -0,0 +1,121 @@ +#ifndef __ASM_MSR_H +#define __ASM_MSR_H + +/* + * Access to machine-specific registers (available on 586 and better only) + * Note: the rd* operations modify the parameters directly (without using + * pointer indirection), this allows gcc to optimize better + */ + +#define rdmsr(msr,val1,val2) \ + __asm__ __volatile__("rdmsr" \ + : "=a" (val1), "=d" (val2) \ + : "c" (msr)) + +#define wrmsr(msr,val1,val2) \ + __asm__ __volatile__("wrmsr" \ + : /* no outputs */ \ + : "c" (msr), "a" (val1), "d" (val2)) + +#define rdtsc(low,high) \ + __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high)) + +#define rdtscl(low) \ + __asm__ __volatile__("rdtsc" : "=a" (low) : : "edx") + +#define rdtscll(val) \ + __asm__ __volatile__("rdtsc" : "=A" (val)) + +#define write_tsc(val1,val2) wrmsr(0x10, val1, val2) + +#define rdpmc(counter,low,high) \ + __asm__ __volatile__("rdpmc" \ + : "=a" (low), "=d" (high) \ + : "c" (counter)) + +/* symbolic names for some interesting MSRs */ +/* Intel defined MSRs. */ +#define MSR_IA32_P5_MC_ADDR 0 +#define MSR_IA32_P5_MC_TYPE 1 +#define MSR_IA32_PLATFORM_ID 0x17 +#define MSR_IA32_EBL_CR_POWERON 0x2a + +#define MSR_IA32_APICBASE 0x1b +#define MSR_IA32_APICBASE_BSP (1<<8) +#define MSR_IA32_APICBASE_ENABLE (1<<11) +#define MSR_IA32_APICBASE_BASE (0xfffff<<12) + +#define MSR_IA32_UCODE_WRITE 0x79 +#define MSR_IA32_UCODE_REV 0x8b + +#define MSR_IA32_BBL_CR_CTL 0x119 + +#define MSR_IA32_MCG_CAP 0x179 +#define MSR_IA32_MCG_STATUS 0x17a +#define MSR_IA32_MCG_CTL 0x17b + +#define MSR_IA32_THERM_CONTROL 0x19a +#define MSR_IA32_THERM_INTERRUPT 0x19b +#define MSR_IA32_THERM_STATUS 0x19c +#define MSR_IA32_MISC_ENABLE 0x1a0 + +#define MSR_IA32_DEBUGCTLMSR 0x1d9 +#define MSR_IA32_LASTBRANCHFROMIP 0x1db +#define MSR_IA32_LASTBRANCHTOIP 0x1dc +#define MSR_IA32_LASTINTFROMIP 0x1dd +#define MSR_IA32_LASTINTTOIP 0x1de + +#define MSR_IA32_MC0_CTL 0x400 +#define MSR_IA32_MC0_STATUS 0x401 +#define MSR_IA32_MC0_ADDR 0x402 +#define MSR_IA32_MC0_MISC 0x403 + +#define MSR_P6_PERFCTR0 0xc1 +#define MSR_P6_PERFCTR1 0xc2 +#define MSR_P6_EVNTSEL0 0x186 +#define MSR_P6_EVNTSEL1 0x187 + +/* AMD Defined MSRs */ +#define MSR_K6_EFER 0xC0000080 +#define MSR_K6_STAR 0xC0000081 +#define MSR_K6_WHCR 0xC0000082 +#define MSR_K6_UWCCR 0xC0000085 +#define MSR_K6_EPMR 0xC0000086 +#define MSR_K6_PSOR 0xC0000087 +#define MSR_K6_PFIR 0xC0000088 + +#define MSR_K7_EVNTSEL0 0xC0010000 +#define MSR_K7_PERFCTR0 0xC0010004 +#define MSR_K7_HWCR 0xC0010015 +#define MSR_K7_CLK_CTL 0xC001001b +#define MSR_K7_FID_VID_CTL 0xC0010041 +#define MSR_K7_VID_STATUS 0xC0010042 + +/* Centaur-Hauls/IDT defined MSRs. */ +#define MSR_IDT_FCR1 0x107 +#define MSR_IDT_FCR2 0x108 +#define MSR_IDT_FCR3 0x109 +#define MSR_IDT_FCR4 0x10a + +#define MSR_IDT_MCR0 0x110 +#define MSR_IDT_MCR1 0x111 +#define MSR_IDT_MCR2 0x112 +#define MSR_IDT_MCR3 0x113 +#define MSR_IDT_MCR4 0x114 +#define MSR_IDT_MCR5 0x115 +#define MSR_IDT_MCR6 0x116 +#define MSR_IDT_MCR7 0x117 +#define MSR_IDT_MCR_CTRL 0x120 + +/* VIA Cyrix defined MSRs*/ +#define MSR_VIA_FCR 0x1107 +#define MSR_VIA_LONGHAUL 0x110a +#define MSR_VIA_BCR2 0x1147 + +/* Transmeta defined MSRs */ +#define MSR_TMTA_LONGRUN_CTRL 0x80868010 +#define MSR_TMTA_LONGRUN_FLAGS 0x80868011 +#define MSR_TMTA_LRTI_READOUT 0x80868018 +#define MSR_TMTA_LRTI_VOLT_MHZ 0x8086801a + +#endif /* __ASM_MSR_H */ diff --git a/xen/include/asm-x86_64/page.h b/xen/include/asm-x86_64/page.h new file mode 100644 index 0000000000..a4339d64dd --- /dev/null +++ b/xen/include/asm-x86_64/page.h @@ -0,0 +1,179 @@ +#ifndef _I386_PAGE_H +#define _I386_PAGE_H + +#define BUG() do { \ + printk("BUG at %s:%d\n", __FILE__, __LINE__); \ + __asm__ __volatile__("ud2"); \ +} while (0) + +#define L1_PAGETABLE_SHIFT 12 +#define L2_PAGETABLE_SHIFT 22 + +#define ENTRIES_PER_L1_PAGETABLE 1024 +#define ENTRIES_PER_L2_PAGETABLE 1024 + +#define PAGE_SHIFT L1_PAGETABLE_SHIFT +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#define clear_page(_p) memset((void *)(_p), 0, PAGE_SIZE) +#define copy_page(_t,_f) memcpy((void *)(_t), (void *)(_f), PAGE_SIZE) + +#ifndef __ASSEMBLY__ +#include <xeno/config.h> +typedef struct { unsigned long l1_lo; } l1_pgentry_t; +typedef struct { unsigned long l2_lo; } l2_pgentry_t; +typedef l1_pgentry_t *l1_pagetable_t; +typedef l2_pgentry_t *l2_pagetable_t; +typedef struct { unsigned long pt_lo; } pagetable_t; +#endif /* !__ASSEMBLY__ */ + +/* Strip type from a table entry. */ +#define l1_pgentry_val(_x) ((_x).l1_lo) +#define l2_pgentry_val(_x) ((_x).l2_lo) +#define pagetable_val(_x) ((_x).pt_lo) + +#define alloc_l1_pagetable() ((l1_pgentry_t *)get_free_page(GFP_KERNEL)) +#define alloc_l2_pagetable() ((l2_pgentry_t *)get_free_page(GFP_KERNEL)) + +/* Add type to a table entry. */ +#define mk_l1_pgentry(_x) ( (l1_pgentry_t) { (_x) } ) +#define mk_l2_pgentry(_x) ( (l2_pgentry_t) { (_x) } ) +#define mk_pagetable(_x) ( (pagetable_t) { (_x) } ) + +/* Turn a typed table entry into a page index. */ +#define l1_pgentry_to_pagenr(_x) (l1_pgentry_val(_x) >> PAGE_SHIFT) +#define l2_pgentry_to_pagenr(_x) (l2_pgentry_val(_x) >> PAGE_SHIFT) + +/* Turn a typed table entry into a physical address. */ +#define l1_pgentry_to_phys(_x) (l1_pgentry_val(_x) & PAGE_MASK) +#define l2_pgentry_to_phys(_x) (l2_pgentry_val(_x) & PAGE_MASK) + +/* Dereference a typed level-2 entry to yield a typed level-1 table. */ +#define l2_pgentry_to_l1(_x) \ + ((l1_pgentry_t *)__va(l2_pgentry_val(_x) & PAGE_MASK)) + +/* Given a virtual address, get an entry offset into a page table. */ +#define l1_table_offset(_a) \ + (((_a) >> L1_PAGETABLE_SHIFT) & (ENTRIES_PER_L1_PAGETABLE - 1)) +#define l2_table_offset(_a) \ + ((_a) >> L2_PAGETABLE_SHIFT) + +/* Hypervisor table entries use zero to sugnify 'empty'. */ +#define l1_pgentry_empty(_x) (!l1_pgentry_val(_x)) +#define l2_pgentry_empty(_x) (!l2_pgentry_val(_x)) + +#define __PAGE_OFFSET (0xFC400000) +#define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET) +#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) +#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) +#define page_address(_p) (__va(((_p) - frame_table) << PAGE_SHIFT)) +#define virt_to_page(kaddr) (frame_table + (__pa(kaddr) >> PAGE_SHIFT)) +#define VALID_PAGE(page) ((page - frame_table) < max_mapnr) + +/* + * NB. We don't currently track I/O holes in the physical RAM space. + * For now we guess that I/O devices will be mapped in the first 1MB + * (e.g., VGA buffers) or beyond the end of physical RAM. + */ +#define pfn_is_ram(_pfn) (((_pfn) > 0x100) && ((_pfn) < max_page)) + +/* High table entries are reserved by the hypervisor. */ +#define DOMAIN_ENTRIES_PER_L2_PAGETABLE \ + (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) +#define HYPERVISOR_ENTRIES_PER_L2_PAGETABLE \ + (ENTRIES_PER_L2_PAGETABLE - DOMAIN_ENTRIES_PER_L2_PAGETABLE) + +#ifndef __ASSEMBLY__ +#include <asm/processor.h> +#include <asm/fixmap.h> +#include <asm/bitops.h> +#include <asm/flushtlb.h> + +#define linear_pg_table ((l1_pgentry_t *)LINEAR_PT_VIRT_START) + +extern l2_pgentry_t idle_pg_table[ENTRIES_PER_L2_PAGETABLE]; +extern void paging_init(void); + +#define __flush_tlb() flush_tlb_counted() + +/* Flush global pages as well. */ + +#define __pge_off() \ + do { \ + __asm__ __volatile__( \ + "movl %0, %%cr4; # turn off PGE " \ + :: "r" (mmu_cr4_features & ~X86_CR4_PGE)); \ + } while (0) + +#define __pge_on() \ + do { \ + __asm__ __volatile__( \ + "movl %0, %%cr4; # turn off PGE " \ + :: "r" (mmu_cr4_features)); \ + } while (0) + + +#define __flush_tlb_pge() \ + do { \ + __pge_off(); \ + flush_tlb_counted(); \ + __pge_on(); \ + } while (0) + +#define __flush_tlb_one(__addr) \ +__asm__ __volatile__("invlpg %0": :"m" (*(char *) (__addr))) + +#endif /* !__ASSEMBLY__ */ + + +#define _PAGE_PRESENT 0x001 +#define _PAGE_RW 0x002 +#define _PAGE_USER 0x004 +#define _PAGE_PWT 0x008 +#define _PAGE_PCD 0x010 +#define _PAGE_ACCESSED 0x020 +#define _PAGE_DIRTY 0x040 +#define _PAGE_PAT 0x080 +#define _PAGE_PSE 0x080 +#define _PAGE_GLOBAL 0x100 + +#define __PAGE_HYPERVISOR \ + (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED) +#define __PAGE_HYPERVISOR_NOCACHE \ + (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_PCD | _PAGE_ACCESSED) +#define __PAGE_HYPERVISOR_RO \ + (_PAGE_PRESENT | _PAGE_DIRTY | _PAGE_ACCESSED) + +#define MAKE_GLOBAL(_x) ((_x) | _PAGE_GLOBAL) + +#define PAGE_HYPERVISOR MAKE_GLOBAL(__PAGE_HYPERVISOR) +#define PAGE_HYPERVISOR_RO MAKE_GLOBAL(__PAGE_HYPERVISOR_RO) +#define PAGE_HYPERVISOR_NOCACHE MAKE_GLOBAL(__PAGE_HYPERVISOR_NOCACHE) + +#define mk_l2_writeable(_p) \ + (*(_p) = mk_l2_pgentry(l2_pgentry_val(*(_p)) | _PAGE_RW)) +#define mk_l2_readonly(_p) \ + (*(_p) = mk_l2_pgentry(l2_pgentry_val(*(_p)) & ~_PAGE_RW)) +#define mk_l1_writeable(_p) \ + (*(_p) = mk_l1_pgentry(l1_pgentry_val(*(_p)) | _PAGE_RW)) +#define mk_l1_readonly(_p) \ + (*(_p) = mk_l1_pgentry(l1_pgentry_val(*(_p)) & ~_PAGE_RW)) + + +#ifndef __ASSEMBLY__ +static __inline__ int get_order(unsigned long size) +{ + int order; + + size = (size-1) >> (PAGE_SHIFT-1); + order = -1; + do { + size >>= 1; + order++; + } while (size); + return order; +} +#endif + +#endif /* _I386_PAGE_H */ diff --git a/xen/include/asm-x86_64/param.h b/xen/include/asm-x86_64/param.h new file mode 100644 index 0000000000..1b10bf49fe --- /dev/null +++ b/xen/include/asm-x86_64/param.h @@ -0,0 +1,24 @@ +#ifndef _ASMi386_PARAM_H +#define _ASMi386_PARAM_H + +#ifndef HZ +#define HZ 100 +#endif + +#define EXEC_PAGESIZE 4096 + +#ifndef NGROUPS +#define NGROUPS 32 +#endif + +#ifndef NOGROUP +#define NOGROUP (-1) +#endif + +#define MAXHOSTNAMELEN 64 /* max length of hostname */ + +#ifdef __KERNEL__ +# define CLOCKS_PER_SEC 100 /* frequency at which times() counts */ +#endif + +#endif diff --git a/xen/include/asm-x86_64/pci.h b/xen/include/asm-x86_64/pci.h new file mode 100644 index 0000000000..a38bef4986 --- /dev/null +++ b/xen/include/asm-x86_64/pci.h @@ -0,0 +1,286 @@ +#ifndef __i386_PCI_H +#define __i386_PCI_H + +#include <linux/config.h> + +#ifdef __KERNEL__ + +/* Can be used to override the logic in pci_scan_bus for skipping + already-configured bus numbers - to be used for buggy BIOSes + or architectures with incomplete PCI setup by the loader */ + +#ifdef CONFIG_PCI +extern unsigned int pcibios_assign_all_busses(void); +#else +#define pcibios_assign_all_busses() 0 +#endif + +extern unsigned long pci_mem_start; +#define PCIBIOS_MIN_IO 0x1000 +#define PCIBIOS_MIN_MEM (pci_mem_start) + +void pcibios_set_master(struct pci_dev *dev); +void pcibios_penalize_isa_irq(int irq); +struct irq_routing_table *pcibios_get_irq_routing_table(void); +int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq); + +/* Dynamic DMA mapping stuff. + * i386 has everything mapped statically. + */ + +#include <linux/types.h> +#include <linux/slab.h> +#include <asm/scatterlist.h> +/*#include <linux/string.h>*/ +#include <asm/io.h> + +struct pci_dev; + +/* The PCI address space does equal the physical memory + * address space. The networking and block device layers use + * this boolean for bounce buffer decisions. + */ +#define PCI_DMA_BUS_IS_PHYS (1) + +/* Allocate and map kernel buffer using consistent mode DMA for a device. + * hwdev should be valid struct pci_dev pointer for PCI devices, + * NULL for PCI-like buses (ISA, EISA). + * Returns non-NULL cpu-view pointer to the buffer if successful and + * sets *dma_addrp to the pci side dma address as well, else *dma_addrp + * is undefined. + */ +extern void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, + dma_addr_t *dma_handle); + +/* Free and unmap a consistent DMA buffer. + * cpu_addr is what was returned from pci_alloc_consistent, + * size must be the same as what as passed into pci_alloc_consistent, + * and likewise dma_addr must be the same as what *dma_addrp was set to. + * + * References to the memory and mappings associated with cpu_addr/dma_addr + * past this call are illegal. + */ +extern void pci_free_consistent(struct pci_dev *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle); + +/* Map a single buffer of the indicated size for DMA in streaming mode. + * The 32-bit bus address to use is returned. + * + * Once the device is given the dma address, the device owns this memory + * until either pci_unmap_single or pci_dma_sync_single is performed. + */ +static inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, + size_t size, int direction) +{ + if (direction == PCI_DMA_NONE) + out_of_line_bug(); + flush_write_buffers(); + return virt_to_bus(ptr); +} + +/* Unmap a single streaming mode DMA translation. The dma_addr and size + * must match what was provided for in a previous pci_map_single call. All + * other usages are undefined. + * + * After this call, reads by the cpu to the buffer are guarenteed to see + * whatever the device wrote there. + */ +static inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, + size_t size, int direction) +{ + if (direction == PCI_DMA_NONE) + out_of_line_bug(); + /* Nothing to do */ +} + +/* + * pci_{map,unmap}_single_page maps a kernel page to a dma_addr_t. identical + * to pci_map_single, but takes a struct pfn_info instead of a virtual address + */ +static inline dma_addr_t pci_map_page(struct pci_dev *hwdev, struct pfn_info *page, + unsigned long offset, size_t size, int direction) +{ + if (direction == PCI_DMA_NONE) + out_of_line_bug(); + + return (dma_addr_t)(page - frame_table) * PAGE_SIZE + offset; +} + +static inline void pci_unmap_page(struct pci_dev *hwdev, dma_addr_t dma_address, + size_t size, int direction) +{ + if (direction == PCI_DMA_NONE) + out_of_line_bug(); + /* Nothing to do */ +} + +/* pci_unmap_{page,single} is a nop so... */ +#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) +#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) +#define pci_unmap_addr(PTR, ADDR_NAME) (0) +#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0) +#define pci_unmap_len(PTR, LEN_NAME) (0) +#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0) + +/* Map a set of buffers described by scatterlist in streaming + * mode for DMA. This is the scather-gather version of the + * above pci_map_single interface. Here the scatter gather list + * elements are each tagged with the appropriate dma address + * and length. They are obtained via sg_dma_{address,length}(SG). + * + * NOTE: An implementation may be able to use a smaller number of + * DMA address/length pairs than there are SG table elements. + * (for example via virtual mapping capabilities) + * The routine returns the number of addr/length pairs actually + * used, at most nents. + * + * Device ownership issues as mentioned above for pci_map_single are + * the same here. + */ +static inline int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, + int nents, int direction) +{ + int i; + + if (direction == PCI_DMA_NONE) + out_of_line_bug(); + + /* + * temporary 2.4 hack + */ + for (i = 0; i < nents; i++ ) { + if (sg[i].address && sg[i].page) + out_of_line_bug(); +#if 0 + /* Invalid check, since address==0 is valid. */ + else if (!sg[i].address && !sg[i].page) + out_of_line_bug(); +#endif + + /* XXX Switched round, since address==0 is valid. */ + if (sg[i].page) + sg[i].dma_address = page_to_bus(sg[i].page) + sg[i].offset; + else + sg[i].dma_address = virt_to_bus(sg[i].address); + } + + flush_write_buffers(); + return nents; +} + +/* Unmap a set of streaming mode DMA translations. + * Again, cpu read rules concerning calls here are the same as for + * pci_unmap_single() above. + */ +static inline void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, + int nents, int direction) +{ + if (direction == PCI_DMA_NONE) + out_of_line_bug(); + /* Nothing to do */ +} + +/* Make physical memory consistent for a single + * streaming mode DMA translation after a transfer. + * + * If you perform a pci_map_single() but wish to interrogate the + * buffer using the cpu, yet do not wish to teardown the PCI dma + * mapping, you must call this function before doing so. At the + * next point you give the PCI dma address back to the card, the + * device again owns the buffer. + */ +static inline void pci_dma_sync_single(struct pci_dev *hwdev, + dma_addr_t dma_handle, + size_t size, int direction) +{ + if (direction == PCI_DMA_NONE) + out_of_line_bug(); + flush_write_buffers(); +} + +/* Make physical memory consistent for a set of streaming + * mode DMA translations after a transfer. + * + * The same as pci_dma_sync_single but for a scatter-gather list, + * same rules and usage. + */ +static inline void pci_dma_sync_sg(struct pci_dev *hwdev, + struct scatterlist *sg, + int nelems, int direction) +{ + if (direction == PCI_DMA_NONE) + out_of_line_bug(); + flush_write_buffers(); +} + +/* Return whether the given PCI device DMA address mask can + * be supported properly. For example, if your device can + * only drive the low 24-bits during PCI bus mastering, then + * you would pass 0x00ffffff as the mask to this function. + */ +static inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask) +{ + /* + * we fall back to GFP_DMA when the mask isn't all 1s, + * so we can't guarantee allocations that must be + * within a tighter range than GFP_DMA.. + */ + if(mask < 0x00ffffff) + return 0; + + return 1; +} + +/* This is always fine. */ +#define pci_dac_dma_supported(pci_dev, mask) (1) + +static __inline__ dma64_addr_t +pci_dac_page_to_dma(struct pci_dev *pdev, struct pfn_info *page, unsigned long offset, int direction) +{ + return ((dma64_addr_t) page_to_bus(page) + + (dma64_addr_t) offset); +} + +static __inline__ struct pfn_info * +pci_dac_dma_to_page(struct pci_dev *pdev, dma64_addr_t dma_addr) +{ + unsigned long poff = (dma_addr >> PAGE_SHIFT); + + return frame_table + poff; +} + +static __inline__ unsigned long +pci_dac_dma_to_offset(struct pci_dev *pdev, dma64_addr_t dma_addr) +{ + return (dma_addr & ~PAGE_MASK); +} + +static __inline__ void +pci_dac_dma_sync_single(struct pci_dev *pdev, dma64_addr_t dma_addr, size_t len, int direction) +{ + flush_write_buffers(); +} + +/* These macros should be used after a pci_map_sg call has been done + * to get bus addresses of each of the SG entries and their lengths. + * You should only work with the number of sg entries pci_map_sg + * returns. + */ +#define sg_dma_address(sg) ((sg)->dma_address) +#define sg_dma_len(sg) ((sg)->length) + +/* Return the index of the PCI controller for device. */ +static inline int pci_controller_num(struct pci_dev *dev) +{ + return 0; +} + +#if 0 /* XXX Not in land of Xen XXX */ +#define HAVE_PCI_MMAP +extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, + enum pci_mmap_state mmap_state, int write_combine); +#endif + +#endif /* __KERNEL__ */ + +#endif /* __i386_PCI_H */ diff --git a/xen/include/asm-x86_64/pda.h b/xen/include/asm-x86_64/pda.h new file mode 100644 index 0000000000..a2223a5925 --- /dev/null +++ b/xen/include/asm-x86_64/pda.h @@ -0,0 +1,68 @@ +#ifndef X86_64_PDA_H +#define X86_64_PDA_H + +#include <linux/cache.h> + +/* Per processor datastructure. %gs points to it while the kernel runs */ +/* To use a new field with the *_pda macros it needs to be added to tools/offset.c */ +struct x8664_pda { + unsigned long kernelstack; /* TOS for current process */ + unsigned long oldrsp; /* user rsp for system call */ + unsigned long irqrsp; /* Old rsp for interrupts. */ + struct task_struct *pcurrent; /* Current process */ + int irqcount; /* Irq nesting counter. Starts with -1 */ + int cpunumber; /* Logical CPU number */ + /* XXX: could be a single list */ + unsigned long *pgd_quick; + unsigned long *pmd_quick; + unsigned long *pte_quick; + unsigned long pgtable_cache_sz; + char *irqstackptr; /* top of irqstack */ + unsigned long volatile *level4_pgt; +} ____cacheline_aligned; + +#define PDA_STACKOFFSET (5*8) + +#define IRQSTACK_ORDER 2 +#define IRQSTACKSIZE (PAGE_SIZE << IRQSTACK_ORDER) + +extern struct x8664_pda cpu_pda[]; + +/* + * There is no fast way to get the base address of the PDA, all the accesses + * have to mention %fs/%gs. So it needs to be done this Torvaldian way. + */ +#define sizeof_field(type,field) (sizeof(((type *)0)->field)) +#define typeof_field(type,field) typeof(((type *)0)->field) + +extern void __bad_pda_field(void); +/* Don't use offsetof because it requires too much infrastructure */ +#define pda_offset(field) ((unsigned long)&((struct x8664_pda *)0)->field) + +#define pda_to_op(op,field,val) do { \ + switch (sizeof_field(struct x8664_pda, field)) { \ + case 2: asm volatile(op "w %0,%%gs:%P1" :: "r" (val), "i"(pda_offset(field)):"memory"); break; \ + case 4: asm volatile(op "l %0,%%gs:%P1" :: "r" (val), "i"(pda_offset(field)):"memory"); break; \ + case 8: asm volatile(op "q %0,%%gs:%P1" :: "r" (val), "i"(pda_offset(field)):"memory"); break; \ + default: __bad_pda_field(); \ + } \ + } while (0) + + +#define pda_from_op(op,field) ({ \ + typedef typeof_field(struct x8664_pda, field) T__; T__ ret__; \ + switch (sizeof_field(struct x8664_pda, field)) { \ + case 2: asm volatile(op "w %%gs:%P1,%0":"=r" (ret__): "i" (pda_offset(field)):"memory"); break; \ + case 4: asm volatile(op "l %%gs:%P1,%0":"=r" (ret__): "i" (pda_offset(field)):"memory"); break; \ + case 8: asm volatile(op "q %%gs:%P1,%0":"=r" (ret__): "i" (pda_offset(field)):"memory"); break; \ + default: __bad_pda_field(); \ + } \ + ret__; }) + + +#define read_pda(field) pda_from_op("mov",field) +#define write_pda(field,val) pda_to_op("mov",field,val) +#define add_pda(field,val) pda_to_op("add",field,val) +#define sub_pda(field,val) pda_to_op("sub",field,val) + +#endif diff --git a/xen/include/asm-x86_64/pdb.h b/xen/include/asm-x86_64/pdb.h new file mode 100644 index 0000000000..fa161f22d0 --- /dev/null +++ b/xen/include/asm-x86_64/pdb.h @@ -0,0 +1,51 @@ + +/* + * pervasive debugger + * + * alex ho + * 2004 + * university of cambridge computer laboratory + */ + + +#ifndef __PDB_H__ +#define __PDB_H__ + +#include <asm/ptrace.h> +#include <xeno/list.h> + +extern int pdb_initialized; +extern int pdb_com_port; +extern int pdb_high_bit; + +extern void initialize_pdb(void); + +/* Get/set values from generic debug interface. */ +extern int pdb_set_values(domid_t domain, u_char *buffer, + unsigned long addr, int length); +extern int pdb_get_values(domid_t domain, u_char *buffer, + unsigned long addr, int length); + +/* External entry points. */ +extern int pdb_handle_exception(int exceptionVector, + struct pt_regs *xen_regs); +extern int pdb_serial_input(u_char c, struct pt_regs *regs); +extern void pdb_do_debug(dom0_op_t *op); + +/* Breakpoints. */ +struct pdb_breakpoint +{ + struct list_head list; + unsigned long address; +}; +extern void pdb_bkpt_add (unsigned long address); +extern struct pdb_breakpoint* pdb_bkpt_search (unsigned long address); +extern int pdb_bkpt_remove (unsigned long address); + +/* Conversions. */ +extern int hex (char); +extern char *mem2hex (char *, char *, int); +extern char *hex2mem (char *, char *, int); +extern int hexToInt (char **ptr, int *intValue); + +#endif /* __PDB_H__ */ diff --git a/xen/include/asm-x86_64/pgalloc.h b/xen/include/asm-x86_64/pgalloc.h new file mode 100644 index 0000000000..6f01b44441 --- /dev/null +++ b/xen/include/asm-x86_64/pgalloc.h @@ -0,0 +1,79 @@ +#ifndef _I386_PGALLOC_H +#define _I386_PGALLOC_H + +#include <xeno/config.h> +#include <xeno/sched.h> +#include <asm/processor.h> +#include <asm/fixmap.h> + +#define pgd_quicklist (current_cpu_data.pgd_quick) +#define pmd_quicklist (current_cpu_data.pmd_quick) +#define pte_quicklist (current_cpu_data.pte_quick) +#define pgtable_cache_size (current_cpu_data.pgtable_cache_sz) + + +/* + * Allocate and free page tables. + */ + + +#define pte_free(pte) pte_free_fast(pte) +#define pgd_alloc(mm) get_pgd_fast() +#define pgd_free(pgd) free_pgd_fast(pgd) + +/* + * allocating and freeing a pmd is trivial: the 1-entry pmd is + * inside the pgd, so has no extra memory associated with it. + * (In the PAE case we free the pmds as part of the pgd.) + */ + +#define pmd_alloc_one_fast(mm, addr) ({ BUG(); ((pmd_t *)1); }) +#define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); }) +#define pmd_free_slow(x) do { } while (0) +#define pmd_free_fast(x) do { } while (0) +#define pmd_free(x) do { } while (0) +#define pgd_populate(mm, pmd, pte) BUG() + +/* + * TLB flushing: + * + * - flush_tlb() flushes the current mm struct TLBs + * - flush_tlb_all() flushes all processes TLBs + * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables + * + * ..but the i386 has somewhat limited tlb flushing capabilities, + * and page-granular flushes are available only on i486 and up. + */ + +#ifndef CONFIG_SMP + +#define flush_tlb() __flush_tlb() +#define flush_tlb_all() __flush_tlb() +#define flush_tlb_all_pge() __flush_tlb_pge() +#define local_flush_tlb() __flush_tlb() +#define flush_tlb_cpu(_cpu) __flush_tlb() +#define flush_tlb_mask(_mask) __flush_tlb() +#define try_flush_tlb_mask(_mask) __flush_tlb() + +#else + +#include <xeno/smp.h> + +extern int try_flush_tlb_mask(unsigned long mask); +extern void flush_tlb_mask(unsigned long mask); +extern void flush_tlb_all_pge(void); + +#define flush_tlb() __flush_tlb() +#define flush_tlb_all() flush_tlb_mask((1 << smp_num_cpus) - 1) +#define local_flush_tlb() __flush_tlb() +#define flush_tlb_cpu(_cpu) flush_tlb_mask(1 << (_cpu)) + +#endif + +static inline void flush_tlb_pgtables(struct mm_struct *mm, + unsigned long start, unsigned long end) +{ + /* i386 does not keep any page table caches in TLB */ +} + +#endif /* _I386_PGALLOC_H */ diff --git a/xen/include/asm-x86_64/processor.h b/xen/include/asm-x86_64/processor.h new file mode 100644 index 0000000000..c7df85aa28 --- /dev/null +++ b/xen/include/asm-x86_64/processor.h @@ -0,0 +1,493 @@ +/* + * include/asm-i386/processor.h + * + * Copyright (C) 1994 Linus Torvalds + */ + +#ifndef __ASM_I386_PROCESSOR_H +#define __ASM_I386_PROCESSOR_H + +#include <asm/page.h> +#include <asm/types.h> +#include <asm/cpufeature.h> +#include <asm/desc.h> +#include <xeno/config.h> +#include <hypervisor-ifs/hypervisor-if.h> + +struct task_struct; + +/* + * Default implementation of macro that returns current + * instruction pointer ("program counter"). + */ +#define current_text_addr() \ + ({ void *pc; __asm__("movl $1f,%0\n1:":"=g" (pc)); pc; }) + +/* + * CPU type and hardware bug flags. Kept separately for each CPU. + * Members of this structure are referenced in head.S, so think twice + * before touching them. [mj] + */ + +struct cpuinfo_x86 { + __u8 x86; /* CPU family */ + __u8 x86_vendor; /* CPU vendor */ + __u8 x86_model; + __u8 x86_mask; + int cpuid_level; /* Maximum supported CPUID level, -1=no CPUID */ + __u32 x86_capability[NCAPINTS]; + char x86_vendor_id[16]; + unsigned long *pgd_quick; + unsigned long *pmd_quick; + unsigned long *pte_quick; + unsigned long pgtable_cache_sz; +} __attribute__((__aligned__(SMP_CACHE_BYTES))); + +#define X86_VENDOR_INTEL 0 +#define X86_VENDOR_CYRIX 1 +#define X86_VENDOR_AMD 2 +#define X86_VENDOR_UMC 3 +#define X86_VENDOR_NEXGEN 4 +#define X86_VENDOR_CENTAUR 5 +#define X86_VENDOR_RISE 6 +#define X86_VENDOR_TRANSMETA 7 +#define X86_VENDOR_UNKNOWN 0xff + +/* + * capabilities of CPUs + */ + +extern struct cpuinfo_x86 boot_cpu_data; +extern struct tss_struct init_tss[NR_CPUS]; + +#ifdef CONFIG_SMP +extern struct cpuinfo_x86 cpu_data[]; +#define current_cpu_data cpu_data[smp_processor_id()] +#else +#define cpu_data (&boot_cpu_data) +#define current_cpu_data boot_cpu_data +#endif + +#define cpu_has_pge (test_bit(X86_FEATURE_PGE, boot_cpu_data.x86_capability)) +#define cpu_has_pse (test_bit(X86_FEATURE_PSE, boot_cpu_data.x86_capability)) +#define cpu_has_pae (test_bit(X86_FEATURE_PAE, boot_cpu_data.x86_capability)) +#define cpu_has_tsc (test_bit(X86_FEATURE_TSC, boot_cpu_data.x86_capability)) +#define cpu_has_de (test_bit(X86_FEATURE_DE, boot_cpu_data.x86_capability)) +#define cpu_has_vme (test_bit(X86_FEATURE_VME, boot_cpu_data.x86_capability)) +#define cpu_has_fxsr (test_bit(X86_FEATURE_FXSR, boot_cpu_data.x86_capability)) +#define cpu_has_xmm (test_bit(X86_FEATURE_XMM, boot_cpu_data.x86_capability)) +#define cpu_has_fpu (test_bit(X86_FEATURE_FPU, boot_cpu_data.x86_capability)) +#define cpu_has_apic (test_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability)) + +extern void identify_cpu(struct cpuinfo_x86 *); +extern void print_cpu_info(struct cpuinfo_x86 *); +extern void dodgy_tsc(void); + +/* + * EFLAGS bits + */ +#define X86_EFLAGS_CF 0x00000001 /* Carry Flag */ +#define X86_EFLAGS_PF 0x00000004 /* Parity Flag */ +#define X86_EFLAGS_AF 0x00000010 /* Auxillary carry Flag */ +#define X86_EFLAGS_ZF 0x00000040 /* Zero Flag */ +#define X86_EFLAGS_SF 0x00000080 /* Sign Flag */ +#define X86_EFLAGS_TF 0x00000100 /* Trap Flag */ +#define X86_EFLAGS_IF 0x00000200 /* Interrupt Flag */ +#define X86_EFLAGS_DF 0x00000400 /* Direction Flag */ +#define X86_EFLAGS_OF 0x00000800 /* Overflow Flag */ +#define X86_EFLAGS_IOPL 0x00003000 /* IOPL mask */ +#define X86_EFLAGS_NT 0x00004000 /* Nested Task */ +#define X86_EFLAGS_RF 0x00010000 /* Resume Flag */ +#define X86_EFLAGS_VM 0x00020000 /* Virtual Mode */ +#define X86_EFLAGS_AC 0x00040000 /* Alignment Check */ +#define X86_EFLAGS_VIF 0x00080000 /* Virtual Interrupt Flag */ +#define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */ +#define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */ + +/* + * Generic CPUID function + */ +static inline void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx) +{ + __asm__("cpuid" + : "=a" (*eax), + "=b" (*ebx), + "=c" (*ecx), + "=d" (*edx) + : "0" (op)); +} + +/* + * CPUID functions returning a single datum + */ +static inline unsigned int cpuid_eax(unsigned int op) +{ + unsigned int eax; + + __asm__("cpuid" + : "=a" (eax) + : "0" (op) + : "bx", "cx", "dx"); + return eax; +} +static inline unsigned int cpuid_ebx(unsigned int op) +{ + unsigned int eax, ebx; + + __asm__("cpuid" + : "=a" (eax), "=b" (ebx) + : "0" (op) + : "cx", "dx" ); + return ebx; +} +static inline unsigned int cpuid_ecx(unsigned int op) +{ + unsigned int eax, ecx; + + __asm__("cpuid" + : "=a" (eax), "=c" (ecx) + : "0" (op) + : "bx", "dx" ); + return ecx; +} +static inline unsigned int cpuid_edx(unsigned int op) +{ + unsigned int eax, edx; + + __asm__("cpuid" + : "=a" (eax), "=d" (edx) + : "0" (op) + : "bx", "cx"); + return edx; +} + + +/* + * Intel CPU flags in CR0 + */ +#define X86_CR0_PE 0x00000001 /* Enable Protected Mode (RW) */ +#define X86_CR0_MP 0x00000002 /* Monitor Coprocessor (RW) */ +#define X86_CR0_EM 0x00000004 /* Require FPU Emulation (RO) */ +#define X86_CR0_TS 0x00000008 /* Task Switched (RW) */ +#define X86_CR0_NE 0x00000020 /* Numeric Error Reporting (RW) */ +#define X86_CR0_WP 0x00010000 /* Supervisor Write Protect (RW) */ +#define X86_CR0_AM 0x00040000 /* Alignment Checking (RW) */ +#define X86_CR0_NW 0x20000000 /* Not Write-Through (RW) */ +#define X86_CR0_CD 0x40000000 /* Cache Disable (RW) */ +#define X86_CR0_PG 0x80000000 /* Paging (RW) */ + +#define read_cr0() ({ \ + unsigned int __dummy; \ + __asm__( \ + "movl %%cr0,%0\n\t" \ + :"=r" (__dummy)); \ + __dummy; \ +}) + +#define write_cr0(x) \ + __asm__("movl %0,%%cr0": :"r" (x)); + + + +/* + * Intel CPU features in CR4 + */ +#define X86_CR4_VME 0x0001 /* enable vm86 extensions */ +#define X86_CR4_PVI 0x0002 /* virtual interrupts flag enable */ +#define X86_CR4_TSD 0x0004 /* disable time stamp at ipl 3 */ +#define X86_CR4_DE 0x0008 /* enable debugging extensions */ +#define X86_CR4_PSE 0x0010 /* enable page size extensions */ +#define X86_CR4_PAE 0x0020 /* enable physical address extensions */ +#define X86_CR4_MCE 0x0040 /* Machine check enable */ +#define X86_CR4_PGE 0x0080 /* enable global pages */ +#define X86_CR4_PCE 0x0100 /* enable performance counters at ipl 3 */ +#define X86_CR4_OSFXSR 0x0200 /* enable fast FPU save and restore */ +#define X86_CR4_OSXMMEXCPT 0x0400 /* enable unmasked SSE exceptions */ + +/* + * Save the cr4 feature set we're using (ie + * Pentium 4MB enable and PPro Global page + * enable), so that any CPU's that boot up + * after us can get the correct flags. + */ +extern unsigned long mmu_cr4_features; + +static inline void set_in_cr4 (unsigned long mask) +{ + mmu_cr4_features |= mask; + __asm__("movl %%cr4,%%eax\n\t" + "orl %0,%%eax\n\t" + "movl %%eax,%%cr4\n" + : : "irg" (mask) + :"ax"); +} + +static inline void clear_in_cr4 (unsigned long mask) +{ + mmu_cr4_features &= ~mask; + __asm__("movl %%cr4,%%eax\n\t" + "andl %0,%%eax\n\t" + "movl %%eax,%%cr4\n" + : : "irg" (~mask) + :"ax"); +} + +/* + * Cyrix CPU configuration register indexes + */ +#define CX86_CCR0 0xc0 +#define CX86_CCR1 0xc1 +#define CX86_CCR2 0xc2 +#define CX86_CCR3 0xc3 +#define CX86_CCR4 0xe8 +#define CX86_CCR5 0xe9 +#define CX86_CCR6 0xea +#define CX86_CCR7 0xeb +#define CX86_DIR0 0xfe +#define CX86_DIR1 0xff +#define CX86_ARR_BASE 0xc4 +#define CX86_RCR_BASE 0xdc + +/* + * Cyrix CPU indexed register access macros + */ + +#define getCx86(reg) ({ outb((reg), 0x22); inb(0x23); }) + +#define setCx86(reg, data) do { \ + outb((reg), 0x22); \ + outb((data), 0x23); \ +} while (0) + +#define EISA_bus (0) +#define MCA_bus (0) + +/* from system description table in BIOS. Mostly for MCA use, but +others may find it useful. */ +extern unsigned int machine_id; +extern unsigned int machine_submodel_id; +extern unsigned int BIOS_revision; +extern unsigned int mca_pentium_flag; + +/* + * User space process size: 3GB (default). + */ +#define TASK_SIZE (PAGE_OFFSET) + +/* This decides where the kernel will search for a free chunk of vm + * space during mmap's. + */ +#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) + +/* + * Size of io_bitmap in longwords: 32 is ports 0-0x3ff. + */ +#define IO_BITMAP_SIZE 32 +#define IO_BITMAP_OFFSET offsetof(struct tss_struct,io_bitmap) +#define INVALID_IO_BITMAP_OFFSET 0x8000 + +struct i387_fsave_struct { + long cwd; + long swd; + long twd; + long fip; + long fcs; + long foo; + long fos; + long st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */ +}; + +struct i387_fxsave_struct { + unsigned short cwd; + unsigned short swd; + unsigned short twd; + unsigned short fop; + long fip; + long fcs; + long foo; + long fos; + long mxcsr; + long reserved; + long st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ + long xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */ + long padding[56]; +} __attribute__ ((aligned (16))); + +union i387_union { + struct i387_fsave_struct fsave; + struct i387_fxsave_struct fxsave; +}; + +typedef struct { + unsigned long seg; +} mm_segment_t; + +struct tss_struct { + unsigned short back_link,__blh; + unsigned long esp0; + unsigned short ss0,__ss0h; + unsigned long esp1; + unsigned short ss1,__ss1h; + unsigned long esp2; + unsigned short ss2,__ss2h; + unsigned long __cr3; + unsigned long eip; + unsigned long eflags; + unsigned long eax,ecx,edx,ebx; + unsigned long esp; + unsigned long ebp; + unsigned long esi; + unsigned long edi; + unsigned short es, __esh; + unsigned short cs, __csh; + unsigned short ss, __ssh; + unsigned short ds, __dsh; + unsigned short fs, __fsh; + unsigned short gs, __gsh; + unsigned short ldt, __ldth; + unsigned short trace, bitmap; + unsigned long io_bitmap[IO_BITMAP_SIZE+1]; + /* + * pads the TSS to be cacheline-aligned (size is 0x100) + */ + unsigned long __cacheline_filler[5]; +}; + +struct thread_struct { + unsigned long esp1, ss1; +/* Hardware debugging registers */ + unsigned long debugreg[8]; /* %%db0-7 debug registers */ +/* floating point info */ + union i387_union i387; +/* Trap info. */ + int fast_trap_idx; + struct desc_struct fast_trap_desc; + trap_info_t traps[256]; +}; + +#define IDT_ENTRIES 256 +extern struct desc_struct idt_table[]; +extern struct desc_struct *idt_tables[]; + +#define SET_DEFAULT_FAST_TRAP(_p) \ + (_p)->fast_trap_idx = 0x20; \ + (_p)->fast_trap_desc.a = 0; \ + (_p)->fast_trap_desc.b = 0; + +#define CLEAR_FAST_TRAP(_p) \ + (memset(idt_tables[smp_processor_id()] + (_p)->fast_trap_idx, \ + 0, 8)) + +#define SET_FAST_TRAP(_p) \ + (memcpy(idt_tables[smp_processor_id()] + (_p)->fast_trap_idx, \ + &((_p)->fast_trap_desc), 8)) + +long set_fast_trap(struct task_struct *p, int idx); + +#define INIT_THREAD { \ + 0, 0, \ + { [0 ... 7] = 0 }, /* debugging registers */ \ + { { 0, }, }, /* 387 state */ \ + 0x20, { 0, 0 }, /* DEFAULT_FAST_TRAP */ \ + { {0} } /* io permissions */ \ +} + +#define INIT_TSS { \ + 0,0, /* back_link, __blh */ \ + 0, /* esp0 */ \ + 0, 0, /* ss0 */ \ + 0,0,0,0,0,0, /* stack1, stack2 */ \ + 0, /* cr3 */ \ + 0,0, /* eip,eflags */ \ + 0,0,0,0, /* eax,ecx,edx,ebx */ \ + 0,0,0,0, /* esp,ebp,esi,edi */ \ + 0,0,0,0,0,0, /* es,cs,ss */ \ + 0,0,0,0,0,0, /* ds,fs,gs */ \ + 0,0, /* ldt */ \ + 0, INVALID_IO_BITMAP_OFFSET, /* tace, bitmap */ \ + {~0, } /* ioperm */ \ +} + +struct mm_struct { + /* + * Every domain has a L1 pagetable of its own. Per-domain mappings + * are put in this table (eg. the current GDT is mapped here). + */ + l1_pgentry_t *perdomain_pt; + pagetable_t pagetable; + /* Current LDT details. */ + unsigned long ldt_base, ldt_ents, shadow_ldt_mapcnt; + /* Next entry is passed to LGDT on domain switch. */ + char gdt[6]; +}; + +#define IDLE0_MM \ +{ \ + perdomain_pt: 0, \ + pagetable: mk_pagetable(__pa(idle_pg_table)) \ +} + +/* Convenient accessor for mm.gdt. */ +#define SET_GDT_ENTRIES(_p, _e) ((*(u16 *)((_p)->mm.gdt + 0)) = (_e)) +#define SET_GDT_ADDRESS(_p, _a) ((*(u32 *)((_p)->mm.gdt + 2)) = (_a)) +#define GET_GDT_ENTRIES(_p) ((*(u16 *)((_p)->mm.gdt + 0))) +#define GET_GDT_ADDRESS(_p) ((*(u32 *)((_p)->mm.gdt + 2))) + +long set_gdt(struct task_struct *p, + unsigned long *frames, + unsigned int entries); + +long set_debugreg(struct task_struct *p, int reg, unsigned long value); + +struct microcode { + unsigned int hdrver; + unsigned int rev; + unsigned int date; + unsigned int sig; + unsigned int cksum; + unsigned int ldrver; + unsigned int pf; + unsigned int reserved[5]; + unsigned int bits[500]; +}; + +/* '6' because it used to be for P6 only (but now covers Pentium 4 as well) */ +#define MICROCODE_IOCFREE _IO('6',0) + +/* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ +static inline void rep_nop(void) +{ + __asm__ __volatile__("rep;nop"); +} + +#define cpu_relax() rep_nop() + +/* Prefetch instructions for Pentium III and AMD Athlon */ +#ifdef CONFIG_MPENTIUMIII + +#define ARCH_HAS_PREFETCH +extern inline void prefetch(const void *x) +{ + __asm__ __volatile__ ("prefetchnta (%0)" : : "r"(x)); +} + +#elif CONFIG_X86_USE_3DNOW + +#define ARCH_HAS_PREFETCH +#define ARCH_HAS_PREFETCHW +#define ARCH_HAS_SPINLOCK_PREFETCH + +extern inline void prefetch(const void *x) +{ + __asm__ __volatile__ ("prefetch (%0)" : : "r"(x)); +} + +extern inline void prefetchw(const void *x) +{ + __asm__ __volatile__ ("prefetchw (%0)" : : "r"(x)); +} +#define spin_lock_prefetch(x) prefetchw(x) + +#endif + +#endif /* __ASM_I386_PROCESSOR_H */ diff --git a/xen/include/asm-x86_64/ptrace.h b/xen/include/asm-x86_64/ptrace.h new file mode 100644 index 0000000000..26269afcb0 --- /dev/null +++ b/xen/include/asm-x86_64/ptrace.h @@ -0,0 +1,51 @@ +#ifndef _I386_PTRACE_H +#define _I386_PTRACE_H + +struct pt_regs { + long ebx; + long ecx; + long edx; + long esi; + long edi; + long ebp; + long eax; + int xds; + int xes; + int xfs; + int xgs; + long orig_eax; + long eip; + int xcs; + long eflags; + long esp; + int xss; +}; + +enum EFLAGS { + EF_CF = 0x00000001, + EF_PF = 0x00000004, + EF_AF = 0x00000010, + EF_ZF = 0x00000040, + EF_SF = 0x00000080, + EF_TF = 0x00000100, + EF_IE = 0x00000200, + EF_DF = 0x00000400, + EF_OF = 0x00000800, + EF_IOPL = 0x00003000, + EF_IOPL_RING0 = 0x00000000, + EF_IOPL_RING1 = 0x00001000, + EF_IOPL_RING2 = 0x00002000, + EF_NT = 0x00004000, /* nested task */ + EF_RF = 0x00010000, /* resume */ + EF_VM = 0x00020000, /* virtual mode */ + EF_AC = 0x00040000, /* alignment */ + EF_VIF = 0x00080000, /* virtual interrupt */ + EF_VIP = 0x00100000, /* virtual interrupt pending */ + EF_ID = 0x00200000, /* id */ +}; + +#ifdef __KERNEL__ +#define user_mode(regs) ((3 & (regs)->xcs)) +#endif + +#endif diff --git a/xen/include/asm-x86_64/rwlock.h b/xen/include/asm-x86_64/rwlock.h new file mode 100644 index 0000000000..9475419f95 --- /dev/null +++ b/xen/include/asm-x86_64/rwlock.h @@ -0,0 +1,83 @@ +/* include/asm-i386/rwlock.h + * + * Helpers used by both rw spinlocks and rw semaphores. + * + * Based in part on code from semaphore.h and + * spinlock.h Copyright 1996 Linus Torvalds. + * + * Copyright 1999 Red Hat, Inc. + * + * Written by Benjamin LaHaise. + * + * 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. + */ +#ifndef _ASM_I386_RWLOCK_H +#define _ASM_I386_RWLOCK_H + +#define RW_LOCK_BIAS 0x01000000 +#define RW_LOCK_BIAS_STR "0x01000000" + +#define __build_read_lock_ptr(rw, helper) \ + asm volatile(LOCK "subl $1,(%0)\n\t" \ + "js 2f\n" \ + "1:\n" \ + ".section .text.lock,\"ax\"\n" \ + "2:\tcall " helper "\n\t" \ + "jmp 1b\n" \ + ".previous" \ + ::"a" (rw) : "memory") + +#define __build_read_lock_const(rw, helper) \ + asm volatile(LOCK "subl $1,%0\n\t" \ + "js 2f\n" \ + "1:\n" \ + ".section .text.lock,\"ax\"\n" \ + "2:\tpushl %%eax\n\t" \ + "leal %0,%%eax\n\t" \ + "call " helper "\n\t" \ + "popl %%eax\n\t" \ + "jmp 1b\n" \ + ".previous" \ + :"=m" (*(volatile int *)rw) : : "memory") + +#define __build_read_lock(rw, helper) do { \ + if (__builtin_constant_p(rw)) \ + __build_read_lock_const(rw, helper); \ + else \ + __build_read_lock_ptr(rw, helper); \ + } while (0) + +#define __build_write_lock_ptr(rw, helper) \ + asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \ + "jnz 2f\n" \ + "1:\n" \ + ".section .text.lock,\"ax\"\n" \ + "2:\tcall " helper "\n\t" \ + "jmp 1b\n" \ + ".previous" \ + ::"a" (rw) : "memory") + +#define __build_write_lock_const(rw, helper) \ + asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \ + "jnz 2f\n" \ + "1:\n" \ + ".section .text.lock,\"ax\"\n" \ + "2:\tpushl %%eax\n\t" \ + "leal %0,%%eax\n\t" \ + "call " helper "\n\t" \ + "popl %%eax\n\t" \ + "jmp 1b\n" \ + ".previous" \ + :"=m" (*(volatile int *)rw) : : "memory") + +#define __build_write_lock(rw, helper) do { \ + if (__builtin_constant_p(rw)) \ + __build_write_lock_const(rw, helper); \ + else \ + __build_write_lock_ptr(rw, helper); \ + } while (0) + +#endif diff --git a/xen/include/asm-x86_64/scatterlist.h b/xen/include/asm-x86_64/scatterlist.h new file mode 100644 index 0000000000..9d858415db --- /dev/null +++ b/xen/include/asm-x86_64/scatterlist.h @@ -0,0 +1,16 @@ +#ifndef _I386_SCATTERLIST_H +#define _I386_SCATTERLIST_H + +struct scatterlist { + char * address; /* Location data is to be transferred to, NULL for + * highmem page */ + struct pfn_info * page; /* Location for highmem page, if any */ + unsigned int offset;/* for highmem, page offset */ + + dma_addr_t dma_address; + unsigned int length; +}; + +#define ISA_DMA_THRESHOLD (0x00ffffff) + +#endif /* !(_I386_SCATTERLIST_H) */ diff --git a/xen/include/asm-x86_64/smp.h b/xen/include/asm-x86_64/smp.h new file mode 100644 index 0000000000..58a0a24d30 --- /dev/null +++ b/xen/include/asm-x86_64/smp.h @@ -0,0 +1,83 @@ +#ifndef __ASM_SMP_H +#define __ASM_SMP_H + +#include <xeno/config.h> +#include <asm/ptrace.h> + +#ifdef CONFIG_SMP +#define TARGET_CPUS cpu_online_map +#else +#define TARGET_CPUS 0x01 +#endif + +#ifdef CONFIG_SMP +/* + * Private routines/data + */ + +extern void smp_alloc_memory(void); +extern unsigned long phys_cpu_present_map; +extern unsigned long cpu_online_map; +extern volatile unsigned long smp_invalidate_needed; +extern int pic_mode; +extern void smp_flush_tlb(void); +extern void smp_message_irq(int cpl, void *dev_id, struct pt_regs *regs); +extern void smp_invalidate_rcv(void); /* Process an NMI */ +extern void (*mtrr_hook) (void); +extern void zap_low_mappings (void); + +/* + * On x86 all CPUs are mapped 1:1 to the APIC space. + * This simplifies scheduling and IPI sending and + * compresses data structures. + */ +static inline int cpu_logical_map(int cpu) +{ + return cpu; +} +static inline int cpu_number_map(int cpu) +{ + return cpu; +} + +/* + * Some lowlevel functions might want to know about + * the real APIC ID <-> CPU # mapping. + */ +#define MAX_APICID 256 +extern volatile int cpu_to_physical_apicid[NR_CPUS]; +extern volatile int physical_apicid_to_cpu[MAX_APICID]; +extern volatile int cpu_to_logical_apicid[NR_CPUS]; +extern volatile int logical_apicid_to_cpu[MAX_APICID]; + +/* + * General functions that each host system must provide. + */ + +extern void smp_store_cpu_info(int id); /* Store per CPU info (like the initial udelay numbers */ + +/* + * This function is needed by all SMP systems. It must _always_ be valid + * from the initial startup. We map APIC_BASE very early in page_setup(), + * so this is correct in the x86 case. + */ + +#define smp_processor_id() (current->processor) + +#include <asm/fixmap.h> +#include <asm/apic.h> + +static __inline int hard_smp_processor_id(void) +{ + /* we don't want to mark this access volatile - bad code generation */ + return GET_APIC_ID(*(unsigned long *)(APIC_BASE+APIC_ID)); +} + +static __inline int logical_smp_processor_id(void) +{ + /* we don't want to mark this access volatile - bad code generation */ + return GET_APIC_LOGICAL_ID(*(unsigned long *)(APIC_BASE+APIC_LDR)); +} + +#endif +#endif diff --git a/xen/include/asm-x86_64/smpboot.h b/xen/include/asm-x86_64/smpboot.h new file mode 100644 index 0000000000..4017902c69 --- /dev/null +++ b/xen/include/asm-x86_64/smpboot.h @@ -0,0 +1,130 @@ +#ifndef __ASM_SMPBOOT_H +#define __ASM_SMPBOOT_H + +/*emum for clustered_apic_mode values*/ +enum{ + CLUSTERED_APIC_NONE = 0, + CLUSTERED_APIC_XAPIC, + CLUSTERED_APIC_NUMAQ +}; + +#ifdef CONFIG_X86_CLUSTERED_APIC +extern unsigned int apic_broadcast_id; +extern unsigned char clustered_apic_mode; +extern unsigned char esr_disable; +extern unsigned char int_delivery_mode; +extern unsigned int int_dest_addr_mode; +extern int cyclone_setup(char*); + +static inline void detect_clustered_apic(char* oem, char* prod) +{ + /* + * Can't recognize Summit xAPICs at present, so use the OEM ID. + */ + if (!strncmp(oem, "IBM ENSW", 8) && !strncmp(prod, "VIGIL SMP", 9)){ + clustered_apic_mode = CLUSTERED_APIC_XAPIC; + apic_broadcast_id = APIC_BROADCAST_ID_XAPIC; + int_dest_addr_mode = APIC_DEST_PHYSICAL; + int_delivery_mode = dest_Fixed; + esr_disable = 1; + /*Start cyclone clock*/ + cyclone_setup(0); + } + else if (!strncmp(oem, "IBM ENSW", 8) && !strncmp(prod, "RUTHLESS SMP", 9)){ + clustered_apic_mode = CLUSTERED_APIC_XAPIC; + apic_broadcast_id = APIC_BROADCAST_ID_XAPIC; + int_dest_addr_mode = APIC_DEST_PHYSICAL; + int_delivery_mode = dest_Fixed; + esr_disable = 1; + /*Start cyclone clock*/ + cyclone_setup(0); + } + else if (!strncmp(oem, "IBM NUMA", 8)){ + clustered_apic_mode = CLUSTERED_APIC_NUMAQ; + apic_broadcast_id = APIC_BROADCAST_ID_APIC; + int_dest_addr_mode = APIC_DEST_LOGICAL; + int_delivery_mode = dest_LowestPrio; + esr_disable = 1; + } +} +#define INT_DEST_ADDR_MODE (int_dest_addr_mode) +#define INT_DELIVERY_MODE (int_delivery_mode) +#else /* CONFIG_X86_CLUSTERED_APIC */ +#define apic_broadcast_id (APIC_BROADCAST_ID_APIC) +#define clustered_apic_mode (CLUSTERED_APIC_NONE) +#define esr_disable (0) +#define detect_clustered_apic(x,y) +#define INT_DEST_ADDR_MODE (APIC_DEST_LOGICAL) /* logical delivery */ +#define INT_DELIVERY_MODE (dest_LowestPrio) +#endif /* CONFIG_X86_CLUSTERED_APIC */ +#define BAD_APICID 0xFFu + +#define TRAMPOLINE_LOW phys_to_virt((clustered_apic_mode == CLUSTERED_APIC_NUMAQ)?0x8:0x467) +#define TRAMPOLINE_HIGH phys_to_virt((clustered_apic_mode == CLUSTERED_APIC_NUMAQ)?0xa:0x469) + +#define boot_cpu_apicid ((clustered_apic_mode == CLUSTERED_APIC_NUMAQ)?boot_cpu_logical_apicid:boot_cpu_physical_apicid) + +extern unsigned char raw_phys_apicid[NR_CPUS]; + +/* + * How to map from the cpu_present_map + */ +static inline int cpu_present_to_apicid(int mps_cpu) +{ + if (clustered_apic_mode == CLUSTERED_APIC_XAPIC) + return raw_phys_apicid[mps_cpu]; + if(clustered_apic_mode == CLUSTERED_APIC_NUMAQ) + return (mps_cpu/4)*16 + (1<<(mps_cpu%4)); + return mps_cpu; +} + +static inline unsigned long apicid_to_phys_cpu_present(int apicid) +{ + if(clustered_apic_mode) + return 1UL << (((apicid >> 4) << 2) + (apicid & 0x3)); + return 1UL << apicid; +} + +#define physical_to_logical_apicid(phys_apic) ( (1ul << (phys_apic & 0x3)) | (phys_apic & 0xF0u) ) + +/* + * Mappings between logical cpu number and logical / physical apicid + * The first four macros are trivial, but it keeps the abstraction consistent + */ +extern volatile int logical_apicid_2_cpu[]; +extern volatile int cpu_2_logical_apicid[]; +extern volatile int physical_apicid_2_cpu[]; +extern volatile int cpu_2_physical_apicid[]; + +#define logical_apicid_to_cpu(apicid) logical_apicid_2_cpu[apicid] +#define cpu_to_logical_apicid(cpu) cpu_2_logical_apicid[cpu] +#define physical_apicid_to_cpu(apicid) physical_apicid_2_cpu[apicid] +#define cpu_to_physical_apicid(cpu) cpu_2_physical_apicid[cpu] +#ifdef CONFIG_MULTIQUAD /* use logical IDs to bootstrap */ +#define boot_apicid_to_cpu(apicid) logical_apicid_2_cpu[apicid] +#define cpu_to_boot_apicid(cpu) cpu_2_logical_apicid[cpu] +#else /* !CONFIG_MULTIQUAD */ /* use physical IDs to bootstrap */ +#define boot_apicid_to_cpu(apicid) physical_apicid_2_cpu[apicid] +#define cpu_to_boot_apicid(cpu) cpu_2_physical_apicid[cpu] +#endif /* CONFIG_MULTIQUAD */ + +#ifdef CONFIG_X86_CLUSTERED_APIC +static inline int target_cpus(void) +{ + static int cpu; + switch(clustered_apic_mode){ + case CLUSTERED_APIC_NUMAQ: + /* Broadcast intrs to local quad only. */ + return APIC_BROADCAST_ID_APIC; + case CLUSTERED_APIC_XAPIC: + /*round robin the interrupts*/ + cpu = (cpu+1)%smp_num_cpus; + return cpu_to_physical_apicid(cpu); + default: + } + return cpu_online_map; +} +#else +#define target_cpus() (0xFF) +#endif +#endif diff --git a/xen/include/asm-x86_64/softirq.h b/xen/include/asm-x86_64/softirq.h new file mode 100644 index 0000000000..292baac6ea --- /dev/null +++ b/xen/include/asm-x86_64/softirq.h @@ -0,0 +1,17 @@ +#ifndef __ASM_SOFTIRQ_H +#define __ASM_SOFTIRQ_H + +#include <asm/atomic.h> +#include <asm/hardirq.h> + +#define cpu_bh_enable(cpu) \ + do { barrier(); local_bh_count(cpu)--; } while (0) +#define cpu_bh_disable(cpu) \ + do { local_bh_count(cpu)++; barrier(); } while (0) + +#define local_bh_disable() cpu_bh_disable(smp_processor_id()) +#define local_bh_enable() cpu_bh_enable(smp_processor_id()) + +#define in_softirq() (local_bh_count(smp_processor_id()) != 0) + +#endif /* __ASM_SOFTIRQ_H */ diff --git a/xen/include/asm-x86_64/spinlock.h b/xen/include/asm-x86_64/spinlock.h new file mode 100644 index 0000000000..9a4fc8573d --- /dev/null +++ b/xen/include/asm-x86_64/spinlock.h @@ -0,0 +1,205 @@ +#ifndef __ASM_SPINLOCK_H +#define __ASM_SPINLOCK_H + +#include <xeno/config.h> +#include <xeno/lib.h> +#include <asm/atomic.h> +#include <asm/rwlock.h> + +#if 0 +#define SPINLOCK_DEBUG 1 +#else +#define SPINLOCK_DEBUG 0 +#endif + +/* + * Your basic SMP spinlocks, allowing only a single CPU anywhere + */ + +typedef struct { + volatile unsigned int lock; +#if SPINLOCK_DEBUG + unsigned magic; +#endif +} spinlock_t; + +#define SPINLOCK_MAGIC 0xdead4ead + +#if SPINLOCK_DEBUG +#define SPINLOCK_MAGIC_INIT , SPINLOCK_MAGIC +#else +#define SPINLOCK_MAGIC_INIT /* */ +#endif + +#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 SPINLOCK_MAGIC_INIT } + +#define spin_lock_init(x) do { *(x) = SPIN_LOCK_UNLOCKED; } while(0) + +/* + * Simple spin lock operations. There are two variants, one clears IRQ's + * on the local processor, one does not. + * + * We make no fairness assumptions. They have a cost. + */ + +#define spin_is_locked(x) (*(volatile char *)(&(x)->lock) <= 0) +#define spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x)) + +#define spin_lock_string \ + "\n1:\t" \ + "lock ; decb %0\n\t" \ + "js 2f\n" \ + ".section .text.lock,\"ax\"\n" \ + "2:\t" \ + "cmpb $0,%0\n\t" \ + "rep;nop\n\t" \ + "jle 2b\n\t" \ + "jmp 1b\n" \ + ".previous" + +/* + * This works. Despite all the confusion. + * (except on PPro SMP or if we are using OOSTORE) + * (PPro errata 66, 92) + */ + +#if !defined(CONFIG_X86_OOSTORE) && !defined(CONFIG_X86_PPRO_FENCE) + +#define spin_unlock_string \ + "movb $1,%0" \ + :"=m" (lock->lock) : : "memory" + + +static inline void spin_unlock(spinlock_t *lock) +{ +#if SPINLOCK_DEBUG + if (lock->magic != SPINLOCK_MAGIC) + BUG(); + if (!spin_is_locked(lock)) + BUG(); +#endif + __asm__ __volatile__( + spin_unlock_string + ); +} + +#else + +#define spin_unlock_string \ + "xchgb %b0, %1" \ + :"=q" (oldval), "=m" (lock->lock) \ + :"0" (oldval) : "memory" + +static inline void spin_unlock(spinlock_t *lock) +{ + char oldval = 1; +#if SPINLOCK_DEBUG + if (lock->magic != SPINLOCK_MAGIC) + BUG(); + if (!spin_is_locked(lock)) + BUG(); +#endif + __asm__ __volatile__( + spin_unlock_string + ); +} + +#endif + +static inline int spin_trylock(spinlock_t *lock) +{ + char oldval; + __asm__ __volatile__( + "xchgb %b0,%1" + :"=q" (oldval), "=m" (lock->lock) + :"0" (0) : "memory"); + return oldval > 0; +} + +static inline void spin_lock(spinlock_t *lock) +{ +#if SPINLOCK_DEBUG + __label__ here; +here: + if (lock->magic != SPINLOCK_MAGIC) { +printk("eip: %p\n", &&here); + BUG(); + } +#endif + __asm__ __volatile__( + spin_lock_string + :"=m" (lock->lock) : : "memory"); +} + + +/* + * Read-write spinlocks, allowing multiple readers + * but only one writer. + * + * NOTE! it is quite common to have readers in interrupts + * but no interrupt writers. For those circumstances we + * can "mix" irq-safe locks - any writer needs to get a + * irq-safe write-lock, but readers can get non-irqsafe + * read-locks. + */ +typedef struct { + volatile unsigned int lock; +#if SPINLOCK_DEBUG + unsigned magic; +#endif +} rwlock_t; + +#define RWLOCK_MAGIC 0xdeaf1eed + +#if SPINLOCK_DEBUG +#define RWLOCK_MAGIC_INIT , RWLOCK_MAGIC +#else +#define RWLOCK_MAGIC_INIT /* */ +#endif + +#define RW_LOCK_UNLOCKED (rwlock_t) { RW_LOCK_BIAS RWLOCK_MAGIC_INIT } + +#define rwlock_init(x) do { *(x) = RW_LOCK_UNLOCKED; } while(0) + +/* + * On x86, we implement read-write locks as a 32-bit counter + * with the high bit (sign) being the "contended" bit. + * + * The inline assembly is non-obvious. Think about it. + * + * Changed to use the same technique as rw semaphores. See + * semaphore.h for details. -ben + */ +/* the spinlock helpers are in arch/i386/kernel/semaphore.c */ + +static inline void read_lock(rwlock_t *rw) +{ +#if SPINLOCK_DEBUG + if (rw->magic != RWLOCK_MAGIC) + BUG(); +#endif + __build_read_lock(rw, "__read_lock_failed"); +} + +static inline void write_lock(rwlock_t *rw) +{ +#if SPINLOCK_DEBUG + if (rw->magic != RWLOCK_MAGIC) + BUG(); +#endif + __build_write_lock(rw, "__write_lock_failed"); +} + +#define read_unlock(rw) asm volatile("lock ; incl %0" :"=m" ((rw)->lock) : : "memory") +#define write_unlock(rw) asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ",%0":"=m" ((rw)->lock) : : "memory") + +static inline int write_trylock(rwlock_t *lock) +{ + atomic_t *count = (atomic_t *)lock; + if (atomic_sub_and_test(RW_LOCK_BIAS, count)) + return 1; + atomic_add(RW_LOCK_BIAS, count); + return 0; +} + +#endif /* __ASM_SPINLOCK_H */ diff --git a/xen/include/asm-x86_64/string.h b/xen/include/asm-x86_64/string.h new file mode 100644 index 0000000000..385da59b5c --- /dev/null +++ b/xen/include/asm-x86_64/string.h @@ -0,0 +1,500 @@ +#ifndef _I386_STRING_H_ +#define _I386_STRING_H_ + +#ifdef __KERNEL__ +#include <linux/config.h> +/* + * On a 486 or Pentium, we are better off not using the + * byte string operations. But on a 386 or a PPro the + * byte string ops are faster than doing it by hand + * (MUCH faster on a Pentium). + * + * Also, the byte strings actually work correctly. Forget + * the i486 routines for now as they may be broken.. + */ +#if FIXED_486_STRING && defined(CONFIG_X86_USE_STRING_486) +#include <asm/string-486.h> +#else + +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + + +#define __HAVE_ARCH_STRCPY +static inline char * strcpy(char * dest,const char *src) +{ +int d0, d1, d2; +__asm__ __volatile__( + "1:\tlodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b" + : "=&S" (d0), "=&D" (d1), "=&a" (d2) + :"0" (src),"1" (dest) : "memory"); +return dest; +} + +#define __HAVE_ARCH_STRNCPY +static inline char * strncpy(char * dest,const char *src,size_t count) +{ +int d0, d1, d2, d3; +__asm__ __volatile__( + "1:\tdecl %2\n\t" + "js 2f\n\t" + "lodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "rep\n\t" + "stosb\n" + "2:" + : "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3) + :"0" (src),"1" (dest),"2" (count) : "memory"); +return dest; +} + +#define __HAVE_ARCH_STRCAT +static inline char * strcat(char * dest,const char * src) +{ +int d0, d1, d2, d3; +__asm__ __volatile__( + "repne\n\t" + "scasb\n\t" + "decl %1\n" + "1:\tlodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b" + : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3) + : "0" (src), "1" (dest), "2" (0), "3" (0xffffffff):"memory"); +return dest; +} + +#define __HAVE_ARCH_STRNCAT +static inline char * strncat(char * dest,const char * src,size_t count) +{ +int d0, d1, d2, d3; +__asm__ __volatile__( + "repne\n\t" + "scasb\n\t" + "decl %1\n\t" + "movl %8,%3\n" + "1:\tdecl %3\n\t" + "js 2f\n\t" + "lodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n" + "2:\txorl %2,%2\n\t" + "stosb" + : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3) + : "0" (src),"1" (dest),"2" (0),"3" (0xffffffff), "g" (count) + : "memory"); +return dest; +} + +#define __HAVE_ARCH_STRCMP +static inline int strcmp(const char * cs,const char * ct) +{ +int d0, d1; +register int __res; +__asm__ __volatile__( + "1:\tlodsb\n\t" + "scasb\n\t" + "jne 2f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "xorl %%eax,%%eax\n\t" + "jmp 3f\n" + "2:\tsbbl %%eax,%%eax\n\t" + "orb $1,%%al\n" + "3:" + :"=a" (__res), "=&S" (d0), "=&D" (d1) + :"1" (cs),"2" (ct)); +return __res; +} + +#define __HAVE_ARCH_STRNCMP +static inline int strncmp(const char * cs,const char * ct,size_t count) +{ +register int __res; +int d0, d1, d2; +__asm__ __volatile__( + "1:\tdecl %3\n\t" + "js 2f\n\t" + "lodsb\n\t" + "scasb\n\t" + "jne 3f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n" + "2:\txorl %%eax,%%eax\n\t" + "jmp 4f\n" + "3:\tsbbl %%eax,%%eax\n\t" + "orb $1,%%al\n" + "4:" + :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2) + :"1" (cs),"2" (ct),"3" (count)); +return __res; +} + +#define __HAVE_ARCH_STRCHR +static inline char * strchr(const char * s, int c) +{ +int d0; +register char * __res; +__asm__ __volatile__( + "movb %%al,%%ah\n" + "1:\tlodsb\n\t" + "cmpb %%ah,%%al\n\t" + "je 2f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "movl $1,%1\n" + "2:\tmovl %1,%0\n\t" + "decl %0" + :"=a" (__res), "=&S" (d0) : "1" (s),"0" (c)); +return __res; +} + +#define __HAVE_ARCH_STRRCHR +static inline char * strrchr(const char * s, int c) +{ +int d0, d1; +register char * __res; +__asm__ __volatile__( + "movb %%al,%%ah\n" + "1:\tlodsb\n\t" + "cmpb %%ah,%%al\n\t" + "jne 2f\n\t" + "leal -1(%%esi),%0\n" + "2:\ttestb %%al,%%al\n\t" + "jne 1b" + :"=g" (__res), "=&S" (d0), "=&a" (d1) :"0" (0),"1" (s),"2" (c)); +return __res; +} + +#define __HAVE_ARCH_STRLEN +static inline size_t strlen(const char * s) +{ +int d0; +register int __res; +__asm__ __volatile__( + "repne\n\t" + "scasb\n\t" + "notl %0\n\t" + "decl %0" + :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff)); +return __res; +} + +static inline void * __memcpy(void * to, const void * from, size_t n) +{ +int d0, d1, d2; +__asm__ __volatile__( + "rep ; movsl\n\t" + "testb $2,%b4\n\t" + "je 1f\n\t" + "movsw\n" + "1:\ttestb $1,%b4\n\t" + "je 2f\n\t" + "movsb\n" + "2:" + : "=&c" (d0), "=&D" (d1), "=&S" (d2) + :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from) + : "memory"); +return (to); +} + +/* + * This looks horribly ugly, but the compiler can optimize it totally, + * as the count is constant. + */ +static inline void * __constant_memcpy(void * to, const void * from, size_t n) +{ + switch (n) { + case 0: + return to; + case 1: + *(unsigned char *)to = *(const unsigned char *)from; + return to; + case 2: + *(unsigned short *)to = *(const unsigned short *)from; + return to; + case 3: + *(unsigned short *)to = *(const unsigned short *)from; + *(2+(unsigned char *)to) = *(2+(const unsigned char *)from); + return to; + case 4: + *(unsigned long *)to = *(const unsigned long *)from; + return to; + case 6: /* for Ethernet addresses */ + *(unsigned long *)to = *(const unsigned long *)from; + *(2+(unsigned short *)to) = *(2+(const unsigned short *)from); + return to; + case 8: + *(unsigned long *)to = *(const unsigned long *)from; + *(1+(unsigned long *)to) = *(1+(const unsigned long *)from); + return to; + case 12: + *(unsigned long *)to = *(const unsigned long *)from; + *(1+(unsigned long *)to) = *(1+(const unsigned long *)from); + *(2+(unsigned long *)to) = *(2+(const unsigned long *)from); + return to; + case 16: + *(unsigned long *)to = *(const unsigned long *)from; + *(1+(unsigned long *)to) = *(1+(const unsigned long *)from); + *(2+(unsigned long *)to) = *(2+(const unsigned long *)from); + *(3+(unsigned long *)to) = *(3+(const unsigned long *)from); + return to; + case 20: + *(unsigned long *)to = *(const unsigned long *)from; + *(1+(unsigned long *)to) = *(1+(const unsigned long *)from); + *(2+(unsigned long *)to) = *(2+(const unsigned long *)from); + *(3+(unsigned long *)to) = *(3+(const unsigned long *)from); + *(4+(unsigned long *)to) = *(4+(const unsigned long *)from); + return to; + } +#define COMMON(x) \ +__asm__ __volatile__( \ + "rep ; movsl" \ + x \ + : "=&c" (d0), "=&D" (d1), "=&S" (d2) \ + : "0" (n/4),"1" ((long) to),"2" ((long) from) \ + : "memory"); +{ + int d0, d1, d2; + switch (n % 4) { + case 0: COMMON(""); return to; + case 1: COMMON("\n\tmovsb"); return to; + case 2: COMMON("\n\tmovsw"); return to; + default: COMMON("\n\tmovsw\n\tmovsb"); return to; + } +} + +#undef COMMON +} + +#define __HAVE_ARCH_MEMCPY + +#define memcpy(t, f, n) \ +(__builtin_constant_p(n) ? \ + __constant_memcpy((t),(f),(n)) : \ + __memcpy((t),(f),(n))) + + +/* + * struct_cpy(x,y), copy structure *x into (matching structure) *y. + * + * We get link-time errors if the structure sizes do not match. + * There is no runtime overhead, it's all optimized away at + * compile time. + */ +//extern void __struct_cpy_bug (void); + +/* +#define struct_cpy(x,y) \ +({ \ + if (sizeof(*(x)) != sizeof(*(y))) \ + __struct_cpy_bug; \ + memcpy(x, y, sizeof(*(x))); \ +}) +*/ + +#define __HAVE_ARCH_MEMMOVE +static inline void * memmove(void * dest,const void * src, size_t n) +{ +int d0, d1, d2; +if (dest<src) +__asm__ __volatile__( + "rep\n\t" + "movsb" + : "=&c" (d0), "=&S" (d1), "=&D" (d2) + :"0" (n),"1" (src),"2" (dest) + : "memory"); +else +__asm__ __volatile__( + "std\n\t" + "rep\n\t" + "movsb\n\t" + "cld" + : "=&c" (d0), "=&S" (d1), "=&D" (d2) + :"0" (n), + "1" (n-1+(const char *)src), + "2" (n-1+(char *)dest) + :"memory"); +return dest; +} + +#define memcmp __builtin_memcmp + +#define __HAVE_ARCH_MEMCHR +static inline void * memchr(const void * cs,int c,size_t count) +{ +int d0; +register void * __res; +if (!count) + return NULL; +__asm__ __volatile__( + "repne\n\t" + "scasb\n\t" + "je 1f\n\t" + "movl $1,%0\n" + "1:\tdecl %0" + :"=D" (__res), "=&c" (d0) : "a" (c),"0" (cs),"1" (count)); +return __res; +} + +static inline void * __memset_generic(void * s, char c,size_t count) +{ +int d0, d1; +__asm__ __volatile__( + "rep\n\t" + "stosb" + : "=&c" (d0), "=&D" (d1) + :"a" (c),"1" (s),"0" (count) + :"memory"); +return s; +} + +/* we might want to write optimized versions of these later */ +#define __constant_count_memset(s,c,count) __memset_generic((s),(c),(count)) + +/* + * memset(x,0,y) is a reasonably common thing to do, so we want to fill + * things 32 bits at a time even when we don't know the size of the + * area at compile-time.. + */ +static inline void * __constant_c_memset(void * s, unsigned long c, size_t count) +{ +int d0, d1; +__asm__ __volatile__( + "rep ; stosl\n\t" + "testb $2,%b3\n\t" + "je 1f\n\t" + "stosw\n" + "1:\ttestb $1,%b3\n\t" + "je 2f\n\t" + "stosb\n" + "2:" + : "=&c" (d0), "=&D" (d1) + :"a" (c), "q" (count), "0" (count/4), "1" ((long) s) + :"memory"); +return (s); +} + +/* Added by Gertjan van Wingerde to make minix and sysv module work */ +#define __HAVE_ARCH_STRNLEN +static inline size_t strnlen(const char * s, size_t count) +{ +int d0; +register int __res; +__asm__ __volatile__( + "movl %2,%0\n\t" + "jmp 2f\n" + "1:\tcmpb $0,(%0)\n\t" + "je 3f\n\t" + "incl %0\n" + "2:\tdecl %1\n\t" + "cmpl $-1,%1\n\t" + "jne 1b\n" + "3:\tsubl %2,%0" + :"=a" (__res), "=&d" (d0) + :"c" (s),"1" (count)); +return __res; +} +/* end of additional stuff */ + +//#define __HAVE_ARCH_STRSTR + +//extern char *strstr(const char *cs, const char *ct); + +/* + * This looks horribly ugly, but the compiler can optimize it totally, + * as we by now know that both pattern and count is constant.. + */ +static inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count) +{ + switch (count) { + case 0: + return s; + case 1: + *(unsigned char *)s = pattern; + return s; + case 2: + *(unsigned short *)s = pattern; + return s; + case 3: + *(unsigned short *)s = pattern; + *(2+(unsigned char *)s) = pattern; + return s; + case 4: + *(unsigned long *)s = pattern; + return s; + } +#define COMMON(x) \ +__asm__ __volatile__( \ + "rep ; stosl" \ + x \ + : "=&c" (d0), "=&D" (d1) \ + : "a" (pattern),"0" (count/4),"1" ((long) s) \ + : "memory") +{ + int d0, d1; + switch (count % 4) { + case 0: COMMON(""); return s; + case 1: COMMON("\n\tstosb"); return s; + case 2: COMMON("\n\tstosw"); return s; + default: COMMON("\n\tstosw\n\tstosb"); return s; + } +} + +#undef COMMON +} + +#define __constant_c_x_memset(s, c, count) \ +(__builtin_constant_p(count) ? \ + __constant_c_and_count_memset((s),(c),(count)) : \ + __constant_c_memset((s),(c),(count))) + +#define __memset(s, c, count) \ +(__builtin_constant_p(count) ? \ + __constant_count_memset((s),(c),(count)) : \ + __memset_generic((s),(c),(count))) + +#define __HAVE_ARCH_MEMSET +#define memset(s, c, count) \ +(__builtin_constant_p(c) ? \ + __constant_c_x_memset((s),(0x01010101UL*(unsigned char)(c)),(count)) : \ + __memset((s),(c),(count))) + +/* + * find the first occurrence of byte 'c', or 1 past the area if none + */ +#define __HAVE_ARCH_MEMSCAN +static inline void * memscan(void * addr, int c, size_t size) +{ + if (!size) + return addr; + __asm__("repnz; scasb\n\t" + "jnz 1f\n\t" + "dec %%edi\n" + "1:" + : "=D" (addr), "=c" (size) + : "0" (addr), "1" (size), "a" (c)); + return addr; +} + +#endif /* CONFIG_X86_USE_STRING_486 */ +#endif /* __KERNEL__ */ + +#endif diff --git a/xen/include/asm-x86_64/system.h b/xen/include/asm-x86_64/system.h new file mode 100644 index 0000000000..3e85277d6c --- /dev/null +++ b/xen/include/asm-x86_64/system.h @@ -0,0 +1,208 @@ +#ifndef __ASM_SYSTEM_H +#define __ASM_SYSTEM_H + +#include <xeno/config.h> +#include <asm/bitops.h> + +/* Clear and set 'TS' bit respectively */ +#define clts() __asm__ __volatile__ ("clts") +#define stts() write_cr0(X86_CR0_TS|read_cr0()) + +#define wbinvd() \ + __asm__ __volatile__ ("wbinvd": : :"memory"); + +static inline unsigned long get_limit(unsigned long segment) +{ + unsigned long __limit; + __asm__("lsll %1,%0" + :"=r" (__limit):"r" (segment)); + return __limit+1; +} + +#define nop() __asm__ __volatile__ ("nop") + +#define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr)))) + +struct __xchg_dummy { unsigned long a[100]; }; +#define __xg(x) ((struct __xchg_dummy *)(x)) + + +/* + * Note: no "lock" prefix even on SMP: xchg always implies lock anyway + * Note 2: xchg has side effect, so that attribute volatile is necessary, + * but generally the primitive is invalid, *ptr is output argument. --ANK + */ +static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) +{ + switch (size) { + case 1: + __asm__ __volatile__("xchgb %b0,%1" + :"=q" (x) + :"m" (*__xg(ptr)), "0" (x) + :"memory"); + break; + case 2: + __asm__ __volatile__("xchgw %w0,%1" + :"=r" (x) + :"m" (*__xg(ptr)), "0" (x) + :"memory"); + break; + case 4: + __asm__ __volatile__("xchgl %0,%1" + :"=r" (x) + :"m" (*__xg(ptr)), "0" (x) + :"memory"); + break; + } + return x; +} + +/* + * Atomic compare and exchange. Compare OLD with MEM, if identical, + * store NEW in MEM. Return the initial value in MEM. Success is + * indicated by comparing RETURN with OLD. + */ + +static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old, + unsigned long new, int size) +{ + unsigned long prev; + switch (size) { + case 1: + __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2" + : "=a"(prev) + : "q"(new), "m"(*__xg(ptr)), "0"(old) + : "memory"); + return prev; + case 2: + __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2" + : "=a"(prev) + : "q"(new), "m"(*__xg(ptr)), "0"(old) + : "memory"); + return prev; + case 4: + __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2" + : "=a"(prev) + : "q"(new), "m"(*__xg(ptr)), "0"(old) + : "memory"); + return prev; + } + return old; +} + +#define cmpxchg(ptr,o,n)\ + ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\ + (unsigned long)(n),sizeof(*(ptr)))) + + +/* + * This function causes longword _o to be changed to _n at location _p. + * If this access causes a fault then we return 1, otherwise we return 0. + * If no fault occurs then _o is updated to teh value we saw at _p. If this + * is the same as the initial value of _o then _n is written to location _p. + */ +#define cmpxchg_user(_p,_o,_n) \ +({ \ + int _rc; \ + __asm__ __volatile__ ( \ + "1: " LOCK_PREFIX "cmpxchgl %2,%3\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: movl $1,%1\n" \ + " jmp 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 1b,3b\n" \ + ".previous" \ + : "=a" (_o), "=r" (_rc) \ + : "q" (_n), "m" (*__xg((volatile void *)_p)), "0" (_o), "1" (0) \ + : "memory"); \ + _rc; \ +}) + +/* + * Force strict CPU ordering. + * And yes, this is required on UP too when we're talking + * to devices. + * + * For now, "wmb()" doesn't actually do anything, as all + * Intel CPU's follow what Intel calls a *Processor Order*, + * in which all writes are seen in the program order even + * outside the CPU. + * + * I expect future Intel CPU's to have a weaker ordering, + * but I'd also expect them to finally get their act together + * and add some real memory barriers if so. + * + * Some non intel clones support out of order store. wmb() ceases to be a + * nop for these. + */ + +#define mb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory") +#define rmb() mb() + +#ifdef CONFIG_X86_OOSTORE +#define wmb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory") +#else +#define wmb() __asm__ __volatile__ ("": : :"memory") +#endif + +#ifdef CONFIG_SMP +#define smp_mb() mb() +#define smp_rmb() rmb() +#define smp_wmb() wmb() +#else +#define smp_mb() barrier() +#define smp_rmb() barrier() +#define smp_wmb() barrier() +#endif + +#define set_mb(var, value) do { xchg(&var, value); } while (0) +#define set_wmb(var, value) do { var = value; wmb(); } while (0) + +/* interrupt control.. */ +#define __save_flags(x) __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */) +#define __restore_flags(x) __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory", "cc") +#define __cli() __asm__ __volatile__("cli": : :"memory") +#define __sti() __asm__ __volatile__("sti": : :"memory") +/* used in the idle loop; sti takes one instruction cycle to complete */ +#define safe_halt() __asm__ __volatile__("sti; hlt": : :"memory") + +/* For spinlocks etc */ +#define local_irq_save(x) __asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (x): /* no input */ :"memory") +#define local_irq_restore(x) __restore_flags(x) +#define local_irq_disable() __cli() +#define local_irq_enable() __sti() + +#ifdef CONFIG_SMP + +extern void __global_cli(void); +extern void __global_sti(void); +extern unsigned long __global_save_flags(void); +extern void __global_restore_flags(unsigned long); +#define cli() __global_cli() +#define sti() __global_sti() +#define save_flags(x) ((x)=__global_save_flags()) +#define restore_flags(x) __global_restore_flags(x) + +#else + +#define cli() __cli() +#define sti() __sti() +#define save_flags(x) __save_flags(x) +#define restore_flags(x) __restore_flags(x) + +#endif + +/* + * disable hlt during certain critical i/o operations + */ +#define HAVE_DISABLE_HLT +void disable_hlt(void); +void enable_hlt(void); + +#define BROKEN_ACPI_Sx 0x0001 +#define BROKEN_INIT_AFTER_S1 0x0002 + +#endif diff --git a/xen/include/asm-x86_64/time.h b/xen/include/asm-x86_64/time.h new file mode 100644 index 0000000000..40145ddb0f --- /dev/null +++ b/xen/include/asm-x86_64/time.h @@ -0,0 +1,23 @@ +/* -*- Mode:C; c-basic-offset:4; tab-width:4 -*- + **************************************************************************** + * (C) 2002 - Rolf Neugebauer - Intel Research Cambridge + **************************************************************************** + * + * File: time.h + * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk) + * + * Environment: Xen Hypervisor + * Description: Architecture dependent definition of time variables + */ + +#ifndef _ASM_TIME_H_ +#define _ASM_TIME_H_ + +#include <asm/types.h> +#include <asm/msr.h> + +typedef s64 s_time_t; /* system time */ + +extern int using_apic_timer; + +#endif /* _ASM_TIME_H_ */ diff --git a/xen/include/asm-x86_64/timex.h b/xen/include/asm-x86_64/timex.h new file mode 100644 index 0000000000..3eeb5d2b70 --- /dev/null +++ b/xen/include/asm-x86_64/timex.h @@ -0,0 +1,58 @@ +/* + * linux/include/asm-i386/timex.h + * + * i386 architecture timex specifications + */ +#ifndef _ASMi386_TIMEX_H +#define _ASMi386_TIMEX_H + +#include <linux/config.h> +#include <asm/msr.h> + +#ifdef CONFIG_MELAN +# define CLOCK_TICK_RATE 1189200 /* AMD Elan has different frequency! */ +#else +# define CLOCK_TICK_RATE 1193180 /* Underlying HZ */ +#endif + +#define CLOCK_TICK_FACTOR 20 /* Factor of both 1000000 and CLOCK_TICK_RATE */ +#define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \ + (1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \ + << (SHIFT_SCALE-SHIFT_HZ)) / HZ) + +/* + * Standard way to access the cycle counter on i586+ CPUs. + * Currently only used on SMP. + * + * If you really have a SMP machine with i486 chips or older, + * compile for that, and this will just always return zero. + * That's ok, it just means that the nicer scheduling heuristics + * won't work for you. + * + * We only use the low 32 bits, and we'd simply better make sure + * that we reschedule before that wraps. Scheduling at least every + * four billion cycles just basically sounds like a good idea, + * regardless of how fast the machine is. + */ +typedef unsigned long long cycles_t; + +extern cycles_t cacheflush_time; + +static inline cycles_t get_cycles (void) +{ +#ifndef CONFIG_X86_TSC + return 0; +#else + unsigned long long ret; + + rdtscll(ret); + return ret; +#endif +} + +extern unsigned long cpu_khz; + +#define vxtime_lock() do {} while (0) +#define vxtime_unlock() do {} while (0) + +#endif diff --git a/xen/include/asm-x86_64/types.h b/xen/include/asm-x86_64/types.h new file mode 100644 index 0000000000..2bd0f258b9 --- /dev/null +++ b/xen/include/asm-x86_64/types.h @@ -0,0 +1,50 @@ +#ifndef _I386_TYPES_H +#define _I386_TYPES_H + +typedef unsigned short umode_t; + +/* + * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the + * header files exported to user space + */ + +typedef __signed__ char __s8; +typedef unsigned char __u8; + +typedef __signed__ short __s16; +typedef unsigned short __u16; + +typedef __signed__ int __s32; +typedef unsigned int __u32; + +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +typedef __signed__ long long __s64; +typedef unsigned long long __u64; +#endif + +#include <xeno/config.h> + +typedef signed char s8; +typedef unsigned char u8; + +typedef signed short s16; +typedef unsigned short u16; + +typedef signed int s32; +typedef unsigned int u32; + +typedef signed long long s64; +typedef unsigned long long u64; + +#define BITS_PER_LONG 32 + +/* DMA addresses come in generic and 64-bit flavours. */ + +#ifdef CONFIG_HIGHMEM +typedef u64 dma_addr_t; +#else +typedef u32 dma_addr_t; +#endif +typedef u64 dma64_addr_t; + +#endif diff --git a/xen/include/asm-x86_64/uaccess.h b/xen/include/asm-x86_64/uaccess.h new file mode 100644 index 0000000000..ba19cfb2b3 --- /dev/null +++ b/xen/include/asm-x86_64/uaccess.h @@ -0,0 +1,600 @@ +#ifndef __i386_UACCESS_H +#define __i386_UACCESS_H + +/* + * User space memory access functions + */ +#include <linux/config.h> +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/prefetch.h> +#include <asm/page.h> + +#define VERIFY_READ 0 +#define VERIFY_WRITE 1 + +/* + * The fs value determines whether argument validity checking should be + * performed or not. If get_fs() == USER_DS, checking is performed, with + * get_fs() == KERNEL_DS, checking is bypassed. + * + * For historical reasons, these macros are grossly misnamed. + */ + +#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) + + +#define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF) +#define USER_DS MAKE_MM_SEG(PAGE_OFFSET) + +#define get_ds() (KERNEL_DS) +#define get_fs() (current->addr_limit) +#define set_fs(x) (current->addr_limit = (x)) + +#define segment_eq(a,b) ((a).seg == (b).seg) + +extern int __verify_write(const void *, unsigned long); + +#define __addr_ok(addr) ((unsigned long)(addr) < (current->addr_limit.seg)) + +/* + * Uhhuh, this needs 33-bit arithmetic. We have a carry.. + */ +#define __range_ok(addr,size) ({ \ + unsigned long flag,sum; \ + asm("addl %3,%1 ; sbbl %0,%0; cmpl %1,%4; sbbl $0,%0" \ + :"=&r" (flag), "=r" (sum) \ + :"1" (addr),"g" ((int)(size)),"g" (current->addr_limit.seg)); \ + flag; }) + +#define access_ok(type,addr,size) (__range_ok(addr,size) == 0) + +static inline int verify_area(int type, const void * addr, unsigned long size) +{ + return access_ok(type,addr,size) ? 0 : -EFAULT; +} + + +/* + * The exception table consists of pairs of addresses: the first is the + * address of an instruction that is allowed to fault, and the second is + * the address at which the program should continue. No registers are + * modified, so it is entirely up to the continuation code to figure out + * what to do. + * + * All the routines below use bits of fixup code that are out of line + * with the main instruction path. This means when everything is well, + * we don't even have to jump over them. Further, they do not intrude + * on our cache or tlb entries. + */ + +struct exception_table_entry +{ + unsigned long insn, fixup; +}; + +/* Returns 0 if exception not found and fixup otherwise. */ +extern unsigned long search_exception_table(unsigned long); + + +/* + * These are the main single-value transfer routines. They automatically + * use the right size if we just have the right pointer type. + * + * This gets kind of ugly. We want to return _two_ values in "get_user()" + * and yet we don't want to do any pointers, because that is too much + * of a performance impact. Thus we have a few rather ugly macros here, + * and hide all the uglyness from the user. + * + * The "__xxx" versions of the user access functions are versions that + * do not verify the address space, that must have been done previously + * with a separate "access_ok()" call (this is used when we do multiple + * accesses to the same area of user memory). + */ + +extern void __get_user_1(void); +extern void __get_user_2(void); +extern void __get_user_4(void); + +#define __get_user_x(size,ret,x,ptr) \ + __asm__ __volatile__("call __get_user_" #size \ + :"=a" (ret),"=d" (x) \ + :"0" (ptr)) + +/* Careful: we have to cast the result to the type of the pointer for sign reasons */ +#define get_user(x,ptr) \ +({ int __ret_gu=1,__val_gu; \ + switch(sizeof (*(ptr))) { \ + case 1: __ret_gu=copy_from_user(&__val_gu,ptr,1); break; \ + case 2: __ret_gu=copy_from_user(&__val_gu,ptr,2); break; \ + case 4: __ret_gu=copy_from_user(&__val_gu,ptr,4); break; \ + default: __ret_gu=copy_from_user(&__val_gu,ptr,8); break; \ + /*case 1: __get_user_x(1,__ret_gu,__val_gu,ptr); break;*/ \ + /*case 2: __get_user_x(2,__ret_gu,__val_gu,ptr); break;*/ \ + /*case 4: __get_user_x(4,__ret_gu,__val_gu,ptr); break;*/ \ + /*default: __get_user_x(X,__ret_gu,__val_gu,ptr); break;*/ \ + } \ + (x) = (__typeof__(*(ptr)))__val_gu; \ + __ret_gu; \ +}) + +extern void __put_user_1(void); +extern void __put_user_2(void); +extern void __put_user_4(void); +extern void __put_user_8(void); + +extern void __put_user_bad(void); + +#define put_user(x,ptr) \ + __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) + +#define __get_user(x,ptr) \ + __get_user_nocheck((x),(ptr),sizeof(*(ptr))) +#define __put_user(x,ptr) \ + __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) + +#define __put_user_nocheck(x,ptr,size) \ +({ \ + long __pu_err; \ + __put_user_size((x),(ptr),(size),__pu_err); \ + __pu_err; \ +}) + + +#define __put_user_check(x,ptr,size) \ +({ \ + long __pu_err = -EFAULT; \ + __typeof__(*(ptr)) *__pu_addr = (ptr); \ + if (access_ok(VERIFY_WRITE,__pu_addr,size)) \ + __put_user_size((x),__pu_addr,(size),__pu_err); \ + __pu_err; \ +}) + +#define __put_user_u64(x, addr, err) \ + __asm__ __volatile__( \ + "1: movl %%eax,0(%2)\n" \ + "2: movl %%edx,4(%2)\n" \ + "3:\n" \ + ".section .fixup,\"ax\"\n" \ + "4: movl %3,%0\n" \ + " jmp 3b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 1b,4b\n" \ + " .long 2b,4b\n" \ + ".previous" \ + : "=r"(err) \ + : "A" (x), "r" (addr), "i"(-EFAULT), "0"(err)) + +#define __put_user_size(x,ptr,size,retval) \ +do { \ + retval = 0; \ + switch (size) { \ + case 1: __put_user_asm(x,ptr,retval,"b","b","iq"); break; \ + case 2: __put_user_asm(x,ptr,retval,"w","w","ir"); break; \ + case 4: __put_user_asm(x,ptr,retval,"l","","ir"); break; \ + case 8: __put_user_u64(x,ptr,retval); break; \ + default: __put_user_bad(); \ + } \ +} while (0) + +struct __large_struct { unsigned long buf[100]; }; +#define __m(x) (*(struct __large_struct *)(x)) + +/* + * Tell gcc we read from memory instead of writing: this is because + * we do not write to any memory gcc knows about, so there are no + * aliasing issues. + */ +#define __put_user_asm(x, addr, err, itype, rtype, ltype) \ + __asm__ __volatile__( \ + "1: mov"itype" %"rtype"1,%2\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: movl %3,%0\n" \ + " jmp 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 1b,3b\n" \ + ".previous" \ + : "=r"(err) \ + : ltype (x), "m"(__m(addr)), "i"(-EFAULT), "0"(err)) + + +#define __get_user_nocheck(x,ptr,size) \ +({ \ + long __gu_err, __gu_val; \ + __get_user_size(__gu_val,(ptr),(size),__gu_err); \ + (x) = (__typeof__(*(ptr)))__gu_val; \ + __gu_err; \ +}) + +extern long __get_user_bad(void); + +#define __get_user_size(x,ptr,size,retval) \ +do { \ + retval = 0; \ + switch (size) { \ + case 1: __get_user_asm(x,ptr,retval,"b","b","=q"); break; \ + case 2: __get_user_asm(x,ptr,retval,"w","w","=r"); break; \ + case 4: __get_user_asm(x,ptr,retval,"l","","=r"); break; \ + default: (x) = __get_user_bad(); \ + } \ +} while (0) + +#define __get_user_asm(x, addr, err, itype, rtype, ltype) \ + __asm__ __volatile__( \ + "1: mov"itype" %2,%"rtype"1\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: movl %3,%0\n" \ + " xor"itype" %"rtype"1,%"rtype"1\n" \ + " jmp 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 1b,3b\n" \ + ".previous" \ + : "=r"(err), ltype (x) \ + : "m"(__m(addr)), "i"(-EFAULT), "0"(err)) + + +/* + * Copy To/From Userspace + */ + +/* Generic arbitrary sized copy. */ +#define __copy_user(to,from,size) \ +do { \ + int __d0, __d1; \ + __asm__ __volatile__( \ + "0: rep; movsl\n" \ + " movl %3,%0\n" \ + "1: rep; movsb\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: lea 0(%3,%0,4),%0\n" \ + " jmp 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 0b,3b\n" \ + " .long 1b,2b\n" \ + ".previous" \ + : "=&c"(size), "=&D" (__d0), "=&S" (__d1) \ + : "r"(size & 3), "0"(size / 4), "1"(to), "2"(from) \ + : "memory"); \ +} while (0) + +#define __copy_user_zeroing(to,from,size) \ +do { \ + int __d0, __d1; \ + __asm__ __volatile__( \ + "0: rep; movsl\n" \ + " movl %3,%0\n" \ + "1: rep; movsb\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: lea 0(%3,%0,4),%0\n" \ + "4: pushl %0\n" \ + " pushl %%eax\n" \ + " xorl %%eax,%%eax\n" \ + " rep; stosb\n" \ + " popl %%eax\n" \ + " popl %0\n" \ + " jmp 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 0b,3b\n" \ + " .long 1b,4b\n" \ + ".previous" \ + : "=&c"(size), "=&D" (__d0), "=&S" (__d1) \ + : "r"(size & 3), "0"(size / 4), "1"(to), "2"(from) \ + : "memory"); \ +} while (0) + +/* We let the __ versions of copy_from/to_user inline, because they're often + * used in fast paths and have only a small space overhead. + */ +static inline unsigned long +__generic_copy_from_user_nocheck(void *to, const void *from, unsigned long n) +{ + __copy_user_zeroing(to,from,n); + return n; +} + +static inline unsigned long +__generic_copy_to_user_nocheck(void *to, const void *from, unsigned long n) +{ + __copy_user(to,from,n); + return n; +} + + +/* Optimize just a little bit when we know the size of the move. */ +#define __constant_copy_user(to, from, size) \ +do { \ + int __d0, __d1; \ + switch (size & 3) { \ + default: \ + __asm__ __volatile__( \ + "0: rep; movsl\n" \ + "1:\n" \ + ".section .fixup,\"ax\"\n" \ + "2: shl $2,%0\n" \ + " jmp 1b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 0b,2b\n" \ + ".previous" \ + : "=c"(size), "=&S" (__d0), "=&D" (__d1)\ + : "1"(from), "2"(to), "0"(size/4) \ + : "memory"); \ + break; \ + case 1: \ + __asm__ __volatile__( \ + "0: rep; movsl\n" \ + "1: movsb\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: shl $2,%0\n" \ + "4: incl %0\n" \ + " jmp 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 0b,3b\n" \ + " .long 1b,4b\n" \ + ".previous" \ + : "=c"(size), "=&S" (__d0), "=&D" (__d1)\ + : "1"(from), "2"(to), "0"(size/4) \ + : "memory"); \ + break; \ + case 2: \ + __asm__ __volatile__( \ + "0: rep; movsl\n" \ + "1: movsw\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: shl $2,%0\n" \ + "4: addl $2,%0\n" \ + " jmp 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 0b,3b\n" \ + " .long 1b,4b\n" \ + ".previous" \ + : "=c"(size), "=&S" (__d0), "=&D" (__d1)\ + : "1"(from), "2"(to), "0"(size/4) \ + : "memory"); \ + break; \ + case 3: \ + __asm__ __volatile__( \ + "0: rep; movsl\n" \ + "1: movsw\n" \ + "2: movsb\n" \ + "3:\n" \ + ".section .fixup,\"ax\"\n" \ + "4: shl $2,%0\n" \ + "5: addl $2,%0\n" \ + "6: incl %0\n" \ + " jmp 3b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 0b,4b\n" \ + " .long 1b,5b\n" \ + " .long 2b,6b\n" \ + ".previous" \ + : "=c"(size), "=&S" (__d0), "=&D" (__d1)\ + : "1"(from), "2"(to), "0"(size/4) \ + : "memory"); \ + break; \ + } \ +} while (0) + +/* Optimize just a little bit when we know the size of the move. */ +#define __constant_copy_user_zeroing(to, from, size) \ +do { \ + int __d0, __d1; \ + switch (size & 3) { \ + default: \ + __asm__ __volatile__( \ + "0: rep; movsl\n" \ + "1:\n" \ + ".section .fixup,\"ax\"\n" \ + "2: pushl %0\n" \ + " pushl %%eax\n" \ + " xorl %%eax,%%eax\n" \ + " rep; stosl\n" \ + " popl %%eax\n" \ + " popl %0\n" \ + " shl $2,%0\n" \ + " jmp 1b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 0b,2b\n" \ + ".previous" \ + : "=c"(size), "=&S" (__d0), "=&D" (__d1)\ + : "1"(from), "2"(to), "0"(size/4) \ + : "memory"); \ + break; \ + case 1: \ + __asm__ __volatile__( \ + "0: rep; movsl\n" \ + "1: movsb\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: pushl %0\n" \ + " pushl %%eax\n" \ + " xorl %%eax,%%eax\n" \ + " rep; stosl\n" \ + " stosb\n" \ + " popl %%eax\n" \ + " popl %0\n" \ + " shl $2,%0\n" \ + " incl %0\n" \ + " jmp 2b\n" \ + "4: pushl %%eax\n" \ + " xorl %%eax,%%eax\n" \ + " stosb\n" \ + " popl %%eax\n" \ + " incl %0\n" \ + " jmp 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 0b,3b\n" \ + " .long 1b,4b\n" \ + ".previous" \ + : "=c"(size), "=&S" (__d0), "=&D" (__d1)\ + : "1"(from), "2"(to), "0"(size/4) \ + : "memory"); \ + break; \ + case 2: \ + __asm__ __volatile__( \ + "0: rep; movsl\n" \ + "1: movsw\n" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3: pushl %0\n" \ + " pushl %%eax\n" \ + " xorl %%eax,%%eax\n" \ + " rep; stosl\n" \ + " stosw\n" \ + " popl %%eax\n" \ + " popl %0\n" \ + " shl $2,%0\n" \ + " addl $2,%0\n" \ + " jmp 2b\n" \ + "4: pushl %%eax\n" \ + " xorl %%eax,%%eax\n" \ + " stosw\n" \ + " popl %%eax\n" \ + " addl $2,%0\n" \ + " jmp 2b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 0b,3b\n" \ + " .long 1b,4b\n" \ + ".previous" \ + : "=c"(size), "=&S" (__d0), "=&D" (__d1)\ + : "1"(from), "2"(to), "0"(size/4) \ + : "memory"); \ + break; \ + case 3: \ + __asm__ __volatile__( \ + "0: rep; movsl\n" \ + "1: movsw\n" \ + "2: movsb\n" \ + "3:\n" \ + ".section .fixup,\"ax\"\n" \ + "4: pushl %0\n" \ + " pushl %%eax\n" \ + " xorl %%eax,%%eax\n" \ + " rep; stosl\n" \ + " stosw\n" \ + " stosb\n" \ + " popl %%eax\n" \ + " popl %0\n" \ + " shl $2,%0\n" \ + " addl $3,%0\n" \ + " jmp 2b\n" \ + "5: pushl %%eax\n" \ + " xorl %%eax,%%eax\n" \ + " stosw\n" \ + " stosb\n" \ + " popl %%eax\n" \ + " addl $3,%0\n" \ + " jmp 2b\n" \ + "6: pushl %%eax\n" \ + " xorl %%eax,%%eax\n" \ + " stosb\n" \ + " popl %%eax\n" \ + " incl %0\n" \ + " jmp 3b\n" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n" \ + " .align 4\n" \ + " .long 0b,4b\n" \ + " .long 1b,5b\n" \ + " .long 2b,6b\n" \ + ".previous" \ + : "=c"(size), "=&S" (__d0), "=&D" (__d1)\ + : "1"(from), "2"(to), "0"(size/4) \ + : "memory"); \ + break; \ + } \ +} while (0) + +unsigned long __generic_copy_to_user(void *, const void *, unsigned long); +unsigned long __generic_copy_from_user(void *, const void *, unsigned long); + +static inline unsigned long +__constant_copy_to_user(void *to, const void *from, unsigned long n) +{ + prefetch(from); + if (access_ok(VERIFY_WRITE, to, n)) + __constant_copy_user(to,from,n); + return n; +} + +static inline unsigned long +__constant_copy_from_user(void *to, const void *from, unsigned long n) +{ + if (access_ok(VERIFY_READ, from, n)) + __constant_copy_user_zeroing(to,from,n); + else + memset(to, 0, n); + return n; +} + +static inline unsigned long +__constant_copy_to_user_nocheck(void *to, const void *from, unsigned long n) +{ + __constant_copy_user(to,from,n); + return n; +} + +static inline unsigned long +__constant_copy_from_user_nocheck(void *to, const void *from, unsigned long n) +{ + __constant_copy_user_zeroing(to,from,n); + return n; +} + +#define copy_to_user(to,from,n) \ + (__builtin_constant_p(n) ? \ + __constant_copy_to_user((to),(from),(n)) : \ + __generic_copy_to_user((to),(from),(n))) + +#define copy_from_user(to,from,n) \ + (__builtin_constant_p(n) ? \ + __constant_copy_from_user((to),(from),(n)) : \ + __generic_copy_from_user((to),(from),(n))) + +#define __copy_to_user(to,from,n) \ + (__builtin_constant_p(n) ? \ + __constant_copy_to_user_nocheck((to),(from),(n)) : \ + __generic_copy_to_user_nocheck((to),(from),(n))) + +#define __copy_from_user(to,from,n) \ + (__builtin_constant_p(n) ? \ + __constant_copy_from_user_nocheck((to),(from),(n)) : \ + __generic_copy_from_user_nocheck((to),(from),(n))) + +long strncpy_from_user(char *dst, const char *src, long count); +long __strncpy_from_user(char *dst, const char *src, long count); +#define strlen_user(str) strnlen_user(str, ~0UL >> 1) +long strnlen_user(const char *str, long n); +unsigned long clear_user(void *mem, unsigned long len); +unsigned long __clear_user(void *mem, unsigned long len); + +#endif /* __i386_UACCESS_H */ diff --git a/xen/include/asm-x86_64/unaligned.h b/xen/include/asm-x86_64/unaligned.h new file mode 100644 index 0000000000..7acd795762 --- /dev/null +++ b/xen/include/asm-x86_64/unaligned.h @@ -0,0 +1,37 @@ +#ifndef __I386_UNALIGNED_H +#define __I386_UNALIGNED_H + +/* + * The i386 can do unaligned accesses itself. + * + * The strange macros are there to make sure these can't + * be misused in a way that makes them not work on other + * architectures where unaligned accesses aren't as simple. + */ + +/** + * get_unaligned - get value from possibly mis-aligned location + * @ptr: pointer to value + * + * This macro should be used for accessing values larger in size than + * single bytes at locations that are expected to be improperly aligned, + * e.g. retrieving a u16 value from a location not u16-aligned. + * + * Note that unaligned accesses can be very expensive on some architectures. + */ +#define get_unaligned(ptr) (*(ptr)) + +/** + * put_unaligned - put value to a possibly mis-aligned location + * @val: value to place + * @ptr: pointer to location + * + * This macro should be used for placing values larger in size than + * single bytes at locations that are expected to be improperly aligned, + * e.g. writing a u16 value to a location not u16-aligned. + * + * Note that unaligned accesses can be very expensive on some architectures. + */ +#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) )) + +#endif diff --git a/xen/include/hypervisor-ifs/if-i386/hypervisor-if-arch.h b/xen/include/hypervisor-ifs/if-i386/hypervisor-if-arch.h new file mode 100644 index 0000000000..ee950c01e1 --- /dev/null +++ b/xen/include/hypervisor-ifs/if-i386/hypervisor-if-arch.h @@ -0,0 +1,352 @@ +/****************************************************************************** + * hypervisor-if.h + * + * Interface to Xeno hypervisor. + */ + +#ifndef __HYPERVISOR_IF_H__ +#define __HYPERVISOR_IF_H__ + +/* + * SEGMENT DESCRIPTOR TABLES + */ +/* + * A number of GDT entries are reserved by Xen. These are not situated at the + * start of the GDT because some stupid OSes export hard-coded selector values + * in their ABI. These hard-coded values are always near the start of the GDT, + * so Xen places itself out of the way. + * + * NB. The reserved range is inclusive (that is, both FIRST_RESERVED_GDT_ENTRY + * and LAST_RESERVED_GDT_ENTRY are reserved). + */ +#define NR_RESERVED_GDT_ENTRIES 40 +#define FIRST_RESERVED_GDT_ENTRY 256 +#define LAST_RESERVED_GDT_ENTRY \ + (FIRST_RESERVED_GDT_ENTRY + NR_RESERVED_GDT_ENTRIES - 1) + +/* + * These flat segments are in the Xen-private section of every GDT. Since these + * are also present in the initial GDT, many OSes will be able to avoid + * installing their own GDT. + */ +#define FLAT_RING1_CS 0x0819 /* GDT index 259 */ +#define FLAT_RING1_DS 0x0821 /* GDT index 260 */ +#define FLAT_RING3_CS 0x082b /* GDT index 261 */ +#define FLAT_RING3_DS 0x0833 /* GDT index 262 */ + + +/* + * HYPERVISOR "SYSTEM CALLS" + */ + +/* EAX = vector; EBX, ECX, EDX, ESI, EDI = args 1, 2, 3, 4, 5. */ +#define __HYPERVISOR_set_trap_table 0 +#define __HYPERVISOR_mmu_update 1 +#define __HYPERVISOR_console_write 2 /* DEPRECATED */ +#define __HYPERVISOR_set_gdt 3 +#define __HYPERVISOR_stack_switch 4 +#define __HYPERVISOR_set_callbacks 5 +#define __HYPERVISOR_net_io_op 6 +#define __HYPERVISOR_fpu_taskswitch 7 +#define __HYPERVISOR_sched_op 8 +#define __HYPERVISOR_dom0_op 9 +#define __HYPERVISOR_network_op 10 +#define __HYPERVISOR_block_io_op 11 +#define __HYPERVISOR_set_debugreg 12 +#define __HYPERVISOR_get_debugreg 13 +#define __HYPERVISOR_update_descriptor 14 +#define __HYPERVISOR_set_fast_trap 15 +#define __HYPERVISOR_dom_mem_op 16 +#define __HYPERVISOR_multicall 17 +#define __HYPERVISOR_kbd_op 18 +#define __HYPERVISOR_update_va_mapping 19 +#define __HYPERVISOR_set_timer_op 20 +#define __HYPERVISOR_event_channel_op 21 +#define __HYPERVISOR_xen_version 22 +#define __HYPERVISOR_serial_io 23 + +/* And the trap vector is... */ +#define TRAP_INSTR "int $0x82" + + +/* + * MULTICALLS + * + * Multicalls are listed in an array, with each element being a fixed size + * (BYTES_PER_MULTICALL_ENTRY). Each is of the form (op, arg1, ..., argN) + * where each element of the tuple is a machine word. + */ +#define BYTES_PER_MULTICALL_ENTRY 32 + + +/* EVENT MESSAGES + * + * Here, as in the interrupts to the guestos, additional network interfaces + * are defined. These definitions server as placeholders for the event bits, + * however, in the code these events will allways be referred to as shifted + * offsets from the base NET events. + */ + +/* Events that a guest OS may receive from the hypervisor. */ +#define EVENT_BLKDEV 0x01 /* A block device response has been queued. */ +#define EVENT_TIMER 0x02 /* A timeout has been updated. */ +#define EVENT_DIE 0x04 /* OS is about to be killed. Clean up please! */ +#define EVENT_DEBUG 0x08 /* Request guest to dump debug info (gross!) */ +#define EVENT_NET 0x10 /* There are packets for transmission. */ +#define EVENT_PS2 0x20 /* PS/2 keyboard or mouse event(s) */ +#define EVENT_STOP 0x40 /* Prepare for stopping and possible pickling */ +#define EVENT_EVTCHN 0x80 /* Event pending on an event channel */ +#define EVENT_VBD_UPD 0x100 /* Event to signal VBDs should be reprobed */ + +/* Bit offsets, as opposed to the above masks. */ +#define _EVENT_BLKDEV 0 +#define _EVENT_TIMER 1 +#define _EVENT_DIE 2 +#define _EVENT_DEBUG 3 +#define _EVENT_NET 4 +#define _EVENT_PS2 5 +#define _EVENT_STOP 6 +#define _EVENT_EVTCHN 7 +#define _EVENT_VBD_UPD 8 +#define _EVENT_CONSOLE 9 /* This is only for domain-0 initial console. */ + +/* + * Virtual addresses beyond this are not modifiable by guest OSes. The + * machine->physical mapping table starts at this address, read-only. + */ +#define HYPERVISOR_VIRT_START (0xFC000000UL) +#ifndef machine_to_phys_mapping +#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START) +#endif + + +/* + * MMU_XXX: specified in least 2 bits of 'ptr' field. These bits are masked + * off to get the real 'ptr' value. + * All requests specify relevent address in 'ptr'. This is either a + * machine/physical address (MA), or linear/virtual address (VA). + * Normal requests specify update value in 'value'. + * Extended requests specify command in least 8 bits of 'value'. These bits + * are masked off to get the real 'val' value. Except for MMUEXT_SET_LDT + * which shifts the least bits out. + */ +/* A normal page-table update request. */ +#define MMU_NORMAL_PT_UPDATE 0 /* checked '*ptr = val'. ptr is MA. */ +/* Update an entry in the machine->physical mapping table. */ +#define MMU_MACHPHYS_UPDATE 2 /* ptr = MA of frame to modify entry for */ +/* An extended command. */ +#define MMU_EXTENDED_COMMAND 3 /* least 8 bits of val demux further */ +/* Extended commands: */ +#define MMUEXT_PIN_L1_TABLE 0 /* ptr = MA of frame to pin */ +#define MMUEXT_PIN_L2_TABLE 1 /* ptr = MA of frame to pin */ +#define MMUEXT_PIN_L3_TABLE 2 /* ptr = MA of frame to pin */ +#define MMUEXT_PIN_L4_TABLE 3 /* ptr = MA of frame to pin */ +#define MMUEXT_UNPIN_TABLE 4 /* ptr = MA of frame to unpin */ +#define MMUEXT_NEW_BASEPTR 5 /* ptr = MA of new pagetable base */ +#define MMUEXT_TLB_FLUSH 6 /* ptr = NULL */ +#define MMUEXT_INVLPG 7 /* ptr = NULL ; val = VA to invalidate */ +#define MMUEXT_SET_LDT 8 /* ptr = VA of table; val = # entries */ +/* NB. MMUEXT_SET_SUBJECTDOM must consist of *_L followed immediately by *_H */ +#define MMUEXT_SET_SUBJECTDOM_L 9 /* (ptr[31:15],val[31:15]) = dom[31:0] */ +#define MMUEXT_SET_SUBJECTDOM_H 10 /* (ptr[31:15],val[31:15]) = dom[63:32] */ +#define MMUEXT_CMD_MASK 255 +#define MMUEXT_CMD_SHIFT 8 + +/* These are passed as 'flags' to update_va_mapping. They can be ORed. */ +#define UVMF_FLUSH_TLB 1 /* Flush entire TLB. */ +#define UVMF_INVLPG 2 /* Flush the VA mapping being updated. */ + +/* + * Master "switch" for enabling/disabling event delivery. + */ +#define EVENTS_MASTER_ENABLE_MASK 0x80000000UL +#define EVENTS_MASTER_ENABLE_BIT 31 + + +/* + * SCHEDOP_* - Scheduler hypercall operations. + */ +#define SCHEDOP_yield 0 /* Give up the CPU voluntarily. */ +#define SCHEDOP_block 1 /* Block until an event is received. */ +#define SCHEDOP_exit 3 /* Exit and kill this domain. */ +#define SCHEDOP_stop 4 /* Stop executing this domain. */ + +/* + * Commands to HYPERVISOR_serial_io(). + */ +#define SERIALIO_write 0 +#define SERIALIO_read 1 + +#ifndef __ASSEMBLY__ + +typedef u64 domid_t; +/* DOMID_SELF is used in certain contexts to refer to oneself. */ +#define DOMID_SELF (~1ULL) + +#include "network.h" +#include "block.h" + +/* + * Send an array of these to HYPERVISOR_set_trap_table() + */ +#define TI_GET_DPL(_ti) ((_ti)->flags & 3) +#define TI_GET_IF(_ti) ((_ti)->flags & 4) +#define TI_SET_DPL(_ti,_dpl) ((_ti)->flags |= (_dpl)) +#define TI_SET_IF(_ti,_if) ((_ti)->flags |= ((!!(_if))<<2)) +typedef struct trap_info_st +{ + unsigned char vector; /* exception vector */ + unsigned char flags; /* 0-3: privilege level; 4: clear event enable? */ + unsigned short cs; /* code selector */ + unsigned long address; /* code address */ +} trap_info_t; + +/* + * Send an array of these to HYPERVISOR_mmu_update() + */ +typedef struct +{ + unsigned long ptr, val; /* *ptr = val */ +} mmu_update_t; + +/* + * Send an array of these to HYPERVISOR_multicall() + */ +typedef struct +{ + unsigned long op; + unsigned long args[7]; +} multicall_entry_t; + +typedef struct +{ + unsigned long ebx; + unsigned long ecx; + unsigned long edx; + unsigned long esi; + unsigned long edi; + unsigned long ebp; + unsigned long eax; + unsigned long ds; + unsigned long es; + unsigned long fs; + unsigned long gs; + unsigned long _unused; + unsigned long eip; + unsigned long cs; + unsigned long eflags; + unsigned long esp; + unsigned long ss; +} execution_context_t; + +/* + * Xen/guestos shared data -- pointer provided in start_info. + * NB. We expect that this struct is smaller than a page. + */ +typedef struct shared_info_st { + + /* Bitmask of outstanding event notifications hypervisor -> guest OS. */ + unsigned long events; + /* + * Hypervisor will only signal event delivery via the "callback exception" + * when a pending event is not masked. The mask also contains a "master + * enable" which prevents any event delivery. This mask can be used to + * prevent unbounded reentrancy and stack overflow (in this way, acts as a + * kind of interrupt-enable flag). + */ + unsigned long events_mask; + + /* + * A domain can have up to 1024 bidirectional event channels to/from other + * domains. Domains must agree out-of-band to set up a connection, and then + * each must explicitly request a connection to the other. When both have + * made the request the channel is fully allocated and set up. + * + * An event channel is a single sticky 'bit' of information. Setting the + * sticky bit also causes an upcall into the target domain. In this way + * events can be seen as an IPI [Inter-Process(or) Interrupt]. + * + * A guest can see which of its event channels are pending by reading the + * 'event_channel_pend' bitfield. To avoid a linear scan of the entire + * bitfield there is a 'selector' which indicates which words in the + * bitfield contain at least one set bit. + * + * There is a similar bitfield to indicate which event channels have been + * disconnected by the remote end. There is also a 'selector' for this + * field. + */ + u32 event_channel_pend[32]; + u32 event_channel_pend_sel; + u32 event_channel_disc[32]; + u32 event_channel_disc_sel; + + /* + * Time: The following abstractions are exposed: System Time, Clock Time, + * Domain Virtual Time. Domains can access Cycle counter time directly. + */ + + unsigned int rdtsc_bitshift; /* tsc_timestamp uses N:N+31 of TSC. */ + u64 cpu_freq; /* CPU frequency (Hz). */ + + /* + * The following values are updated periodically (and not necessarily + * atomically!). The guest OS detects this because 'time_version1' is + * incremented just before updating these values, and 'time_version2' is + * incremented immediately after. See Xenolinux code for an example of how + * to read these values safely (arch/xeno/kernel/time.c). + */ + unsigned long time_version1; /* A version number for info below. */ + unsigned long time_version2; /* A version number for info below. */ + unsigned long tsc_timestamp; /* TSC at last update of time vals. */ + u64 system_time; /* Time, in nanosecs, since boot. */ + unsigned long wc_sec; /* Secs 00:00:00 UTC, Jan 1, 1970. */ + unsigned long wc_usec; /* Usecs 00:00:00 UTC, Jan 1, 1970. */ + + /* Domain Virtual Time */ + u64 domain_time; + + /* + * Timeout values: + * Allow a domain to specify a timeout value in system time and + * domain virtual time. + */ + u64 wall_timeout; + u64 domain_timeout; + + /* + * The index structures are all stored here for convenience. The rings + * themselves are allocated by Xen but the guestos must create its own + * mapping -- the machine address is given in the startinfo structure to + * allow this to happen. + */ + net_idx_t net_idx[MAX_DOMAIN_VIFS]; + + execution_context_t execution_context; + +} shared_info_t; + +/* + * NB. We expect that this struct is smaller than a page. + */ +typedef struct start_info_st { + /* THE FOLLOWING ARE FILLED IN BOTH ON INITIAL BOOT AND ON RESUME. */ + unsigned long nr_pages; /* total pages allocated to this domain. */ + unsigned long shared_info; /* MACHINE address of shared info struct.*/ + unsigned long flags; /* SIF_xxx flags. */ + /* THE FOLLOWING ARE ONLY FILLED IN ON INITIAL BOOT (NOT RESUME). */ + unsigned long pt_base; /* VIRTUAL address of page directory. */ + unsigned long mod_start; /* VIRTUAL address of pre-loaded module. */ + unsigned long mod_len; /* Size (bytes) of pre-loaded module. */ + unsigned char cmd_line[1]; /* Variable-length options. */ +} start_info_t; + +/* These flags are passed in the 'flags' field of start_info_t. */ +#define SIF_PRIVILEGED 1 /* Is the domain privileged? */ +#define SIF_INITDOMAIN 2 /* Is thsi the initial control domain? */ + +/* For use in guest OSes. */ +extern shared_info_t *HYPERVISOR_shared_info; + +#endif /* !__ASSEMBLY__ */ + +#endif /* __HYPERVISOR_IF_H__ */ diff --git a/xen/include/hypervisor-ifs/if-x86_64/hypervisor-if-arch.h b/xen/include/hypervisor-ifs/if-x86_64/hypervisor-if-arch.h new file mode 100644 index 0000000000..ee950c01e1 --- /dev/null +++ b/xen/include/hypervisor-ifs/if-x86_64/hypervisor-if-arch.h @@ -0,0 +1,352 @@ +/****************************************************************************** + * hypervisor-if.h + * + * Interface to Xeno hypervisor. + */ + +#ifndef __HYPERVISOR_IF_H__ +#define __HYPERVISOR_IF_H__ + +/* + * SEGMENT DESCRIPTOR TABLES + */ +/* + * A number of GDT entries are reserved by Xen. These are not situated at the + * start of the GDT because some stupid OSes export hard-coded selector values + * in their ABI. These hard-coded values are always near the start of the GDT, + * so Xen places itself out of the way. + * + * NB. The reserved range is inclusive (that is, both FIRST_RESERVED_GDT_ENTRY + * and LAST_RESERVED_GDT_ENTRY are reserved). + */ +#define NR_RESERVED_GDT_ENTRIES 40 +#define FIRST_RESERVED_GDT_ENTRY 256 +#define LAST_RESERVED_GDT_ENTRY \ + (FIRST_RESERVED_GDT_ENTRY + NR_RESERVED_GDT_ENTRIES - 1) + +/* + * These flat segments are in the Xen-private section of every GDT. Since these + * are also present in the initial GDT, many OSes will be able to avoid + * installing their own GDT. + */ +#define FLAT_RING1_CS 0x0819 /* GDT index 259 */ +#define FLAT_RING1_DS 0x0821 /* GDT index 260 */ +#define FLAT_RING3_CS 0x082b /* GDT index 261 */ +#define FLAT_RING3_DS 0x0833 /* GDT index 262 */ + + +/* + * HYPERVISOR "SYSTEM CALLS" + */ + +/* EAX = vector; EBX, ECX, EDX, ESI, EDI = args 1, 2, 3, 4, 5. */ +#define __HYPERVISOR_set_trap_table 0 +#define __HYPERVISOR_mmu_update 1 +#define __HYPERVISOR_console_write 2 /* DEPRECATED */ +#define __HYPERVISOR_set_gdt 3 +#define __HYPERVISOR_stack_switch 4 +#define __HYPERVISOR_set_callbacks 5 +#define __HYPERVISOR_net_io_op 6 +#define __HYPERVISOR_fpu_taskswitch 7 +#define __HYPERVISOR_sched_op 8 +#define __HYPERVISOR_dom0_op 9 +#define __HYPERVISOR_network_op 10 +#define __HYPERVISOR_block_io_op 11 +#define __HYPERVISOR_set_debugreg 12 +#define __HYPERVISOR_get_debugreg 13 +#define __HYPERVISOR_update_descriptor 14 +#define __HYPERVISOR_set_fast_trap 15 +#define __HYPERVISOR_dom_mem_op 16 +#define __HYPERVISOR_multicall 17 +#define __HYPERVISOR_kbd_op 18 +#define __HYPERVISOR_update_va_mapping 19 +#define __HYPERVISOR_set_timer_op 20 +#define __HYPERVISOR_event_channel_op 21 +#define __HYPERVISOR_xen_version 22 +#define __HYPERVISOR_serial_io 23 + +/* And the trap vector is... */ +#define TRAP_INSTR "int $0x82" + + +/* + * MULTICALLS + * + * Multicalls are listed in an array, with each element being a fixed size + * (BYTES_PER_MULTICALL_ENTRY). Each is of the form (op, arg1, ..., argN) + * where each element of the tuple is a machine word. + */ +#define BYTES_PER_MULTICALL_ENTRY 32 + + +/* EVENT MESSAGES + * + * Here, as in the interrupts to the guestos, additional network interfaces + * are defined. These definitions server as placeholders for the event bits, + * however, in the code these events will allways be referred to as shifted + * offsets from the base NET events. + */ + +/* Events that a guest OS may receive from the hypervisor. */ +#define EVENT_BLKDEV 0x01 /* A block device response has been queued. */ +#define EVENT_TIMER 0x02 /* A timeout has been updated. */ +#define EVENT_DIE 0x04 /* OS is about to be killed. Clean up please! */ +#define EVENT_DEBUG 0x08 /* Request guest to dump debug info (gross!) */ +#define EVENT_NET 0x10 /* There are packets for transmission. */ +#define EVENT_PS2 0x20 /* PS/2 keyboard or mouse event(s) */ +#define EVENT_STOP 0x40 /* Prepare for stopping and possible pickling */ +#define EVENT_EVTCHN 0x80 /* Event pending on an event channel */ +#define EVENT_VBD_UPD 0x100 /* Event to signal VBDs should be reprobed */ + +/* Bit offsets, as opposed to the above masks. */ +#define _EVENT_BLKDEV 0 +#define _EVENT_TIMER 1 +#define _EVENT_DIE 2 +#define _EVENT_DEBUG 3 +#define _EVENT_NET 4 +#define _EVENT_PS2 5 +#define _EVENT_STOP 6 +#define _EVENT_EVTCHN 7 +#define _EVENT_VBD_UPD 8 +#define _EVENT_CONSOLE 9 /* This is only for domain-0 initial console. */ + +/* + * Virtual addresses beyond this are not modifiable by guest OSes. The + * machine->physical mapping table starts at this address, read-only. + */ +#define HYPERVISOR_VIRT_START (0xFC000000UL) +#ifndef machine_to_phys_mapping +#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START) +#endif + + +/* + * MMU_XXX: specified in least 2 bits of 'ptr' field. These bits are masked + * off to get the real 'ptr' value. + * All requests specify relevent address in 'ptr'. This is either a + * machine/physical address (MA), or linear/virtual address (VA). + * Normal requests specify update value in 'value'. + * Extended requests specify command in least 8 bits of 'value'. These bits + * are masked off to get the real 'val' value. Except for MMUEXT_SET_LDT + * which shifts the least bits out. + */ +/* A normal page-table update request. */ +#define MMU_NORMAL_PT_UPDATE 0 /* checked '*ptr = val'. ptr is MA. */ +/* Update an entry in the machine->physical mapping table. */ +#define MMU_MACHPHYS_UPDATE 2 /* ptr = MA of frame to modify entry for */ +/* An extended command. */ +#define MMU_EXTENDED_COMMAND 3 /* least 8 bits of val demux further */ +/* Extended commands: */ +#define MMUEXT_PIN_L1_TABLE 0 /* ptr = MA of frame to pin */ +#define MMUEXT_PIN_L2_TABLE 1 /* ptr = MA of frame to pin */ +#define MMUEXT_PIN_L3_TABLE 2 /* ptr = MA of frame to pin */ +#define MMUEXT_PIN_L4_TABLE 3 /* ptr = MA of frame to pin */ +#define MMUEXT_UNPIN_TABLE 4 /* ptr = MA of frame to unpin */ +#define MMUEXT_NEW_BASEPTR 5 /* ptr = MA of new pagetable base */ +#define MMUEXT_TLB_FLUSH 6 /* ptr = NULL */ +#define MMUEXT_INVLPG 7 /* ptr = NULL ; val = VA to invalidate */ +#define MMUEXT_SET_LDT 8 /* ptr = VA of table; val = # entries */ +/* NB. MMUEXT_SET_SUBJECTDOM must consist of *_L followed immediately by *_H */ +#define MMUEXT_SET_SUBJECTDOM_L 9 /* (ptr[31:15],val[31:15]) = dom[31:0] */ +#define MMUEXT_SET_SUBJECTDOM_H 10 /* (ptr[31:15],val[31:15]) = dom[63:32] */ +#define MMUEXT_CMD_MASK 255 +#define MMUEXT_CMD_SHIFT 8 + +/* These are passed as 'flags' to update_va_mapping. They can be ORed. */ +#define UVMF_FLUSH_TLB 1 /* Flush entire TLB. */ +#define UVMF_INVLPG 2 /* Flush the VA mapping being updated. */ + +/* + * Master "switch" for enabling/disabling event delivery. + */ +#define EVENTS_MASTER_ENABLE_MASK 0x80000000UL +#define EVENTS_MASTER_ENABLE_BIT 31 + + +/* + * SCHEDOP_* - Scheduler hypercall operations. + */ +#define SCHEDOP_yield 0 /* Give up the CPU voluntarily. */ +#define SCHEDOP_block 1 /* Block until an event is received. */ +#define SCHEDOP_exit 3 /* Exit and kill this domain. */ +#define SCHEDOP_stop 4 /* Stop executing this domain. */ + +/* + * Commands to HYPERVISOR_serial_io(). + */ +#define SERIALIO_write 0 +#define SERIALIO_read 1 + +#ifndef __ASSEMBLY__ + +typedef u64 domid_t; +/* DOMID_SELF is used in certain contexts to refer to oneself. */ +#define DOMID_SELF (~1ULL) + +#include "network.h" +#include "block.h" + +/* + * Send an array of these to HYPERVISOR_set_trap_table() + */ +#define TI_GET_DPL(_ti) ((_ti)->flags & 3) +#define TI_GET_IF(_ti) ((_ti)->flags & 4) +#define TI_SET_DPL(_ti,_dpl) ((_ti)->flags |= (_dpl)) +#define TI_SET_IF(_ti,_if) ((_ti)->flags |= ((!!(_if))<<2)) +typedef struct trap_info_st +{ + unsigned char vector; /* exception vector */ + unsigned char flags; /* 0-3: privilege level; 4: clear event enable? */ + unsigned short cs; /* code selector */ + unsigned long address; /* code address */ +} trap_info_t; + +/* + * Send an array of these to HYPERVISOR_mmu_update() + */ +typedef struct +{ + unsigned long ptr, val; /* *ptr = val */ +} mmu_update_t; + +/* + * Send an array of these to HYPERVISOR_multicall() + */ +typedef struct +{ + unsigned long op; + unsigned long args[7]; +} multicall_entry_t; + +typedef struct +{ + unsigned long ebx; + unsigned long ecx; + unsigned long edx; + unsigned long esi; + unsigned long edi; + unsigned long ebp; + unsigned long eax; + unsigned long ds; + unsigned long es; + unsigned long fs; + unsigned long gs; + unsigned long _unused; + unsigned long eip; + unsigned long cs; + unsigned long eflags; + unsigned long esp; + unsigned long ss; +} execution_context_t; + +/* + * Xen/guestos shared data -- pointer provided in start_info. + * NB. We expect that this struct is smaller than a page. + */ +typedef struct shared_info_st { + + /* Bitmask of outstanding event notifications hypervisor -> guest OS. */ + unsigned long events; + /* + * Hypervisor will only signal event delivery via the "callback exception" + * when a pending event is not masked. The mask also contains a "master + * enable" which prevents any event delivery. This mask can be used to + * prevent unbounded reentrancy and stack overflow (in this way, acts as a + * kind of interrupt-enable flag). + */ + unsigned long events_mask; + + /* + * A domain can have up to 1024 bidirectional event channels to/from other + * domains. Domains must agree out-of-band to set up a connection, and then + * each must explicitly request a connection to the other. When both have + * made the request the channel is fully allocated and set up. + * + * An event channel is a single sticky 'bit' of information. Setting the + * sticky bit also causes an upcall into the target domain. In this way + * events can be seen as an IPI [Inter-Process(or) Interrupt]. + * + * A guest can see which of its event channels are pending by reading the + * 'event_channel_pend' bitfield. To avoid a linear scan of the entire + * bitfield there is a 'selector' which indicates which words in the + * bitfield contain at least one set bit. + * + * There is a similar bitfield to indicate which event channels have been + * disconnected by the remote end. There is also a 'selector' for this + * field. + */ + u32 event_channel_pend[32]; + u32 event_channel_pend_sel; + u32 event_channel_disc[32]; + u32 event_channel_disc_sel; + + /* + * Time: The following abstractions are exposed: System Time, Clock Time, + * Domain Virtual Time. Domains can access Cycle counter time directly. + */ + + unsigned int rdtsc_bitshift; /* tsc_timestamp uses N:N+31 of TSC. */ + u64 cpu_freq; /* CPU frequency (Hz). */ + + /* + * The following values are updated periodically (and not necessarily + * atomically!). The guest OS detects this because 'time_version1' is + * incremented just before updating these values, and 'time_version2' is + * incremented immediately after. See Xenolinux code for an example of how + * to read these values safely (arch/xeno/kernel/time.c). + */ + unsigned long time_version1; /* A version number for info below. */ + unsigned long time_version2; /* A version number for info below. */ + unsigned long tsc_timestamp; /* TSC at last update of time vals. */ + u64 system_time; /* Time, in nanosecs, since boot. */ + unsigned long wc_sec; /* Secs 00:00:00 UTC, Jan 1, 1970. */ + unsigned long wc_usec; /* Usecs 00:00:00 UTC, Jan 1, 1970. */ + + /* Domain Virtual Time */ + u64 domain_time; + + /* + * Timeout values: + * Allow a domain to specify a timeout value in system time and + * domain virtual time. + */ + u64 wall_timeout; + u64 domain_timeout; + + /* + * The index structures are all stored here for convenience. The rings + * themselves are allocated by Xen but the guestos must create its own + * mapping -- the machine address is given in the startinfo structure to + * allow this to happen. + */ + net_idx_t net_idx[MAX_DOMAIN_VIFS]; + + execution_context_t execution_context; + +} shared_info_t; + +/* + * NB. We expect that this struct is smaller than a page. + */ +typedef struct start_info_st { + /* THE FOLLOWING ARE FILLED IN BOTH ON INITIAL BOOT AND ON RESUME. */ + unsigned long nr_pages; /* total pages allocated to this domain. */ + unsigned long shared_info; /* MACHINE address of shared info struct.*/ + unsigned long flags; /* SIF_xxx flags. */ + /* THE FOLLOWING ARE ONLY FILLED IN ON INITIAL BOOT (NOT RESUME). */ + unsigned long pt_base; /* VIRTUAL address of page directory. */ + unsigned long mod_start; /* VIRTUAL address of pre-loaded module. */ + unsigned long mod_len; /* Size (bytes) of pre-loaded module. */ + unsigned char cmd_line[1]; /* Variable-length options. */ +} start_info_t; + +/* These flags are passed in the 'flags' field of start_info_t. */ +#define SIF_PRIVILEGED 1 /* Is the domain privileged? */ +#define SIF_INITDOMAIN 2 /* Is thsi the initial control domain? */ + +/* For use in guest OSes. */ +extern shared_info_t *HYPERVISOR_shared_info; + +#endif /* !__ASSEMBLY__ */ + +#endif /* __HYPERVISOR_IF_H__ */ diff --git a/xen/include/xeno/config.h b/xen/include/xeno/config.h index bfd99a0725..88a1186f25 100644 --- a/xen/include/xeno/config.h +++ b/xen/include/xeno/config.h @@ -6,165 +6,6 @@ #ifndef __XENO_CONFIG_H__ #define __XENO_CONFIG_H__ - -#define CONFIG_X86 1 - -#define CONFIG_SMP 1 -#define CONFIG_X86_LOCAL_APIC 1 -#define CONFIG_X86_IO_APIC 1 -#define CONFIG_X86_L1_CACHE_SHIFT 5 - -#define CONFIG_PCI 1 -#define CONFIG_PCI_BIOS 1 -#define CONFIG_PCI_DIRECT 1 - -#define CONFIG_IDE 1 -#define CONFIG_BLK_DEV_IDE 1 -#define CONFIG_BLK_DEV_IDEDMA 1 -#define CONFIG_BLK_DEV_IDEPCI 1 -#define CONFIG_IDEDISK_MULTI_MODE 1 -#define CONFIG_IDEDISK_STROKE 1 -#define CONFIG_IDEPCI_SHARE_IRQ 1 -#define CONFIG_BLK_DEV_IDEDMA_PCI 1 -#define CONFIG_IDEDMA_PCI_AUTO 1 -#define CONFIG_IDEDMA_AUTO 1 -#define CONFIG_IDEDMA_ONLYDISK 1 -#define CONFIG_BLK_DEV_IDE_MODES 1 -#define CONFIG_BLK_DEV_PIIX 1 - -#define CONFIG_SCSI 1 -#define CONFIG_SCSI_LOGGING 1 -#define CONFIG_BLK_DEV_SD 1 -#define CONFIG_SD_EXTRA_DEVS 40 -#define CONFIG_SCSI_MULTI_LUN 1 - -#define CONFIG_XEN_ATTENTION_KEY 1 - -#define HZ 100 - -/* - * Just to keep compiler happy. - * NB. DO NOT CHANGE SMP_CACHE_BYTES WITHOUT FIXING arch/i386/entry.S!!! - * It depends on size of irq_cpustat_t, for example, being 64 bytes. :-) - * Mmmm... so niiiiiice.... - */ -#define SMP_CACHE_BYTES 64 -#define NR_CPUS 16 -#define __cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES))) -#define ____cacheline_aligned __cacheline_aligned - -/*** Hypervisor owns top 64MB of virtual address space. ***/ -#define HYPERVISOR_VIRT_START (0xFC000000UL) - -/* - * First 4MB are mapped read-only for all. It's for the machine->physical - * mapping table (MPT table). The following are virtual addresses. - */ -#define READONLY_MPT_VIRT_START (HYPERVISOR_VIRT_START) -#define READONLY_MPT_VIRT_END (READONLY_MPT_VIRT_START + (4*1024*1024)) -/* - * Next 16MB is fixed monitor space, which is part of a 44MB direct-mapped - * memory region. The following are machine addresses. - */ -#define MAX_MONITOR_ADDRESS (16*1024*1024) -#define MAX_DMA_ADDRESS (16*1024*1024) -#define MAX_DIRECTMAP_ADDRESS (44*1024*1024) -/* And the virtual addresses for the direct-map region... */ -#define DIRECTMAP_VIRT_START (READONLY_MPT_VIRT_END) -#define DIRECTMAP_VIRT_END (DIRECTMAP_VIRT_START + MAX_DIRECTMAP_ADDRESS) -#define MONITOR_VIRT_START (DIRECTMAP_VIRT_START) -#define MONITOR_VIRT_END (MONITOR_VIRT_START + MAX_MONITOR_ADDRESS) -#define RDWR_MPT_VIRT_START (MONITOR_VIRT_END) -#define RDWR_MPT_VIRT_END (RDWR_MPT_VIRT_START + (4*1024*1024)) -#define FRAMETABLE_VIRT_START (RDWR_MPT_VIRT_END) -#define FRAMETABLE_VIRT_END (DIRECTMAP_VIRT_END) -/* Next 4MB of virtual address space is used as a linear p.t. mapping. */ -#define LINEAR_PT_VIRT_START (DIRECTMAP_VIRT_END) -#define LINEAR_PT_VIRT_END (LINEAR_PT_VIRT_START + (4*1024*1024)) -/* Next 4MB of virtual address space used for per-domain mappings (eg. GDT). */ -#define PERDOMAIN_VIRT_START (LINEAR_PT_VIRT_END) -#define PERDOMAIN_VIRT_END (PERDOMAIN_VIRT_START + (4*1024*1024)) -#define GDT_VIRT_START (PERDOMAIN_VIRT_START) -#define GDT_VIRT_END (GDT_VIRT_START + (64*1024)) -#define LDT_VIRT_START (GDT_VIRT_END) -#define LDT_VIRT_END (LDT_VIRT_START + (64*1024)) -/* Penultimate 4MB of virtual address space used for domain page mappings. */ -#define MAPCACHE_VIRT_START (PERDOMAIN_VIRT_END) -#define MAPCACHE_VIRT_END (MAPCACHE_VIRT_START + (4*1024*1024)) -/* Final 4MB of virtual address space used for ioremap(). */ -#define IOREMAP_VIRT_START (MAPCACHE_VIRT_END) -#define IOREMAP_VIRT_END (IOREMAP_VIRT_START + (4*1024*1024)) - -/* - * Amount of slack domain memory to leave in system, in megabytes. - * Prevents a hard out-of-memory crunch for thinsg like network receive. - */ -#define SLACK_DOMAIN_MEM_KILOBYTES 2048 - -/* Linkage for x86 */ -#define FASTCALL(x) x __attribute__((regparm(3))) -#define asmlinkage __attribute__((regparm(0))) -#define __ALIGN .align 16,0x90 -#define __ALIGN_STR ".align 16,0x90" -#define SYMBOL_NAME_STR(X) #X -#define SYMBOL_NAME(X) X -#define SYMBOL_NAME_LABEL(X) X##: -#ifdef __ASSEMBLY__ -#define ALIGN __ALIGN -#define ALIGN_STR __ALIGN_STR -#define ENTRY(name) \ - .globl SYMBOL_NAME(name); \ - ALIGN; \ - SYMBOL_NAME_LABEL(name) -#endif - -/* syslog levels ==> nothing! */ -#define KERN_NOTICE "" -#define KERN_WARNING "" -#define KERN_DEBUG "" -#define KERN_INFO "" -#define KERN_ERR "" -#define KERN_CRIT "" -#define KERN_EMERG "" -#define KERN_ALERT "" - -#define barrier() __asm__ __volatile__("": : :"memory") - -#define __HYPERVISOR_CS 0x0808 -#define __HYPERVISOR_DS 0x0810 - -#define NR_syscalls 256 - -#define offsetof(_p,_f) ((unsigned long)&(((_p *)0)->_f)) -#define struct_cpy(_x,_y) (memcpy((_x),(_y),sizeof(*(_x)))) - -#define dev_probe_lock() ((void)0) -#define dev_probe_unlock() ((void)0) - -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) - -#define capable(_c) 0 - -#ifndef NDEBUG -#define DPRINTK(_f, _a...) printk("(file=%s, line=%d) " _f, \ - __FILE__ , __LINE__ , ## _a ) -#define MEMORY_GUARD -#define TRACE_BUFFER -#else -#define DPRINTK(_f, _a...) ((void)0) -#endif - -#ifndef __ASSEMBLY__ - -#include <xeno/compiler.h> - -extern unsigned long _end; /* standard ELF symbol */ -extern void __out_of_line_bug(int line) __attribute__((noreturn)); -#define out_of_line_bug() __out_of_line_bug(__LINE__) - -extern unsigned int opt_ser_baud; -#define SERIAL_ENABLED (opt_ser_baud != 0) - -#endif /* __ASSEMBLY__ */ +#include <asm/config.h> #endif /* __XENO_CONFIG_H__ */ |