Merge branches 'x86/urgent', 'x86/amd-iommu', 'x86/apic', 'x86/cleanups', 'x86/core', 'x86/cpu', 'x86/fixmap', 'x86/gart', 'x86/kprobes', 'x86/memtest', 'x86/modules', 'x86/nmi', 'x86/pat', 'x86/reboot', 'x86/setup', 'x86/step', 'x86/unify-pci', 'x86/uv', 'x86/xen' and 'xen-64bit' into x86/for-linus

This commit is contained in:
139 changed files with 3891 additions and 1716 deletions

View file

@ -27,13 +27,12 @@
/*
* some size calculation constants
*/
#define DEV_TABLE_ENTRY_SIZE 256
#define DEV_TABLE_ENTRY_SIZE 32
#define ALIAS_TABLE_ENTRY_SIZE 2
#define RLOOKUP_TABLE_ENTRY_SIZE (sizeof(void *))
/* helper macros */
#define LOW_U32(x) ((x) & ((1ULL << 32)-1))
#define HIGH_U32(x) (LOW_U32((x) >> 32))
/* Length of the MMIO region for the AMD IOMMU */
#define MMIO_REGION_LENGTH 0x4000
@ -158,78 +157,170 @@
#define MAX_DOMAIN_ID 65536
/*
* This structure contains generic data for IOMMU protection domains
* independent of their use.
*/
struct protection_domain {
spinlock_t lock;
u16 id;
int mode;
u64 *pt_root;
void *priv;
spinlock_t lock; /* mostly used to lock the page table*/
u16 id; /* the domain id written to the device table */
int mode; /* paging mode (0-6 levels) */
u64 *pt_root; /* page table root pointer */
void *priv; /* private data */
};
/*
* Data container for a dma_ops specific protection domain
*/
struct dma_ops_domain {
struct list_head list;
/* generic protection domain information */
struct protection_domain domain;
/* size of the aperture for the mappings */
unsigned long aperture_size;
/* address we start to search for free addresses */
unsigned long next_bit;
/* address allocation bitmap */
unsigned long *bitmap;
/*
* Array of PTE pages for the aperture. In this array we save all the
* leaf pages of the domain page table used for the aperture. This way
* we don't need to walk the page table to find a specific PTE. We can
* just calculate its address in constant time.
*/
u64 **pte_pages;
};
/*
* Structure where we save information about one hardware AMD IOMMU in the
* system.
*/
struct amd_iommu {
struct list_head list;
/* locks the accesses to the hardware */
spinlock_t lock;
/* device id of this IOMMU */
u16 devid;
/*
* Capability pointer. There could be more than one IOMMU per PCI
* device function if there are more than one AMD IOMMU capability
* pointers.
*/
u16 cap_ptr;
/* physical address of MMIO space */
u64 mmio_phys;
/* virtual address of MMIO space */
u8 *mmio_base;
/* capabilities of that IOMMU read from ACPI */
u32 cap;
/* first device this IOMMU handles. read from PCI */
u16 first_device;
/* last device this IOMMU handles. read from PCI */
u16 last_device;
/* start of exclusion range of that IOMMU */
u64 exclusion_start;
/* length of exclusion range of that IOMMU */
u64 exclusion_length;
/* command buffer virtual address */
u8 *cmd_buf;
/* size of command buffer */
u32 cmd_buf_size;
/* if one, we need to send a completion wait command */
int need_sync;
/* default dma_ops domain for that IOMMU */
struct dma_ops_domain *default_dom;
};
/*
* List with all IOMMUs in the system. This list is not locked because it is
* only written and read at driver initialization or suspend time
*/
extern struct list_head amd_iommu_list;
/*
* Structure defining one entry in the device table
*/
struct dev_table_entry {
u32 data[8];
};
/*
* One entry for unity mappings parsed out of the ACPI table.
*/
struct unity_map_entry {
struct list_head list;
/* starting device id this entry is used for (including) */
u16 devid_start;
/* end device id this entry is used for (including) */
u16 devid_end;
/* start address to unity map (including) */
u64 address_start;
/* end address to unity map (including) */
u64 address_end;
/* required protection */
int prot;
};
/*
* List of all unity mappings. It is not locked because as runtime it is only
* read. It is created at ACPI table parsing time.
*/
extern struct list_head amd_iommu_unity_map;
/* data structures for device handling */
/*
* Data structures for device handling
*/
/*
* Device table used by hardware. Read and write accesses by software are
* locked with the amd_iommu_pd_table lock.
*/
extern struct dev_table_entry *amd_iommu_dev_table;
/*
* Alias table to find requestor ids to device ids. Not locked because only
* read on runtime.
*/
extern u16 *amd_iommu_alias_table;
/*
* Reverse lookup table to find the IOMMU which translates a specific device.
*/
extern struct amd_iommu **amd_iommu_rlookup_table;
/* size of the dma_ops aperture as power of 2 */
extern unsigned amd_iommu_aperture_order;
/* largest PCI device id we expect translation requests for */
extern u16 amd_iommu_last_bdf;
/* data structures for protection domain handling */
extern struct protection_domain **amd_iommu_pd_table;
/* allocation bitmap for domain ids */
extern unsigned long *amd_iommu_pd_alloc_bitmap;
/* will be 1 if device isolation is enabled */
extern int amd_iommu_isolate;
/* takes a PCI device id and prints it out in a readable form */
static inline void print_devid(u16 devid, int nl)
{
int bus = devid >> 8;
@ -241,4 +332,11 @@ static inline void print_devid(u16 devid, int nl)
printk("\n");
}
/* takes bus and device/function and returns the device id
* FIXME: should that be in generic PCI code? */
static inline u16 calc_devid(u8 bus, u8 devfn)
{
return (((u16)bus) << 8) | devfn;
}
#endif

View file

@ -3,6 +3,8 @@
#include <linux/pm.h>
#include <linux/delay.h>
#include <asm/alternative.h>
#include <asm/fixmap.h>
#include <asm/apicdef.h>
#include <asm/processor.h>
@ -10,7 +12,7 @@
#define ARCH_APICTIMER_STOPS_ON_C3 1
#define Dprintk(x...)
#define Dprintk printk
/*
* Debugging macros
@ -35,7 +37,7 @@ extern void generic_apic_probe(void);
#ifdef CONFIG_X86_LOCAL_APIC
extern int apic_verbosity;
extern unsigned int apic_verbosity;
extern int local_apic_timer_c2_ok;
extern int ioapic_force;
@ -48,7 +50,6 @@ extern int disable_apic;
#include <asm/paravirt.h>
#else
#define apic_write native_apic_write
#define apic_write_atomic native_apic_write_atomic
#define apic_read native_apic_read
#define setup_boot_clock setup_boot_APIC_clock
#define setup_secondary_clock setup_secondary_APIC_clock
@ -58,12 +59,11 @@ extern int is_vsmp_box(void);
static inline void native_apic_write(unsigned long reg, u32 v)
{
*((volatile u32 *)(APIC_BASE + reg)) = v;
}
volatile u32 *addr = (volatile u32 *)(APIC_BASE + reg);
static inline void native_apic_write_atomic(unsigned long reg, u32 v)
{
(void)xchg((u32 *)(APIC_BASE + reg), v);
alternative_io("movl %0, %1", "xchgl %0, %1", X86_FEATURE_11AP,
ASM_OUTPUT2("=r" (v), "=m" (*addr)),
ASM_OUTPUT2("0" (v), "m" (*addr)));
}
static inline u32 native_apic_read(unsigned long reg)
@ -75,16 +75,6 @@ extern void apic_wait_icr_idle(void);
extern u32 safe_apic_wait_icr_idle(void);
extern int get_physical_broadcast(void);
#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)
{
/*
@ -95,7 +85,7 @@ static inline void ack_APIC_irq(void)
*/
/* Docs say use 0 for future compatibility */
apic_write_around(APIC_EOI, 0);
apic_write(APIC_EOI, 0);
}
extern int lapic_get_maxlvt(void);

View file

@ -21,6 +21,7 @@ extern void intr_init_hook(void);
extern void pre_intr_init_hook(void);
extern void pre_setup_arch_hook(void);
extern void trap_init_hook(void);
extern void pre_time_init_hook(void);
extern void time_init_hook(void);
extern void mca_nmi_hook(void);

View file

@ -356,7 +356,7 @@ static inline unsigned long ffz(unsigned long word)
* __fls: find last set bit in word
* @word: The word to search
*
* Undefined if no zero exists, so code should check against ~0UL first.
* Undefined if no set bit exists, so code should check against 0 first.
*/
static inline unsigned long __fls(unsigned long word)
{

View file

@ -104,7 +104,7 @@
.endif
.endm
.macro LOAD_ARGS offset
.macro LOAD_ARGS offset, skiprax=0
movq \offset(%rsp), %r11
movq \offset+8(%rsp), %r10
movq \offset+16(%rsp), %r9
@ -113,7 +113,10 @@
movq \offset+48(%rsp), %rdx
movq \offset+56(%rsp), %rsi
movq \offset+64(%rsp), %rdi
.if \skiprax
.else
movq \offset+72(%rsp), %rax
.endif
.endm
#define REST_SKIP 6*8
@ -165,4 +168,3 @@
.macro icebp
.byte 0xf1
.endm

View file

@ -79,6 +79,7 @@
#define X86_FEATURE_REP_GOOD (3*32+16) /* rep microcode works well on this CPU */
#define X86_FEATURE_MFENCE_RDTSC (3*32+17) /* Mfence synchronizes RDTSC */
#define X86_FEATURE_LFENCE_RDTSC (3*32+18) /* Lfence synchronizes RDTSC */
#define X86_FEATURE_11AP (3*32+19) /* Bad local APIC aka 11AP */
/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
#define X86_FEATURE_XMM3 (4*32+ 0) /* Streaming SIMD Extensions-3 */

View file

@ -14,7 +14,6 @@ extern dma_addr_t bad_dma_address;
extern int iommu_merge;
extern struct device fallback_dev;
extern int panic_on_overflow;
extern int forbid_dac;
extern int force_iommu;
struct dma_mapping_ops {

View file

@ -90,6 +90,14 @@ static inline void e820_mark_nosave_regions(unsigned long limit_pfn)
}
#endif
#ifdef CONFIG_MEMTEST
extern void early_memtest(unsigned long start, unsigned long end);
#else
static inline void early_memtest(unsigned long start, unsigned long end)
{
}
#endif
extern unsigned long end_user_pfn;
extern u64 find_e820_area(u64 start, u64 end, u64 size, u64 align);

View file

@ -90,13 +90,13 @@ enum fixed_addresses {
* 256 temporary boot-time mappings, used by early_ioremap(),
* before ioremap() is functional.
*
* We round it up to the next 512 pages boundary so that we
* We round it up to the next 256 pages boundary so that we
* can have a single pgd entry and a single pte table:
*/
#define NR_FIX_BTMAPS 64
#define FIX_BTMAPS_NESTING 4
FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 512 -
(__end_of_permanent_fixed_addresses & 511),
FIX_BTMAP_END = __end_of_permanent_fixed_addresses + 256 -
(__end_of_permanent_fixed_addresses & 255),
FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS*FIX_BTMAPS_NESTING - 1,
FIX_WP_TEST,
#ifdef CONFIG_ACPI

View file

@ -2,7 +2,6 @@
#define _ASM_X8664_GART_H 1
#include <asm/e820.h>
#include <asm/iommu.h>
extern void set_up_gart_resume(u32, u32);

View file

@ -25,10 +25,18 @@ extern void gart_iommu_hole_init(void);
static inline void early_gart_iommu_check(void)
{
}
static inline void gart_iommu_init(void)
{
}
static inline void gart_iommu_shutdown(void)
{
}
static inline void gart_parse_options(char *options)
{
}
static inline void gart_iommu_hole_init(void)
{
}
#endif
#endif

View file

@ -63,9 +63,9 @@ static inline void init_apic_ldr(void)
unsigned long val;
int cpu = smp_processor_id();
apic_write_around(APIC_DFR, APIC_DFR_VALUE);
apic_write(APIC_DFR, APIC_DFR_VALUE);
val = calculate_ldr(cpu);
apic_write_around(APIC_LDR, val);
apic_write(APIC_LDR, val);
}
static inline void setup_apic_routing(void)

View file

@ -46,10 +46,10 @@ static inline void init_apic_ldr(void)
{
unsigned long val;
apic_write_around(APIC_DFR, APIC_DFR_VALUE);
apic_write(APIC_DFR, APIC_DFR_VALUE);
val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
val |= SET_APIC_LOGICAL_ID(1UL << smp_processor_id());
apic_write_around(APIC_LDR, val);
apic_write(APIC_LDR, val);
}
static inline int apic_id_registered(void)

View file

@ -66,9 +66,9 @@ static inline void init_apic_ldr(void)
unsigned long val;
int cpu = smp_processor_id();
apic_write_around(APIC_DFR, APIC_DFR_VALUE);
apic_write(APIC_DFR, APIC_DFR_VALUE);
val = calculate_ldr(cpu);
apic_write_around(APIC_LDR, val);
apic_write(APIC_LDR, val);
}
#ifndef CONFIG_X86_GENERICARCH

View file

@ -7,4 +7,6 @@
/* Maximum 256 PCI busses, plus 1 ISA bus in each of 4 cabinets. */
#define MAX_MP_BUSSES 260
extern void numaq_mps_oem_check(struct mp_config_table *mpc, char *oem,
char *productid);
#endif /* __ASM_MACH_MPSPEC_H */

View file

@ -63,10 +63,10 @@ static inline void init_apic_ldr(void)
* BIOS puts 5 CPUs in one APIC cluster, we're hosed. */
BUG_ON(count >= XAPIC_DEST_CPUS_SHIFT);
id = my_cluster | (1UL << count);
apic_write_around(APIC_DFR, APIC_DFR_VALUE);
apic_write(APIC_DFR, APIC_DFR_VALUE);
val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
val |= SET_APIC_LOGICAL_ID(id);
apic_write_around(APIC_LDR, val);
apic_write(APIC_LDR, val);
}
static inline int multi_timer_check(int apic, int irq)

View file

@ -1,5 +0,0 @@
/*
* VISWS uses the standard Linux entry points:
*/
#include "../mach-default/entry_arch.h"

View file

@ -1 +0,0 @@
#include "../mach-default/mach_apic.h"

View file

@ -1 +0,0 @@
#include "../mach-default/mach_apicdef.h"

View file

@ -1 +0,0 @@
#include "../mach-default/setup_arch.h"

View file

@ -1 +0,0 @@
#include "../mach-default/smpboot_hooks.h"

View file

@ -205,7 +205,6 @@ struct pv_apic_ops {
* these shouldn't be in this interface.
*/
void (*apic_write)(unsigned long reg, u32 v);
void (*apic_write_atomic)(unsigned long reg, u32 v);
u32 (*apic_read)(unsigned long reg);
void (*setup_boot_clock)(void);
void (*setup_secondary_clock)(void);
@ -896,11 +895,6 @@ static inline void apic_write(unsigned long reg, u32 v)
PVOP_VCALL2(pv_apic_ops.apic_write, reg, v);
}
static inline void apic_write_atomic(unsigned long reg, u32 v)
{
PVOP_VCALL2(pv_apic_ops.apic_write_atomic, reg, v);
}
static inline u32 apic_read(unsigned long reg)
{
return PVOP_CALL1(unsigned long, pv_apic_ops.apic_read, reg);
@ -1396,8 +1390,8 @@ extern struct paravirt_patch_site __parainstructions[],
* caller saved registers but the argument parameter */
#define PV_SAVE_REGS "pushq %%rdi;"
#define PV_RESTORE_REGS "popq %%rdi;"
#define PV_EXTRA_CLOBBERS EXTRA_CLOBBERS, "rcx" , "rdx"
#define PV_VEXTRA_CLOBBERS EXTRA_CLOBBERS, "rdi", "rcx" , "rdx"
#define PV_EXTRA_CLOBBERS EXTRA_CLOBBERS, "rcx" , "rdx", "rsi"
#define PV_VEXTRA_CLOBBERS EXTRA_CLOBBERS, "rdi", "rcx" , "rdx", "rsi"
#define PV_FLAGS_ARG "D"
#endif
@ -1489,8 +1483,26 @@ static inline unsigned long __raw_local_irq_save(void)
#ifdef CONFIG_X86_64
#define PV_SAVE_REGS pushq %rax; pushq %rdi; pushq %rcx; pushq %rdx
#define PV_RESTORE_REGS popq %rdx; popq %rcx; popq %rdi; popq %rax
#define PV_SAVE_REGS \
push %rax; \
push %rcx; \
push %rdx; \
push %rsi; \
push %rdi; \
push %r8; \
push %r9; \
push %r10; \
push %r11
#define PV_RESTORE_REGS \
pop %r11; \
pop %r10; \
pop %r9; \
pop %r8; \
pop %rdi; \
pop %rsi; \
pop %rdx; \
pop %rcx; \
pop %rax
#define PARA_PATCH(struct, off) ((PARAVIRT_PATCH_##struct + (off)) / 8)
#define PARA_SITE(ptype, clobbers, ops) _PVSITE(ptype, clobbers, ops, .quad, 8)
#define PARA_INDIRECT(addr) *addr(%rip)

View file

@ -22,6 +22,32 @@
DECLARE_PER_CPU(struct x8664_pda, pda);
/*
* These are supposed to be implemented as a single instruction which
* operates on the per-cpu data base segment. x86-64 doesn't have
* that yet, so this is a fairly inefficient workaround for the
* meantime. The single instruction is atomic with respect to
* preemption and interrupts, so we need to explicitly disable
* interrupts here to achieve the same effect. However, because it
* can be used from within interrupt-disable/enable, we can't actually
* disable interrupts; disabling preemption is enough.
*/
#define x86_read_percpu(var) \
({ \
typeof(per_cpu_var(var)) __tmp; \
preempt_disable(); \
__tmp = __get_cpu_var(var); \
preempt_enable(); \
__tmp; \
})
#define x86_write_percpu(var, val) \
do { \
preempt_disable(); \
__get_cpu_var(var) = (val); \
preempt_enable(); \
} while(0)
#else /* CONFIG_X86_64 */
#ifdef __ASSEMBLY__

View file

@ -302,6 +302,14 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn,
/* Install a pte for a particular vaddr in kernel space. */
void set_pte_vaddr(unsigned long vaddr, pte_t pte);
#ifdef CONFIG_X86_32
extern void native_pagetable_setup_start(pgd_t *base);
extern void native_pagetable_setup_done(pgd_t *base);
#else
static inline void native_pagetable_setup_start(pgd_t *base) {}
static inline void native_pagetable_setup_done(pgd_t *base) {}
#endif
#ifdef CONFIG_PARAVIRT
#include <asm/paravirt.h>
#else /* !CONFIG_PARAVIRT */
@ -333,6 +341,16 @@ void set_pte_vaddr(unsigned long vaddr, pte_t pte);
#define pte_update(mm, addr, ptep) do { } while (0)
#define pte_update_defer(mm, addr, ptep) do { } while (0)
static inline void __init paravirt_pagetable_setup_start(pgd_t *base)
{
native_pagetable_setup_start(base);
}
static inline void __init paravirt_pagetable_setup_done(pgd_t *base)
{
native_pagetable_setup_done(base);
}
#endif /* CONFIG_PARAVIRT */
#endif /* __ASSEMBLY__ */

View file

@ -171,21 +171,6 @@ do { \
*/
#define update_mmu_cache(vma, address, pte) do { } while (0)
extern void native_pagetable_setup_start(pgd_t *base);
extern void native_pagetable_setup_done(pgd_t *base);
#ifndef CONFIG_PARAVIRT
static inline void __init paravirt_pagetable_setup_start(pgd_t *base)
{
native_pagetable_setup_start(base);
}
static inline void __init paravirt_pagetable_setup_done(pgd_t *base)
{
native_pagetable_setup_done(base);
}
#endif /* !CONFIG_PARAVIRT */
#endif /* !__ASSEMBLY__ */
/*

View file

@ -16,6 +16,8 @@
extern pud_t level3_kernel_pgt[512];
extern pud_t level3_ident_pgt[512];
extern pmd_t level2_kernel_pgt[512];
extern pmd_t level2_fixmap_pgt[512];
extern pmd_t level2_ident_pgt[512];
extern pgd_t init_level4_pgt[];
#define swapper_pg_dir init_level4_pgt

View file

@ -722,8 +722,6 @@ static inline void __sti_mwait(unsigned long eax, unsigned long ecx)
extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx);
extern int force_mwait;
extern void select_idle_routine(const struct cpuinfo_x86 *c);
extern unsigned long boot_option_idle_override;

View file

@ -73,11 +73,11 @@
#ifdef __x86_64__
# define PTRACE_ARCH_PRCTL 30
#else
# define PTRACE_SYSEMU 31
# define PTRACE_SYSEMU_SINGLESTEP 32
#endif
#define PTRACE_SYSEMU 31
#define PTRACE_SYSEMU_SINGLESTEP 32
#define PTRACE_SINGLEBLOCK 33 /* resume execution until next branch */
#ifndef __ASSEMBLY__

View file

@ -1,6 +1,15 @@
#ifndef _ASM_X86_SEGMENT_H_
#define _ASM_X86_SEGMENT_H_
/* Constructor for a conventional segment GDT (or LDT) entry */
/* This is a macro so it can be used in initializers */
#define GDT_ENTRY(flags, base, limit) \
((((base) & 0xff000000ULL) << (56-24)) | \
(((flags) & 0x0000f0ffULL) << 40) | \
(((limit) & 0x000f0000ULL) << (48-16)) | \
(((base) & 0x00ffffffULL) << 16) | \
(((limit) & 0x0000ffffULL)))
/* Simple and small GDT entries for booting only */
#define GDT_ENTRY_BOOT_CS 2

View file

@ -19,13 +19,28 @@ static inline int is_visws_box(void) { return 0; }
/*
* Any setup quirks to be performed?
*/
extern int (*arch_time_init_quirk)(void);
extern int (*arch_pre_intr_init_quirk)(void);
extern int (*arch_intr_init_quirk)(void);
extern int (*arch_trap_init_quirk)(void);
extern char * (*arch_memory_setup_quirk)(void);
extern int (*mach_get_smp_config_quirk)(unsigned int early);
extern int (*mach_find_smp_config_quirk)(unsigned int reserve);
struct mpc_config_processor;
struct mpc_config_bus;
struct mp_config_oemtable;
struct x86_quirks {
int (*arch_pre_time_init)(void);
int (*arch_time_init)(void);
int (*arch_pre_intr_init)(void);
int (*arch_intr_init)(void);
int (*arch_trap_init)(void);
char * (*arch_memory_setup)(void);
int (*mach_get_smp_config)(unsigned int early);
int (*mach_find_smp_config)(unsigned int reserve);
int *mpc_record;
int (*mpc_apic_id)(struct mpc_config_processor *m);
void (*mpc_oem_bus_info)(struct mpc_config_bus *m, char *name);
void (*mpc_oem_pci_bus)(struct mpc_config_bus *m);
void (*smp_read_mpc_oem)(struct mp_config_oemtable *oemtable,
unsigned short oemsize);
};
extern struct x86_quirks *x86_quirks;
#ifndef CONFIG_PARAVIRT
#define paravirt_post_allocator_init() do {} while (0)
@ -76,6 +91,7 @@ extern unsigned long init_pg_tables_start;
extern unsigned long init_pg_tables_end;
#else
void __init x86_64_init_pda(void);
void __init x86_64_start_kernel(char *real_mode);
void __init x86_64_start_reservations(char *real_mode_data);

View file

@ -25,6 +25,8 @@ extern cpumask_t cpu_callin_map;
extern void (*mtrr_hook)(void);
extern void zap_low_mappings(void);
extern int __cpuinit get_local_pda(int cpu);
extern int smp_num_siblings;
extern unsigned int num_processors;
extern cpumask_t cpu_initialized;

View file

@ -45,12 +45,14 @@ extern int swiotlb_force;
#ifdef CONFIG_SWIOTLB
extern int swiotlb;
extern void pci_swiotlb_init(void);
#else
#define swiotlb 0
static inline void pci_swiotlb_init(void)
{
}
#endif
extern void pci_swiotlb_init(void);
static inline void dma_mark_clean(void *addr, size_t size) {}
#endif /* _ASM_SWIOTLB_H */

View file

@ -75,9 +75,7 @@ struct thread_info {
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
#define TIF_SINGLESTEP 4 /* reenable singlestep on user return*/
#define TIF_IRET 5 /* force IRET */
#ifdef CONFIG_X86_32
#define TIF_SYSCALL_EMU 6 /* syscall emulation active */
#endif
#define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */
#define TIF_SECCOMP 8 /* secure computing */
#define TIF_MCE_NOTIFY 10 /* notify userspace of an MCE */
@ -100,11 +98,7 @@ struct thread_info {
#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
#define _TIF_IRET (1 << TIF_IRET)
#ifdef CONFIG_X86_32
#define _TIF_SYSCALL_EMU (1 << TIF_SYSCALL_EMU)
#else
#define _TIF_SYSCALL_EMU 0
#endif
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
#define _TIF_SECCOMP (1 << TIF_SECCOMP)
#define _TIF_MCE_NOTIFY (1 << TIF_MCE_NOTIFY)
@ -121,18 +115,27 @@ struct thread_info {
#define _TIF_DS_AREA_MSR (1 << TIF_DS_AREA_MSR)
#define _TIF_BTS_TRACE_TS (1 << TIF_BTS_TRACE_TS)
/* work to do in syscall_trace_enter() */
#define _TIF_WORK_SYSCALL_ENTRY \
(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_EMU | \
_TIF_SYSCALL_AUDIT | _TIF_SECCOMP | _TIF_SINGLESTEP)
/* work to do in syscall_trace_leave() */
#define _TIF_WORK_SYSCALL_EXIT \
(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | _TIF_SINGLESTEP)
/* work to do on interrupt/exception return */
#define _TIF_WORK_MASK \
(0x0000FFFF & \
~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP| \
_TIF_SECCOMP|_TIF_SYSCALL_EMU))
~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT| \
_TIF_SINGLESTEP|_TIF_SECCOMP|_TIF_SYSCALL_EMU))
/* work to do on any return to user space */
#define _TIF_ALLWORK_MASK (0x0000FFFF & ~_TIF_SECCOMP)
/* Only used for 64 bit */
#define _TIF_DO_NOTIFY_MASK \
(_TIF_SIGPENDING|_TIF_SINGLESTEP|_TIF_MCE_NOTIFY|_TIF_HRTICK_RESCHED)
(_TIF_SIGPENDING|_TIF_MCE_NOTIFY|_TIF_HRTICK_RESCHED)
/* flags to check in __switch_to() */
#define _TIF_WORK_CTXSW \

66
include/asm-x86/traps.h Normal file
View file

@ -0,0 +1,66 @@
#ifndef _ASM_X86_TRAPS_H
#define _ASM_X86_TRAPS_H
/* Common in X86_32 and X86_64 */
asmlinkage void divide_error(void);
asmlinkage void debug(void);
asmlinkage void nmi(void);
asmlinkage void int3(void);
asmlinkage void overflow(void);
asmlinkage void bounds(void);
asmlinkage void invalid_op(void);
asmlinkage void device_not_available(void);
asmlinkage void coprocessor_segment_overrun(void);
asmlinkage void invalid_TSS(void);
asmlinkage void segment_not_present(void);
asmlinkage void stack_segment(void);
asmlinkage void general_protection(void);
asmlinkage void page_fault(void);
asmlinkage void coprocessor_error(void);
asmlinkage void simd_coprocessor_error(void);
asmlinkage void alignment_check(void);
asmlinkage void spurious_interrupt_bug(void);
#ifdef CONFIG_X86_MCE
asmlinkage void machine_check(void);
#endif /* CONFIG_X86_MCE */
void do_divide_error(struct pt_regs *, long);
void do_overflow(struct pt_regs *, long);
void do_bounds(struct pt_regs *, long);
void do_coprocessor_segment_overrun(struct pt_regs *, long);
void do_invalid_TSS(struct pt_regs *, long);
void do_segment_not_present(struct pt_regs *, long);
void do_stack_segment(struct pt_regs *, long);
void do_alignment_check(struct pt_regs *, long);
void do_invalid_op(struct pt_regs *, long);
void do_general_protection(struct pt_regs *, long);
void do_nmi(struct pt_regs *, long);
extern int panic_on_unrecovered_nmi;
extern int kstack_depth_to_print;
#ifdef CONFIG_X86_32
void do_iret_error(struct pt_regs *, long);
void do_int3(struct pt_regs *, long);
void do_debug(struct pt_regs *, long);
void math_error(void __user *);
void do_coprocessor_error(struct pt_regs *, long);
void do_simd_coprocessor_error(struct pt_regs *, long);
void do_spurious_interrupt_bug(struct pt_regs *, long);
unsigned long patch_espfix_desc(unsigned long, unsigned long);
asmlinkage void math_emulate(long);
#else /* CONFIG_X86_32 */
asmlinkage void double_fault(void);
asmlinkage void do_int3(struct pt_regs *, long);
asmlinkage void do_stack_segment(struct pt_regs *, long);
asmlinkage void do_debug(struct pt_regs *, unsigned long);
asmlinkage void do_coprocessor_error(struct pt_regs *);
asmlinkage void do_simd_coprocessor_error(struct pt_regs *);
asmlinkage void do_spurious_interrupt_bug(struct pt_regs *);
#endif /* CONFIG_X86_32 */
#endif /* _ASM_X86_TRAPS_H */

68
include/asm-x86/uv/bios.h Normal file
View file

@ -0,0 +1,68 @@
#ifndef _ASM_X86_BIOS_H
#define _ASM_X86_BIOS_H
/*
* BIOS layer definitions.
*
* Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/rtc.h>
#define BIOS_FREQ_BASE 0x01000001
enum {
BIOS_FREQ_BASE_PLATFORM = 0,
BIOS_FREQ_BASE_INTERVAL_TIMER = 1,
BIOS_FREQ_BASE_REALTIME_CLOCK = 2
};
# define BIOS_CALL(result, a0, a1, a2, a3, a4, a5, a6, a7) \
do { \
/* XXX - the real call goes here */ \
result.status = BIOS_STATUS_UNIMPLEMENTED; \
isrv.v0 = 0; \
isrv.v1 = 0; \
} while (0)
enum {
BIOS_STATUS_SUCCESS = 0,
BIOS_STATUS_UNIMPLEMENTED = -1,
BIOS_STATUS_EINVAL = -2,
BIOS_STATUS_ERROR = -3
};
struct uv_bios_retval {
/*
* A zero status value indicates call completed without error.
* A negative status value indicates reason of call failure.
* A positive status value indicates success but an
* informational value should be printed (e.g., "reboot for
* change to take effect").
*/
s64 status;
u64 v0;
u64 v1;
u64 v2;
};
extern long
x86_bios_freq_base(unsigned long which, unsigned long *ticks_per_second,
unsigned long *drift_info);
extern const char *x86_bios_strerror(long status);
#endif /* _ASM_X86_BIOS_H */

View file

@ -36,4 +36,12 @@ extern const char VDSO32_PRELINK[];
extern void __user __kernel_sigreturn;
extern void __user __kernel_rt_sigreturn;
/*
* These symbols are defined by vdso32.S to mark the bounds
* of the ELF DSO images included therein.
*/
extern const char vdso32_int80_start, vdso32_int80_end;
extern const char vdso32_syscall_start, vdso32_syscall_end;
extern const char vdso32_sysenter_start, vdso32_sysenter_end;
#endif /* asm-x86/vdso.h */

View file

@ -40,83 +40,157 @@
#include <xen/interface/sched.h>
#include <xen/interface/physdev.h>
/*
* The hypercall asms have to meet several constraints:
* - Work on 32- and 64-bit.
* The two architectures put their arguments in different sets of
* registers.
*
* - Work around asm syntax quirks
* It isn't possible to specify one of the rNN registers in a
* constraint, so we use explicit register variables to get the
* args into the right place.
*
* - Mark all registers as potentially clobbered
* Even unused parameters can be clobbered by the hypervisor, so we
* need to make sure gcc knows it.
*
* - Avoid compiler bugs.
* This is the tricky part. Because x86_32 has such a constrained
* register set, gcc versions below 4.3 have trouble generating
* code when all the arg registers and memory are trashed by the
* asm. There are syntactically simpler ways of achieving the
* semantics below, but they cause the compiler to crash.
*
* The only combination I found which works is:
* - assign the __argX variables first
* - list all actually used parameters as "+r" (__argX)
* - clobber the rest
*
* The result certainly isn't pretty, and it really shows up cpp's
* weakness as as macro language. Sorry. (But let's just give thanks
* there aren't more than 5 arguments...)
*/
extern struct { char _entry[32]; } hypercall_page[];
#define __HYPERCALL "call hypercall_page+%c[offset]"
#define __HYPERCALL_ENTRY(x) \
[offset] "i" (__HYPERVISOR_##x * sizeof(hypercall_page[0]))
#ifdef CONFIG_X86_32
#define __HYPERCALL_RETREG "eax"
#define __HYPERCALL_ARG1REG "ebx"
#define __HYPERCALL_ARG2REG "ecx"
#define __HYPERCALL_ARG3REG "edx"
#define __HYPERCALL_ARG4REG "esi"
#define __HYPERCALL_ARG5REG "edi"
#else
#define __HYPERCALL_RETREG "rax"
#define __HYPERCALL_ARG1REG "rdi"
#define __HYPERCALL_ARG2REG "rsi"
#define __HYPERCALL_ARG3REG "rdx"
#define __HYPERCALL_ARG4REG "r10"
#define __HYPERCALL_ARG5REG "r8"
#endif
#define __HYPERCALL_DECLS \
register unsigned long __res asm(__HYPERCALL_RETREG); \
register unsigned long __arg1 asm(__HYPERCALL_ARG1REG) = __arg1; \
register unsigned long __arg2 asm(__HYPERCALL_ARG2REG) = __arg2; \
register unsigned long __arg3 asm(__HYPERCALL_ARG3REG) = __arg3; \
register unsigned long __arg4 asm(__HYPERCALL_ARG4REG) = __arg4; \
register unsigned long __arg5 asm(__HYPERCALL_ARG5REG) = __arg5;
#define __HYPERCALL_0PARAM "=r" (__res)
#define __HYPERCALL_1PARAM __HYPERCALL_0PARAM, "+r" (__arg1)
#define __HYPERCALL_2PARAM __HYPERCALL_1PARAM, "+r" (__arg2)
#define __HYPERCALL_3PARAM __HYPERCALL_2PARAM, "+r" (__arg3)
#define __HYPERCALL_4PARAM __HYPERCALL_3PARAM, "+r" (__arg4)
#define __HYPERCALL_5PARAM __HYPERCALL_4PARAM, "+r" (__arg5)
#define __HYPERCALL_0ARG()
#define __HYPERCALL_1ARG(a1) \
__HYPERCALL_0ARG() __arg1 = (unsigned long)(a1);
#define __HYPERCALL_2ARG(a1,a2) \
__HYPERCALL_1ARG(a1) __arg2 = (unsigned long)(a2);
#define __HYPERCALL_3ARG(a1,a2,a3) \
__HYPERCALL_2ARG(a1,a2) __arg3 = (unsigned long)(a3);
#define __HYPERCALL_4ARG(a1,a2,a3,a4) \
__HYPERCALL_3ARG(a1,a2,a3) __arg4 = (unsigned long)(a4);
#define __HYPERCALL_5ARG(a1,a2,a3,a4,a5) \
__HYPERCALL_4ARG(a1,a2,a3,a4) __arg5 = (unsigned long)(a5);
#define __HYPERCALL_CLOBBER5 "memory"
#define __HYPERCALL_CLOBBER4 __HYPERCALL_CLOBBER5, __HYPERCALL_ARG5REG
#define __HYPERCALL_CLOBBER3 __HYPERCALL_CLOBBER4, __HYPERCALL_ARG4REG
#define __HYPERCALL_CLOBBER2 __HYPERCALL_CLOBBER3, __HYPERCALL_ARG3REG
#define __HYPERCALL_CLOBBER1 __HYPERCALL_CLOBBER2, __HYPERCALL_ARG2REG
#define __HYPERCALL_CLOBBER0 __HYPERCALL_CLOBBER1, __HYPERCALL_ARG1REG
#define _hypercall0(type, name) \
({ \
long __res; \
asm volatile ( \
"call %[call]" \
: "=a" (__res) \
: [call] "m" (hypercall_page[__HYPERVISOR_##name]) \
: "memory" ); \
__HYPERCALL_DECLS; \
__HYPERCALL_0ARG(); \
asm volatile (__HYPERCALL \
: __HYPERCALL_0PARAM \
: __HYPERCALL_ENTRY(name) \
: __HYPERCALL_CLOBBER0); \
(type)__res; \
})
#define _hypercall1(type, name, a1) \
({ \
long __res, __ign1; \
asm volatile ( \
"call %[call]" \
: "=a" (__res), "=b" (__ign1) \
: "1" ((long)(a1)), \
[call] "m" (hypercall_page[__HYPERVISOR_##name]) \
: "memory" ); \
__HYPERCALL_DECLS; \
__HYPERCALL_1ARG(a1); \
asm volatile (__HYPERCALL \
: __HYPERCALL_1PARAM \
: __HYPERCALL_ENTRY(name) \
: __HYPERCALL_CLOBBER1); \
(type)__res; \
})
#define _hypercall2(type, name, a1, a2) \
({ \
long __res, __ign1, __ign2; \
asm volatile ( \
"call %[call]" \
: "=a" (__res), "=b" (__ign1), "=c" (__ign2) \
: "1" ((long)(a1)), "2" ((long)(a2)), \
[call] "m" (hypercall_page[__HYPERVISOR_##name]) \
: "memory" ); \
__HYPERCALL_DECLS; \
__HYPERCALL_2ARG(a1, a2); \
asm volatile (__HYPERCALL \
: __HYPERCALL_2PARAM \
: __HYPERCALL_ENTRY(name) \
: __HYPERCALL_CLOBBER2); \
(type)__res; \
})
#define _hypercall3(type, name, a1, a2, a3) \
({ \
long __res, __ign1, __ign2, __ign3; \
asm volatile ( \
"call %[call]" \
: "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
"=d" (__ign3) \
: "1" ((long)(a1)), "2" ((long)(a2)), \
"3" ((long)(a3)), \
[call] "m" (hypercall_page[__HYPERVISOR_##name]) \
: "memory" ); \
__HYPERCALL_DECLS; \
__HYPERCALL_3ARG(a1, a2, a3); \
asm volatile (__HYPERCALL \
: __HYPERCALL_3PARAM \
: __HYPERCALL_ENTRY(name) \
: __HYPERCALL_CLOBBER3); \
(type)__res; \
})
#define _hypercall4(type, name, a1, a2, a3, a4) \
({ \
long __res, __ign1, __ign2, __ign3, __ign4; \
asm volatile ( \
"call %[call]" \
: "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
"=d" (__ign3), "=S" (__ign4) \
: "1" ((long)(a1)), "2" ((long)(a2)), \
"3" ((long)(a3)), "4" ((long)(a4)), \
[call] "m" (hypercall_page[__HYPERVISOR_##name]) \
: "memory" ); \
__HYPERCALL_DECLS; \
__HYPERCALL_4ARG(a1, a2, a3, a4); \
asm volatile (__HYPERCALL \
: __HYPERCALL_4PARAM \
: __HYPERCALL_ENTRY(name) \
: __HYPERCALL_CLOBBER4); \
(type)__res; \
})
#define _hypercall5(type, name, a1, a2, a3, a4, a5) \
({ \
long __res, __ign1, __ign2, __ign3, __ign4, __ign5; \
asm volatile ( \
"call %[call]" \
: "=a" (__res), "=b" (__ign1), "=c" (__ign2), \
"=d" (__ign3), "=S" (__ign4), "=D" (__ign5) \
: "1" ((long)(a1)), "2" ((long)(a2)), \
"3" ((long)(a3)), "4" ((long)(a4)), \
"5" ((long)(a5)), \
[call] "m" (hypercall_page[__HYPERVISOR_##name]) \
: "memory" ); \
__HYPERCALL_DECLS; \
__HYPERCALL_5ARG(a1, a2, a3, a4, a5); \
asm volatile (__HYPERCALL \
: __HYPERCALL_5PARAM \
: __HYPERCALL_ENTRY(name) \
: __HYPERCALL_CLOBBER5); \
(type)__res; \
})
@ -152,6 +226,7 @@ HYPERVISOR_stack_switch(unsigned long ss, unsigned long esp)
return _hypercall2(int, stack_switch, ss, esp);
}
#ifdef CONFIG_X86_32
static inline int
HYPERVISOR_set_callbacks(unsigned long event_selector,
unsigned long event_address,
@ -162,6 +237,17 @@ HYPERVISOR_set_callbacks(unsigned long event_selector,
event_selector, event_address,
failsafe_selector, failsafe_address);
}
#else /* CONFIG_X86_64 */
static inline int
HYPERVISOR_set_callbacks(unsigned long event_address,
unsigned long failsafe_address,
unsigned long syscall_address)
{
return _hypercall3(int, set_callbacks,
event_address, failsafe_address,
syscall_address);
}
#endif /* CONFIG_X86_{32,64} */
static inline int
HYPERVISOR_callback_op(int cmd, void *arg)
@ -223,12 +309,12 @@ static inline int
HYPERVISOR_update_va_mapping(unsigned long va, pte_t new_val,
unsigned long flags)
{
unsigned long pte_hi = 0;
#ifdef CONFIG_X86_PAE
pte_hi = new_val.pte_high;
#endif
return _hypercall4(int, update_va_mapping, va,
new_val.pte_low, pte_hi, flags);
if (sizeof(new_val) == sizeof(long))
return _hypercall3(int, update_va_mapping, va,
new_val.pte, flags);
else
return _hypercall4(int, update_va_mapping, va,
new_val.pte, new_val.pte >> 32, flags);
}
static inline int
@ -281,12 +367,13 @@ static inline int
HYPERVISOR_update_va_mapping_otherdomain(unsigned long va, pte_t new_val,
unsigned long flags, domid_t domid)
{
unsigned long pte_hi = 0;
#ifdef CONFIG_X86_PAE
pte_hi = new_val.pte_high;
#endif
return _hypercall5(int, update_va_mapping_otherdomain, va,
new_val.pte_low, pte_hi, flags, domid);
if (sizeof(new_val) == sizeof(long))
return _hypercall4(int, update_va_mapping_otherdomain, va,
new_val.pte, flags, domid);
else
return _hypercall5(int, update_va_mapping_otherdomain, va,
new_val.pte, new_val.pte >> 32,
flags, domid);
}
static inline int
@ -301,6 +388,14 @@ HYPERVISOR_vcpu_op(int cmd, int vcpuid, void *extra_args)
return _hypercall3(int, vcpu_op, cmd, vcpuid, extra_args);
}
#ifdef CONFIG_X86_64
static inline int
HYPERVISOR_set_segment_base(int reg, unsigned long value)
{
return _hypercall2(int, set_segment_base, reg, value);
}
#endif
static inline int
HYPERVISOR_suspend(unsigned long srec)
{
@ -327,14 +422,14 @@ MULTI_update_va_mapping(struct multicall_entry *mcl, unsigned long va,
{
mcl->op = __HYPERVISOR_update_va_mapping;
mcl->args[0] = va;
#ifdef CONFIG_X86_PAE
mcl->args[1] = new_val.pte_low;
mcl->args[2] = new_val.pte_high;
#else
mcl->args[1] = new_val.pte_low;
mcl->args[2] = 0;
#endif
mcl->args[3] = flags;
if (sizeof(new_val) == sizeof(long)) {
mcl->args[1] = new_val.pte;
mcl->args[2] = flags;
} else {
mcl->args[1] = new_val.pte;
mcl->args[2] = new_val.pte >> 32;
mcl->args[3] = flags;
}
}
static inline void
@ -354,15 +449,16 @@ MULTI_update_va_mapping_otherdomain(struct multicall_entry *mcl, unsigned long v
{
mcl->op = __HYPERVISOR_update_va_mapping_otherdomain;
mcl->args[0] = va;
#ifdef CONFIG_X86_PAE
mcl->args[1] = new_val.pte_low;
mcl->args[2] = new_val.pte_high;
#else
mcl->args[1] = new_val.pte_low;
mcl->args[2] = 0;
#endif
mcl->args[3] = flags;
mcl->args[4] = domid;
if (sizeof(new_val) == sizeof(long)) {
mcl->args[1] = new_val.pte;
mcl->args[2] = flags;
mcl->args[3] = domid;
} else {
mcl->args[1] = new_val.pte;
mcl->args[2] = new_val.pte >> 32;
mcl->args[3] = flags;
mcl->args[4] = domid;
}
}
static inline void
@ -370,10 +466,15 @@ MULTI_update_descriptor(struct multicall_entry *mcl, u64 maddr,
struct desc_struct desc)
{
mcl->op = __HYPERVISOR_update_descriptor;
mcl->args[0] = maddr;
mcl->args[1] = maddr >> 32;
mcl->args[2] = desc.a;
mcl->args[3] = desc.b;
if (sizeof(maddr) == sizeof(long)) {
mcl->args[0] = maddr;
mcl->args[1] = *(unsigned long *)&desc;
} else {
mcl->args[0] = maddr;
mcl->args[1] = maddr >> 32;
mcl->args[2] = desc.a;
mcl->args[3] = desc.b;
}
}
static inline void

View file

@ -1,13 +1,13 @@
/******************************************************************************
* arch-x86_32.h
*
* Guest OS interface to x86 32-bit Xen.
* Guest OS interface to x86 Xen.
*
* Copyright (c) 2004, K A Fraser
*/
#ifndef __XEN_PUBLIC_ARCH_X86_32_H__
#define __XEN_PUBLIC_ARCH_X86_32_H__
#ifndef __ASM_X86_XEN_INTERFACE_H
#define __ASM_X86_XEN_INTERFACE_H
#ifdef __XEN__
#define __DEFINE_GUEST_HANDLE(name, type) \
@ -57,6 +57,17 @@ DEFINE_GUEST_HANDLE(long);
DEFINE_GUEST_HANDLE(void);
#endif
#ifndef HYPERVISOR_VIRT_START
#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START)
#endif
#ifndef machine_to_phys_mapping
#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
#endif
/* Maximum number of virtual CPUs in multi-processor guests. */
#define MAX_VIRT_CPUS 32
/*
* SEGMENT DESCRIPTOR TABLES
*/
@ -70,59 +81,22 @@ DEFINE_GUEST_HANDLE(void);
#define FIRST_RESERVED_GDT_BYTE (FIRST_RESERVED_GDT_PAGE * 4096)
#define FIRST_RESERVED_GDT_ENTRY (FIRST_RESERVED_GDT_BYTE / 8)
/*
* 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 0xe019 /* GDT index 259 */
#define FLAT_RING1_DS 0xe021 /* GDT index 260 */
#define FLAT_RING1_SS 0xe021 /* GDT index 260 */
#define FLAT_RING3_CS 0xe02b /* GDT index 261 */
#define FLAT_RING3_DS 0xe033 /* GDT index 262 */
#define FLAT_RING3_SS 0xe033 /* GDT index 262 */
#define FLAT_KERNEL_CS FLAT_RING1_CS
#define FLAT_KERNEL_DS FLAT_RING1_DS
#define FLAT_KERNEL_SS FLAT_RING1_SS
#define FLAT_USER_CS FLAT_RING3_CS
#define FLAT_USER_DS FLAT_RING3_DS
#define FLAT_USER_SS FLAT_RING3_SS
/* And the trap vector is... */
#define TRAP_INSTR "int $0x82"
/*
* Virtual addresses beyond this are not modifiable by guest OSes. The
* machine->physical mapping table starts at this address, read-only.
*/
#ifdef CONFIG_X86_PAE
#define __HYPERVISOR_VIRT_START 0xF5800000
#else
#define __HYPERVISOR_VIRT_START 0xFC000000
#endif
#ifndef HYPERVISOR_VIRT_START
#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START)
#endif
#ifndef machine_to_phys_mapping
#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
#endif
/* Maximum number of virtual CPUs in multi-processor guests. */
#define MAX_VIRT_CPUS 32
#ifndef __ASSEMBLY__
/*
* Send an array of these to HYPERVISOR_set_trap_table()
* The privilege level specifies which modes may enter a trap via a software
* interrupt. On x86/64, since rings 1 and 2 are unavailable, we allocate
* privilege levels as follows:
* Level == 0: Noone may enter
* Level == 1: Kernel may enter
* Level == 2: Kernel may enter
* Level == 3: Everyone may enter
*/
#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))
#ifndef __ASSEMBLY__
struct trap_info {
uint8_t vector; /* exception vector */
uint8_t flags; /* 0-3: privilege level; 4: clear event enable? */
@ -131,32 +105,21 @@ struct trap_info {
};
DEFINE_GUEST_HANDLE_STRUCT(trap_info);
struct cpu_user_regs {
uint32_t ebx;
uint32_t ecx;
uint32_t edx;
uint32_t esi;
uint32_t edi;
uint32_t ebp;
uint32_t eax;
uint16_t error_code; /* private */
uint16_t entry_vector; /* private */
uint32_t eip;
uint16_t cs;
uint8_t saved_upcall_mask;
uint8_t _pad0;
uint32_t eflags; /* eflags.IF == !saved_upcall_mask */
uint32_t esp;
uint16_t ss, _pad1;
uint16_t es, _pad2;
uint16_t ds, _pad3;
uint16_t fs, _pad4;
uint16_t gs, _pad5;
struct arch_shared_info {
unsigned long max_pfn; /* max pfn that appears in table */
/* Frame containing list of mfns containing list of mfns containing p2m. */
unsigned long pfn_to_mfn_frame_list_list;
unsigned long nmi_reason;
};
DEFINE_GUEST_HANDLE_STRUCT(cpu_user_regs);
#endif /* !__ASSEMBLY__ */
typedef uint64_t tsc_timestamp_t; /* RDTSC timestamp */
#ifdef CONFIG_X86_32
#include "interface_32.h"
#else
#include "interface_64.h"
#endif
#ifndef __ASSEMBLY__
/*
* The following is all CPU context. Note that the fpu_ctxt block is filled
* in by FXSAVE if the CPU has feature FXSR; otherwise FSAVE is used.
@ -173,33 +136,29 @@ struct vcpu_guest_context {
unsigned long ldt_base, ldt_ents; /* LDT (linear address, # ents) */
unsigned long gdt_frames[16], gdt_ents; /* GDT (machine frames, # ents) */
unsigned long kernel_ss, kernel_sp; /* Virtual TSS (only SS1/SP1) */
/* NB. User pagetable on x86/64 is placed in ctrlreg[1]. */
unsigned long ctrlreg[8]; /* CR0-CR7 (control registers) */
unsigned long debugreg[8]; /* DB0-DB7 (debug registers) */
#ifdef __i386__
unsigned long event_callback_cs; /* CS:EIP of event callback */
unsigned long event_callback_eip;
unsigned long failsafe_callback_cs; /* CS:EIP of failsafe callback */
unsigned long failsafe_callback_eip;
#else
unsigned long event_callback_eip;
unsigned long failsafe_callback_eip;
unsigned long syscall_callback_eip;
#endif
unsigned long vm_assist; /* VMASST_TYPE_* bitmap */
#ifdef __x86_64__
/* Segment base addresses. */
uint64_t fs_base;
uint64_t gs_base_kernel;
uint64_t gs_base_user;
#endif
};
DEFINE_GUEST_HANDLE_STRUCT(vcpu_guest_context);
struct arch_shared_info {
unsigned long max_pfn; /* max pfn that appears in table */
/* Frame containing list of mfns containing list of mfns containing p2m. */
unsigned long pfn_to_mfn_frame_list_list;
unsigned long nmi_reason;
};
struct arch_vcpu_info {
unsigned long cr2;
unsigned long pad[5]; /* sizeof(struct vcpu_info) == 64 */
};
struct xen_callback {
unsigned long cs;
unsigned long eip;
};
#endif /* !__ASSEMBLY__ */
#endif /* !__ASSEMBLY__ */
/*
* Prefix forces emulation of some non-trapping instructions.
@ -213,4 +172,4 @@ struct xen_callback {
#define XEN_CPUID XEN_EMULATE_PREFIX "cpuid"
#endif
#endif
#endif /* __ASM_X86_XEN_INTERFACE_H */

View file

@ -0,0 +1,97 @@
/******************************************************************************
* arch-x86_32.h
*
* Guest OS interface to x86 32-bit Xen.
*
* Copyright (c) 2004, K A Fraser
*/
#ifndef __ASM_X86_XEN_INTERFACE_32_H
#define __ASM_X86_XEN_INTERFACE_32_H
/*
* 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 0xe019 /* GDT index 259 */
#define FLAT_RING1_DS 0xe021 /* GDT index 260 */
#define FLAT_RING1_SS 0xe021 /* GDT index 260 */
#define FLAT_RING3_CS 0xe02b /* GDT index 261 */
#define FLAT_RING3_DS 0xe033 /* GDT index 262 */
#define FLAT_RING3_SS 0xe033 /* GDT index 262 */
#define FLAT_KERNEL_CS FLAT_RING1_CS
#define FLAT_KERNEL_DS FLAT_RING1_DS
#define FLAT_KERNEL_SS FLAT_RING1_SS
#define FLAT_USER_CS FLAT_RING3_CS
#define FLAT_USER_DS FLAT_RING3_DS
#define FLAT_USER_SS FLAT_RING3_SS
/* And the trap vector is... */
#define TRAP_INSTR "int $0x82"
/*
* 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 0xF5800000
#ifndef __ASSEMBLY__
struct cpu_user_regs {
uint32_t ebx;
uint32_t ecx;
uint32_t edx;
uint32_t esi;
uint32_t edi;
uint32_t ebp;
uint32_t eax;
uint16_t error_code; /* private */
uint16_t entry_vector; /* private */
uint32_t eip;
uint16_t cs;
uint8_t saved_upcall_mask;
uint8_t _pad0;
uint32_t eflags; /* eflags.IF == !saved_upcall_mask */
uint32_t esp;
uint16_t ss, _pad1;
uint16_t es, _pad2;
uint16_t ds, _pad3;
uint16_t fs, _pad4;
uint16_t gs, _pad5;
};
DEFINE_GUEST_HANDLE_STRUCT(cpu_user_regs);
typedef uint64_t tsc_timestamp_t; /* RDTSC timestamp */
struct arch_vcpu_info {
unsigned long cr2;
unsigned long pad[5]; /* sizeof(struct vcpu_info) == 64 */
};
struct xen_callback {
unsigned long cs;
unsigned long eip;
};
typedef struct xen_callback xen_callback_t;
#define XEN_CALLBACK(__cs, __eip) \
((struct xen_callback){ .cs = (__cs), .eip = (unsigned long)(__eip) })
#endif /* !__ASSEMBLY__ */
/*
* Page-directory addresses above 4GB do not fit into architectural %cr3.
* When accessing %cr3, or equivalent field in vcpu_guest_context, guests
* must use the following accessor macros to pack/unpack valid MFNs.
*
* Note that Xen is using the fact that the pagetable base is always
* page-aligned, and putting the 12 MSB of the address into the 12 LSB
* of cr3.
*/
#define xen_pfn_to_cr3(pfn) (((unsigned)(pfn) << 12) | ((unsigned)(pfn) >> 20))
#define xen_cr3_to_pfn(cr3) (((unsigned)(cr3) >> 12) | ((unsigned)(cr3) << 20))
#endif /* __ASM_X86_XEN_INTERFACE_32_H */

View file

@ -0,0 +1,159 @@
#ifndef __ASM_X86_XEN_INTERFACE_64_H
#define __ASM_X86_XEN_INTERFACE_64_H
/*
* 64-bit segment selectors
* 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_RING3_CS32 0xe023 /* GDT index 260 */
#define FLAT_RING3_CS64 0xe033 /* GDT index 261 */
#define FLAT_RING3_DS32 0xe02b /* GDT index 262 */
#define FLAT_RING3_DS64 0x0000 /* NULL selector */
#define FLAT_RING3_SS32 0xe02b /* GDT index 262 */
#define FLAT_RING3_SS64 0xe02b /* GDT index 262 */
#define FLAT_KERNEL_DS64 FLAT_RING3_DS64
#define FLAT_KERNEL_DS32 FLAT_RING3_DS32
#define FLAT_KERNEL_DS FLAT_KERNEL_DS64
#define FLAT_KERNEL_CS64 FLAT_RING3_CS64
#define FLAT_KERNEL_CS32 FLAT_RING3_CS32
#define FLAT_KERNEL_CS FLAT_KERNEL_CS64
#define FLAT_KERNEL_SS64 FLAT_RING3_SS64
#define FLAT_KERNEL_SS32 FLAT_RING3_SS32
#define FLAT_KERNEL_SS FLAT_KERNEL_SS64
#define FLAT_USER_DS64 FLAT_RING3_DS64
#define FLAT_USER_DS32 FLAT_RING3_DS32
#define FLAT_USER_DS FLAT_USER_DS64
#define FLAT_USER_CS64 FLAT_RING3_CS64
#define FLAT_USER_CS32 FLAT_RING3_CS32
#define FLAT_USER_CS FLAT_USER_CS64
#define FLAT_USER_SS64 FLAT_RING3_SS64
#define FLAT_USER_SS32 FLAT_RING3_SS32
#define FLAT_USER_SS FLAT_USER_SS64
#define __HYPERVISOR_VIRT_START 0xFFFF800000000000
#define __HYPERVISOR_VIRT_END 0xFFFF880000000000
#define __MACH2PHYS_VIRT_START 0xFFFF800000000000
#define __MACH2PHYS_VIRT_END 0xFFFF804000000000
#ifndef HYPERVISOR_VIRT_START
#define HYPERVISOR_VIRT_START mk_unsigned_long(__HYPERVISOR_VIRT_START)
#define HYPERVISOR_VIRT_END mk_unsigned_long(__HYPERVISOR_VIRT_END)
#endif
#define MACH2PHYS_VIRT_START mk_unsigned_long(__MACH2PHYS_VIRT_START)
#define MACH2PHYS_VIRT_END mk_unsigned_long(__MACH2PHYS_VIRT_END)
#define MACH2PHYS_NR_ENTRIES ((MACH2PHYS_VIRT_END-MACH2PHYS_VIRT_START)>>3)
#ifndef machine_to_phys_mapping
#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
#endif
/*
* int HYPERVISOR_set_segment_base(unsigned int which, unsigned long base)
* @which == SEGBASE_* ; @base == 64-bit base address
* Returns 0 on success.
*/
#define SEGBASE_FS 0
#define SEGBASE_GS_USER 1
#define SEGBASE_GS_KERNEL 2
#define SEGBASE_GS_USER_SEL 3 /* Set user %gs specified in base[15:0] */
/*
* int HYPERVISOR_iret(void)
* All arguments are on the kernel stack, in the following format.
* Never returns if successful. Current kernel context is lost.
* The saved CS is mapped as follows:
* RING0 -> RING3 kernel mode.
* RING1 -> RING3 kernel mode.
* RING2 -> RING3 kernel mode.
* RING3 -> RING3 user mode.
* However RING0 indicates that the guest kernel should return to iteself
* directly with
* orb $3,1*8(%rsp)
* iretq
* If flags contains VGCF_in_syscall:
* Restore RAX, RIP, RFLAGS, RSP.
* Discard R11, RCX, CS, SS.
* Otherwise:
* Restore RAX, R11, RCX, CS:RIP, RFLAGS, SS:RSP.
* All other registers are saved on hypercall entry and restored to user.
*/
/* Guest exited in SYSCALL context? Return to guest with SYSRET? */
#define _VGCF_in_syscall 8
#define VGCF_in_syscall (1<<_VGCF_in_syscall)
#define VGCF_IN_SYSCALL VGCF_in_syscall
#ifndef __ASSEMBLY__
struct iret_context {
/* Top of stack (%rsp at point of hypercall). */
uint64_t rax, r11, rcx, flags, rip, cs, rflags, rsp, ss;
/* Bottom of iret stack frame. */
};
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
/* Anonymous union includes both 32- and 64-bit names (e.g., eax/rax). */
#define __DECL_REG(name) union { \
uint64_t r ## name, e ## name; \
uint32_t _e ## name; \
}
#else
/* Non-gcc sources must always use the proper 64-bit name (e.g., rax). */
#define __DECL_REG(name) uint64_t r ## name
#endif
struct cpu_user_regs {
uint64_t r15;
uint64_t r14;
uint64_t r13;
uint64_t r12;
__DECL_REG(bp);
__DECL_REG(bx);
uint64_t r11;
uint64_t r10;
uint64_t r9;
uint64_t r8;
__DECL_REG(ax);
__DECL_REG(cx);
__DECL_REG(dx);
__DECL_REG(si);
__DECL_REG(di);
uint32_t error_code; /* private */
uint32_t entry_vector; /* private */
__DECL_REG(ip);
uint16_t cs, _pad0[1];
uint8_t saved_upcall_mask;
uint8_t _pad1[3];
__DECL_REG(flags); /* rflags.IF == !saved_upcall_mask */
__DECL_REG(sp);
uint16_t ss, _pad2[3];
uint16_t es, _pad3[3];
uint16_t ds, _pad4[3];
uint16_t fs, _pad5[3]; /* Non-zero => takes precedence over fs_base. */
uint16_t gs, _pad6[3]; /* Non-zero => takes precedence over gs_base_usr. */
};
DEFINE_GUEST_HANDLE_STRUCT(cpu_user_regs);
#undef __DECL_REG
#define xen_pfn_to_cr3(pfn) ((unsigned long)(pfn) << 12)
#define xen_cr3_to_pfn(cr3) ((unsigned long)(cr3) >> 12)
struct arch_vcpu_info {
unsigned long cr2;
unsigned long pad; /* sizeof(vcpu_info_t) == 64 */
};
typedef unsigned long xen_callback_t;
#define XEN_CALLBACK(__cs, __rip) \
((unsigned long)(__rip))
#endif /* !__ASSEMBLY__ */
#endif /* __ASM_X86_XEN_INTERFACE_64_H */

View file

@ -148,13 +148,17 @@ static inline pte_t __pte_ma(pteval_t x)
}
#define pmd_val_ma(v) ((v).pmd)
#ifdef __PAGETABLE_PUD_FOLDED
#define pud_val_ma(v) ((v).pgd.pgd)
#else
#define pud_val_ma(v) ((v).pud)
#endif
#define __pmd_ma(x) ((pmd_t) { (x) } )
#define pgd_val_ma(x) ((x).pgd)
xmaddr_t arbitrary_virt_to_machine(unsigned long address);
xmaddr_t arbitrary_virt_to_machine(void *address);
void make_lowmem_page_readonly(void *vaddr);
void make_lowmem_page_readwrite(void *vaddr);

View file

@ -26,6 +26,8 @@ struct debugfs_blob_wrapper {
unsigned long size;
};
extern struct dentry *arch_debugfs_dir;
#if defined(CONFIG_DEBUG_FS)
/* declared over in file.c */

View file

@ -5,11 +5,12 @@ extern struct console xenboot_console;
#ifdef CONFIG_HVC_XEN
void xen_console_resume(void);
#else
static inline void xen_console_resume(void) { }
#endif
void xen_raw_console_write(const char *str);
void xen_raw_printk(const char *fmt, ...);
#else
static inline void xen_console_resume(void) { }
static inline void xen_raw_console_write(const char *str) { }
static inline void xen_raw_printk(const char *fmt, ...) { }
#endif
#endif /* XEN_HVC_CONSOLE_H */

View file

@ -82,9 +82,9 @@
*/
#define CALLBACKOP_register 0
struct callback_register {
uint16_t type;
uint16_t flags;
struct xen_callback address;
uint16_t type;
uint16_t flags;
xen_callback_t address;
};
/*

View file

@ -11,4 +11,7 @@ void xen_post_suspend(int suspend_cancelled);
void xen_mm_pin_all(void);
void xen_mm_unpin_all(void);
void xen_timer_resume(void);
void xen_arch_resume(void);
#endif /* INCLUDE_XEN_OPS_H */