From fd654d0a4d8622654a1bfb31030e355f39718f3d Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Mon, 14 Aug 2006 11:35:33 -0600 Subject: [PATCH 01/58] [IA64] update xmexample.vti Keep alignment with new QEMU and control panel configuration Signed-off-by: Yongkang You --- tools/examples/xmexample.vti | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/tools/examples/xmexample.vti b/tools/examples/xmexample.vti index fad565d160..77f55ae23e 100644 --- a/tools/examples/xmexample.vti +++ b/tools/examples/xmexample.vti @@ -37,11 +37,9 @@ name = "ExampleVTIDomain" # Optionally define mac and/or bridge for the network interfaces. # Random MACs are assigned if not given. -#vif = [ 'type=ioemu, mac=00:16:3e:00:00:11, bridge=xenbr0' ] +#vif = [ 'type=ioemu, mac=00:16:3e:00:00:11, bridge=xenbr0, model=ne2k_pci' ] # type=ioemu specify the NIC is an ioemu device not netfront vif = [ 'type=ioemu, bridge=xenbr0' ] -# for multiple NICs in device model, 3 in this example -#vif = [ 'type=ioemu, bridge=xenbr0', 'type=ioemu', 'type=ioemu'] #---------------------------------------------------------------------------- # Define the disk devices you want the domain to have access to, and @@ -51,7 +49,7 @@ vif = [ 'type=ioemu, bridge=xenbr0' ] # and MODE is r for read-only, w for read-write. #disk = [ 'phy:hda1,hda1,r' ] -disk = [ 'file:/var/images/xenia64.img,ioemu:hda,w' ] +disk = [ 'file:/var/images/xenia64.img,hda,w', ',hdc:cdrom,r' ] #---------------------------------------------------------------------------- # Set according to whether you want the domain restarted when it exits. @@ -66,13 +64,6 @@ disk = [ 'file:/var/images/xenia64.img,ioemu:hda,w' ] # New stuff device_model = '/usr/' + arch_libdir + '/xen/bin/qemu-dm' -# Advanced users only. Don't touch if you don't know what you're doing -memmap = '/usr/lib/xen/boot/mem-map.sxp' - -#----------------------------------------------------------------------------- -# Disk image for -#cdrom= - #----------------------------------------------------------------------------- # boot on floppy (a), hard disk (c) or CD-ROM (d) #boot=[a|c|d] @@ -89,8 +80,17 @@ sdl=1 vnc=0 #---------------------------------------------------------------------------- -# enable spawning vncviewer(only valid when vnc=1), default = 1 -vncviewer=0 +# set VNC display number, default = domid +#vncdisplay=1 + +#---------------------------------------------------------------------------- +# try to find an unused port for the VNC server, default = 1 +#vncunused=1 + +#---------------------------------------------------------------------------- +# enable spawning vncviewer for domain's console +# (only valid when vnc=1), default = 0 +#vncconsole=0 #---------------------------------------------------------------------------- # no graphics, use serial port @@ -106,15 +106,13 @@ stdvga=0 serial='pty' #----------------------------------------------------------------------------- -# enable audio support -#enable-audio=1 - +# enable sound card support, [sb16|es1370|all|..,..], default none +#soundhw='sb16' #----------------------------------------------------------------------------- # set the real time clock to local time [default=0 i.e. set to utc] #localtime=1 - #----------------------------------------------------------------------------- # start in full screen #full-screen=1 diff -r 42cab8724273 tools/libxc/xc_ia64_stubs.c From 59537bf00b6766cbf556574b95fd50ad394249c4 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Mon, 14 Aug 2006 11:46:40 -0600 Subject: [PATCH 02/58] [IA64] vti bugs fix Bug fixes: - Do not read long-format vhpt as short-format. - Avoid infinite loop in vtlb_purge. Signed-off-by: Tristan Gingold --- xen/arch/ia64/vmx/vtlb.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/xen/arch/ia64/vmx/vtlb.c b/xen/arch/ia64/vmx/vtlb.c index cfb84eaa3b..1fffd1366d 100644 --- a/xen/arch/ia64/vmx/vtlb.c +++ b/xen/arch/ia64/vmx/vtlb.c @@ -214,12 +214,22 @@ u64 guest_vhpt_lookup(u64 iha, u64 *pte) { u64 ret; thash_data_t * data; + PTA vpta; + data = vhpt_lookup(iha); if (data == NULL) { data = vtlb_lookup(current, iha, DSIDE_TLB); if (data != NULL) thash_vhpt_insert(current, data->page_flags, data->itir ,iha); } + + /* VHPT long format is not read. */ + vmx_vcpu_get_pta(current, &vpta.val); + if (vpta.vf == 1) { + *pte = 0; + return 0; + } + asm volatile ("rsm psr.ic|psr.i;;" "srlz.d;;" "ld8.s r9=[%1];;" @@ -231,7 +241,7 @@ u64 guest_vhpt_lookup(u64 iha, u64 *pte) "ssm psr.ic;;" "srlz.d;;" "ssm psr.i;;" - : "=r"(ret) : "r"(iha), "r"(pte):"memory"); + : "=r"(ret) : "r"(iha), "r"(pte):"memory"); return ret; } @@ -257,7 +267,8 @@ void vtlb_purge(VCPU *v, u64 va, u64 ps) psbits &= ~(1UL << ps); def_size = PSIZE(ps); vrr.ps = ps; - while (curadr < end) { + /* Be careful about overflow. */ + while (curadr < end && curadr >= start) { cur = vsa_thash(hcb->pta, curadr, vrr.rrval, &tag); while (cur) { if (cur->etag == tag && cur->ps == ps) From 18a23ebe612bc869eda0eff1a2634b348b0f3226 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Mon, 14 Aug 2006 13:20:40 -0600 Subject: [PATCH 03/58] [IA64] convert stats to perfc, get rid of unsafe hypercall Convert remaining stat counter to perfc. Get rid of unsafe hypercall. Signed-off-by: Tristan Gingold --- xen/arch/ia64/xen/domain.c | 1 - xen/arch/ia64/xen/faults.c | 1 - xen/arch/ia64/xen/hypercall.c | 32 -------- xen/arch/ia64/xen/privop.c | 1 - xen/arch/ia64/xen/privop_stat.c | 113 +++++++++++++++-------------- xen/arch/ia64/xen/vcpu.c | 4 +- xen/arch/ia64/xen/vhpt.c | 12 ++- xen/include/asm-ia64/config.h | 6 ++ xen/include/asm-ia64/perfc.h | 12 ++- xen/include/asm-ia64/perfc_defn.h | 17 +++++ xen/include/asm-ia64/privop_stat.h | 44 ++++++++--- xen/include/asm-ia64/vhpt.h | 2 +- 12 files changed, 131 insertions(+), 114 deletions(-) diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index 86ff7d85f5..5258c40f95 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -47,7 +47,6 @@ #include #include #include -#include unsigned long dom0_size = 512*1024*1024; unsigned long dom0_align = 64*1024*1024; diff --git a/xen/arch/ia64/xen/faults.c b/xen/arch/ia64/xen/faults.c index a37dfc8c80..16bef26b31 100644 --- a/xen/arch/ia64/xen/faults.c +++ b/xen/arch/ia64/xen/faults.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff --git a/xen/arch/ia64/xen/hypercall.c b/xen/arch/ia64/xen/hypercall.c index 97924b8776..6fcc1ef72e 100644 --- a/xen/arch/ia64/xen/hypercall.c +++ b/xen/arch/ia64/xen/hypercall.c @@ -28,7 +28,6 @@ #include #include #include -#include static long do_physdev_op_compat(XEN_GUEST_HANDLE(physdev_op_t) uop); static long do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg); @@ -275,11 +274,6 @@ fw_hypercall (struct pt_regs *regs) return IA64_NO_FAULT; } -/* opt_unsafe_hypercall: If true, unsafe debugging hypercalls are allowed. - These can create security hole. */ -static int opt_unsafe_hypercall = 0; -boolean_param("unsafe_hypercall", opt_unsafe_hypercall); - IA64FAULT ia64_hypercall (struct pt_regs *regs) { @@ -287,32 +281,6 @@ ia64_hypercall (struct pt_regs *regs) unsigned long index = regs->r2; int privlvl = (regs->cr_ipsr & IA64_PSR_CPL) >> IA64_PSR_CPL0_BIT; - if (index >= FW_HYPERCALL_FIRST_USER) { - /* Note: user hypercalls are not safe, since Xen doesn't - check memory access privilege: Xen does not deny reading - or writing to kernel memory. */ - if (!opt_unsafe_hypercall) { - printf("user xen/ia64 hypercalls disabled\n"); - regs->r8 = -1; - } - else switch (index) { - case 0xffff: - regs->r8 = dump_privop_counts_to_user( - (char *) vcpu_get_gr(v,32), - (int) vcpu_get_gr(v,33)); - break; - case 0xfffe: - regs->r8 = zero_privop_counts_to_user( - (char *) vcpu_get_gr(v,32), - (int) vcpu_get_gr(v,33)); - break; - default: - printf("unknown user xen/ia64 hypercall %lx\n", index); - regs->r8 = do_ni_hypercall(); - } - return IA64_NO_FAULT; - } - /* Hypercalls are only allowed by kernel. Kernel checks memory accesses. */ if (VMX_DOMAIN(v) ? (privlvl != 0) : (privlvl != 2)) { diff --git a/xen/arch/ia64/xen/privop.c b/xen/arch/ia64/xen/privop.c index 0172dd87c3..2053317e51 100644 --- a/xen/arch/ia64/xen/privop.c +++ b/xen/arch/ia64/xen/privop.c @@ -13,7 +13,6 @@ #include #include #include -#include long priv_verbose=0; unsigned long privop_trace = 0; diff --git a/xen/arch/ia64/xen/privop_stat.c b/xen/arch/ia64/xen/privop_stat.c index 466b5b1ffd..5bdd5adc6a 100644 --- a/xen/arch/ia64/xen/privop_stat.c +++ b/xen/arch/ia64/xen/privop_stat.c @@ -1,26 +1,55 @@ -#include -#include #include -#include +#include +#include +#include +#include -#ifdef PRIVOP_ADDR_COUNT -#define PRIVOP_COUNT_NINSTS 2 -#define PRIVOP_COUNT_NADDRS 30 +#ifdef CONFIG_PRIVOP_ADDRS struct privop_addr_count { - const char *instname; unsigned long addr[PRIVOP_COUNT_NADDRS]; - unsigned long count[PRIVOP_COUNT_NADDRS]; - unsigned long overflow; + unsigned int count[PRIVOP_COUNT_NADDRS]; + unsigned int overflow; + atomic_t *perfc_addr; + atomic_t *perfc_count; + atomic_t *perfc_overflow; }; +#undef PERFCOUNTER +#define PERFCOUNTER(var, name) -static struct privop_addr_count privop_addr_counter[PRIVOP_COUNT_NINSTS] = { - [_GET_IFA] = { "=ifa", { 0 }, { 0 }, 0 }, - [_THASH] = { "thash", { 0 }, { 0 }, 0 } +#undef PERFCOUNTER_CPU +#define PERFCOUNTER_CPU(var, name) + +#undef PERFCOUNTER_ARRAY +#define PERFCOUNTER_ARRAY(var, name, size) + +#undef PERFSTATUS +#define PERFSTATUS(var, name) + +#undef PERFSTATUS_CPU +#define PERFSTATUS_CPU(var, name) + +#undef PERFSTATUS_ARRAY +#define PERFSTATUS_ARRAY(var, name, size) + +#undef PERFPRIVOPADDR +#define PERFPRIVOPADDR(name) \ + { \ + { 0 }, { 0 }, 0, \ + perfcounters.privop_addr_##name##_addr, \ + perfcounters.privop_addr_##name##_count, \ + perfcounters.privop_addr_##name##_overflow \ + }, + +static struct privop_addr_count privop_addr_counter[] = { +#include }; -void privop_count_addr(unsigned long iip, int inst) +#define PRIVOP_COUNT_NINSTS \ + (sizeof(privop_addr_counter) / sizeof(privop_addr_counter[0])) + +void privop_count_addr(unsigned long iip, enum privop_inst inst) { struct privop_addr_count *v = &privop_addr_counter[inst]; int i; @@ -41,29 +70,28 @@ void privop_count_addr(unsigned long iip, int inst) v->overflow++;; } -static int dump_privop_addrs(char *buf) +void gather_privop_addrs(void) { int i, j; - char *s = buf; - s += sprintf(s, "Privop addresses:\n"); + atomic_t *v; for (i = 0; i < PRIVOP_COUNT_NINSTS; i++) { - struct privop_addr_count *v = &privop_addr_counter[i]; - s += sprintf(s, "%s:\n", v->instname); - for (j = 0; j < PRIVOP_COUNT_NADDRS; j++) { - if (!v->addr[j]) - break; - s += sprintf(s, " at 0x%lx #%ld\n", - v->addr[j], v->count[j]); - } - if (v->overflow) - s += sprintf(s, " other #%ld\n", v->overflow); + /* Note: addresses are truncated! */ + v = privop_addr_counter[i].perfc_addr; + for (j = 0; j < PRIVOP_COUNT_NADDRS; j++) + atomic_set(&v[j], privop_addr_counter[i].addr[j]); + + v = privop_addr_counter[i].perfc_count; + for (j = 0; j < PRIVOP_COUNT_NADDRS; j++) + atomic_set(&v[j], privop_addr_counter[i].count[j]); + + atomic_set(privop_addr_counter[i].perfc_overflow, + privop_addr_counter[i].overflow); } - return s - buf; } -static void zero_privop_addrs(void) +void reset_privop_addrs(void) { - int i,j; + int i, j; for (i = 0; i < PRIVOP_COUNT_NINSTS; i++) { struct privop_addr_count *v = &privop_addr_counter[i]; for (j = 0; j < PRIVOP_COUNT_NADDRS; j++) @@ -119,30 +147,3 @@ static const char * const hyperpriv_str[HYPERPRIVOP_MAX+1] = { "=rr", "rr=", "kr=", "fc", "=cpuid", "=pmd", "=ar.eflg", "ar.eflg=" }; #endif - -#define TMPBUFLEN 8*1024 -int dump_privop_counts_to_user(char __user *ubuf, int len) -{ - char buf[TMPBUFLEN]; - int n; - - if (len < TMPBUFLEN) - return -1; - - n = 0; -#ifdef PRIVOP_ADDR_COUNT - n += dump_privop_addrs(buf + n); -#endif - n += dump_vhpt_stats(buf + n); - if (__copy_to_user(ubuf,buf,n)) - return -1; - return n; -} - -int zero_privop_counts_to_user(char __user *ubuf, int len) -{ -#ifdef PRIVOP_ADDR_COUNT - zero_privop_addrs(); -#endif - return 0; -} diff --git a/xen/arch/ia64/xen/vcpu.c b/xen/arch/ia64/xen/vcpu.c index 18fd1989b8..acbc492686 100644 --- a/xen/arch/ia64/xen/vcpu.c +++ b/xen/arch/ia64/xen/vcpu.c @@ -473,7 +473,7 @@ IA64FAULT vcpu_get_iip(VCPU *vcpu, UINT64 *pval) IA64FAULT vcpu_get_ifa(VCPU *vcpu, UINT64 *pval) { - PRIVOP_COUNT_ADDR(vcpu_regs(vcpu),_GET_IFA); + PRIVOP_COUNT_ADDR(vcpu_regs(vcpu), privop_inst_get_ifa); *pval = PSCB(vcpu,ifa); return (IA64_NO_FAULT); } @@ -540,7 +540,7 @@ IA64FAULT vcpu_get_iim(VCPU *vcpu, UINT64 *pval) IA64FAULT vcpu_get_iha(VCPU *vcpu, UINT64 *pval) { - PRIVOP_COUNT_ADDR(vcpu_regs(vcpu),_THASH); + PRIVOP_COUNT_ADDR(vcpu_regs(vcpu), privop_inst_thash); *pval = PSCB(vcpu,iha); return (IA64_NO_FAULT); } diff --git a/xen/arch/ia64/xen/vhpt.c b/xen/arch/ia64/xen/vhpt.c index 9789c0010a..7df751c2c7 100644 --- a/xen/arch/ia64/xen/vhpt.c +++ b/xen/arch/ia64/xen/vhpt.c @@ -261,13 +261,12 @@ void flush_tlb_mask(cpumask_t mask) (cpu, (void (*)(void *))flush_tlb_vhpt_all, NULL, 1, 1); } -int dump_vhpt_stats(char *buf) +#ifdef PERF_COUNTERS +void gather_vhpt_stats(void) { int i, cpu; - char *s = buf; - s += sprintf(s,"VHPT usage (%ld entries):\n", - (unsigned long) VHPT_NUM_ENTRIES); + perfc_set(vhpt_nbr_entries, VHPT_NUM_ENTRIES); for_each_present_cpu (cpu) { struct vhpt_lf_entry *v = __va(per_cpu(vhpt_paddr, cpu)); @@ -276,8 +275,7 @@ int dump_vhpt_stats(char *buf) for (i = 0; i < VHPT_NUM_ENTRIES; i++, v++) if (!(v->ti_tag & INVALID_TI_TAG)) vhpt_valid++; - s += sprintf(s," cpu %d: %ld\n", cpu, vhpt_valid); + perfc_seta(vhpt_valid_entries, cpu, vhpt_valid); } - - return s - buf; } +#endif diff --git a/xen/include/asm-ia64/config.h b/xen/include/asm-ia64/config.h index 12d48f7baf..e1a4962074 100644 --- a/xen/include/asm-ia64/config.h +++ b/xen/include/asm-ia64/config.h @@ -37,6 +37,12 @@ #define MAX_DMADOM_PFN (0x7FFFFFFFUL >> PAGE_SHIFT) /* 31 addressable bits */ +/* If PERFC is used, include privop maps. */ +#ifdef PERF_COUNTERS +#define CONFIG_PRIVOP_ADDRS +#define PRIVOP_COUNT_NADDRS 30 +#endif + #ifndef __ASSEMBLY__ // can't find where this typedef was before?!? diff --git a/xen/include/asm-ia64/perfc.h b/xen/include/asm-ia64/perfc.h index 37a0ac3bc5..0ca2189622 100644 --- a/xen/include/asm-ia64/perfc.h +++ b/xen/include/asm-ia64/perfc.h @@ -1,16 +1,22 @@ #ifndef __ASM_PERFC_H__ #define __ASM_PERFC_H__ -static inline void arch_perfc_printall (void) +#include +#include + +static inline void arch_perfc_printall(void) { } -static inline void arch_perfc_reset (void) +static inline void arch_perfc_reset(void) { + reset_privop_addrs(); } -static inline void arch_perfc_gather (void) +static inline void arch_perfc_gather(void) { + gather_vhpt_stats(); + gather_privop_addrs(); } #endif diff --git a/xen/include/asm-ia64/perfc_defn.h b/xen/include/asm-ia64/perfc_defn.h index f09e90d03a..d3776611ff 100644 --- a/xen/include/asm-ia64/perfc_defn.h +++ b/xen/include/asm-ia64/perfc_defn.h @@ -40,3 +40,20 @@ PERFCOUNTER_ARRAY(fast_hyperprivop, "fast hyperprivops", HYPERPRIVOP_MAX + 1) PERFCOUNTER_ARRAY(slow_reflect, "slow reflection", 0x80) PERFCOUNTER_ARRAY(fast_reflect, "fast reflection", 0x80) + +PERFSTATUS(vhpt_nbr_entries, "nbr of entries per VHPT") +PERFSTATUS_CPU(vhpt_valid_entries, "nbr of valid entries in VHPT") + +#ifdef CONFIG_PRIVOP_ADDRS +#ifndef PERFPRIVOPADDR +#define PERFPRIVOPADDR(name) \ +PERFSTATUS_ARRAY(privop_addr_##name##_addr, "privop-addrs addr " #name, \ + PRIVOP_COUNT_NADDRS) \ +PERFSTATUS_ARRAY(privop_addr_##name##_count, "privop-addrs count " #name, \ + PRIVOP_COUNT_NADDRS) \ +PERFSTATUS(privop_addr_##name##_overflow, "privop-addrs overflow " #name) +#endif + +PERFPRIVOPADDR(get_ifa) +PERFPRIVOPADDR(thash) +#endif diff --git a/xen/include/asm-ia64/privop_stat.h b/xen/include/asm-ia64/privop_stat.h index b48a39ed3c..a5ea27ad82 100644 --- a/xen/include/asm-ia64/privop_stat.h +++ b/xen/include/asm-ia64/privop_stat.h @@ -1,22 +1,46 @@ #ifndef _XEN_UA64_PRIVOP_STAT_H #define _XEN_UA64_PRIVOP_STAT_H -#include +#include -extern int dump_privop_counts_to_user(char *, int); -extern int zero_privop_counts_to_user(char *, int); +#ifdef CONFIG_PRIVOP_ADDRS -#define PRIVOP_ADDR_COUNT +extern void gather_privop_addrs(void); +extern void reset_privop_addrs(void); -#ifdef PRIVOP_ADDR_COUNT +#undef PERFCOUNTER +#define PERFCOUNTER(var, name) + +#undef PERFCOUNTER_CPU +#define PERFCOUNTER_CPU(var, name) + +#undef PERFCOUNTER_ARRAY +#define PERFCOUNTER_ARRAY(var, name, size) + +#undef PERFSTATUS +#define PERFSTATUS(var, name) + +#undef PERFSTATUS_CPU +#define PERFSTATUS_CPU(var, name) + +#undef PERFSTATUS_ARRAY +#define PERFSTATUS_ARRAY(var, name, size) + +#undef PERFPRIVOPADDR +#define PERFPRIVOPADDR(name) privop_inst_##name, + +enum privop_inst { +#include +}; + +#undef PERFPRIVOPADDR -/* INST argument of PRIVOP_COUNT_ADDR. */ -#define _GET_IFA 0 -#define _THASH 1 #define PRIVOP_COUNT_ADDR(regs,inst) privop_count_addr(regs->cr_iip,inst) -extern void privop_count_addr(unsigned long addr, int inst); +extern void privop_count_addr(unsigned long addr, enum privop_inst inst); #else -#define PRIVOP_COUNT_ADDR(x,y) do {} while (0) +#define PRIVOP_COUNT_ADDR(x,y) do {} while (0) +#define gather_privop_addrs() do {} while (0) +#define reset_privop_addrs() do {} while (0) #endif #endif /* _XEN_UA64_PRIVOP_STAT_H */ diff --git a/xen/include/asm-ia64/vhpt.h b/xen/include/asm-ia64/vhpt.h index afd3d7f279..cb4fc30462 100644 --- a/xen/include/asm-ia64/vhpt.h +++ b/xen/include/asm-ia64/vhpt.h @@ -32,7 +32,7 @@ struct vhpt_lf_entry { #define INVALID_TI_TAG 0x8000000000000000L extern void vhpt_init (void); -extern int dump_vhpt_stats(char *buf); +extern void gather_vhpt_stats(void); extern void vhpt_multiple_insert(unsigned long vaddr, unsigned long pte, unsigned long logps); extern void vhpt_insert (unsigned long vadr, unsigned long pte, From 57fce9506eb8e6605cf49f2c6aff819c1147e171 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Mon, 14 Aug 2006 13:30:17 -0600 Subject: [PATCH 04/58] [IA64] initial cleanup of ivt.S This patch reflects a patch I recently posted to the linux-ia64 mailing list to do essentially the same thing for ivt.S in upstream source. I've reformatted the contents of the Xen version of ivt.S so that they are now readable on 80-column displays, in accordance with Linux coding standards. This is really just a first pass at cleaning up this code. In all of this patch, I only changed one line of assembly; there was a 'mov r31=pr;' in entry 23 (daccess_rights) that I changed to 'mov r31=pr;;' which is most likely what was meant. No other instructions were changed. Hopefully, I didn't harm any other white space formatting. Signed-off-by: Al Stone --- xen/arch/ia64/xen/ivt.S | 929 ++++++++++++++++++++++------------------ 1 file changed, 510 insertions(+), 419 deletions(-) diff --git a/xen/arch/ia64/xen/ivt.S b/xen/arch/ia64/xen/ivt.S index 741cd898e4..04b00c4112 100644 --- a/xen/arch/ia64/xen/ivt.S +++ b/xen/arch/ia64/xen/ivt.S @@ -15,7 +15,8 @@ * Fenghua Yu * * 00/08/23 Asit Mallick TLB handling for SMP - * 00/12/20 David Mosberger-Tang DTLB/ITLB handler now uses virtual PT. + * 00/12/20 David Mosberger-Tang DTLB/ITLB handler now + * uses virtual PT. */ /* * This file defines the interruption vector table used by the CPU. @@ -69,10 +70,14 @@ #if 0 /* - * This lets you track the last eight faults that occurred on the CPU. Make sure ar.k2 isn't - * needed for something else before enabling this... + * This lets you track the last eight faults that occurred on the CPU. + * Make sure ar.k2 isn't needed for something else before enabling this... */ -# define DBG_FAULT(i) mov r16=ar.k2;; shl r16=r16,8;; add r16=(i),r16;;mov ar.k2=r16 +# define DBG_FAULT(i) \ + mov r16=ar.k2;; \ + shl r16=r16,8;; \ + add r16=(i),r16;; \ + mov ar.k2=r16 #else # define DBG_FAULT(i) #endif @@ -80,18 +85,18 @@ #define MINSTATE_VIRT /* needed by minstate.h */ #include "minstate.h" -#define FAULT(n) \ - mov r19=n; /* prepare to save predicates */ \ - mov r31=pr; \ +#define FAULT(n) \ + mov r19=n; /* prepare to save predicates */ \ + mov r31=pr; \ br.sptk.many dispatch_to_fault_handler -#define FAULT_OR_REFLECT(n) \ - mov r20=cr.ipsr; \ - mov r19=n; /* prepare to save predicates */ \ - mov r31=pr;; \ - extr.u r20=r20,IA64_PSR_CPL0_BIT,2;; \ - cmp.ne p6,p0=r0,r20; /* cpl != 0?*/ \ -(p6) br.dptk.many dispatch_reflection; \ +#define FAULT_OR_REFLECT(n) \ + mov r20=cr.ipsr; \ + mov r19=n; /* prepare to save predicates */ \ + mov r31=pr;; \ + extr.u r20=r20,IA64_PSR_CPL0_BIT,2;; \ + cmp.ne p6,p0=r0,r20; /* cpl != 0?*/ \ +(p6) br.dptk.many dispatch_reflection; \ br.sptk.few dispatch_to_fault_handler .section .text.ivt,"ax" @@ -99,7 +104,7 @@ .align 32768 // align on 32KB boundary .global ia64_ivt ia64_ivt: -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x0000 Entry 0 (size 64 bundles) VHPT Translation (8,20,47) ENTRY(vhpt_miss) DBG_FAULT(0) @@ -107,33 +112,34 @@ ENTRY(vhpt_miss) FAULT(0) #else /* - * The VHPT vector is invoked when the TLB entry for the virtual page table - * is missing. This happens only as a result of a previous - * (the "original") TLB miss, which may either be caused by an instruction - * fetch or a data access (or non-access). + * The VHPT vector is invoked when the TLB entry for the virtual + * page table is missing. This happens only as a result of a + * previous (the "original") TLB miss, which may either be caused + * by an instruction fetch or a data access (or non-access). * - * What we do here is normal TLB miss handing for the _original_ miss, followed - * by inserting the TLB entry for the virtual page table page that the VHPT - * walker was attempting to access. The latter gets inserted as long - * as both L1 and L2 have valid mappings for the faulting address. - * The TLB entry for the original miss gets inserted only if - * the L3 entry indicates that the page is present. + * What we do here is normal TLB miss handing for the _original_ + * miss, followed by inserting the TLB entry for the virtual page + * table page that the VHPT walker was attempting to access. The + * latter gets inserted as long as both L1 and L2 have valid + * mappings for the faulting address. The TLB entry for the + * original miss gets inserted only if the L3 entry indicates + * that the page is present. * * do_page_fault gets invoked in the following cases: * - the faulting virtual address uses unimplemented address bits * - the faulting virtual address has no L1, L2, or L3 mapping */ - mov r16=cr.ifa // get address that caused the TLB miss + mov r16=cr.ifa // get address that caused the TLB miss #ifdef CONFIG_HUGETLB_PAGE movl r18=PAGE_SHIFT mov r25=cr.itir #endif ;; - rsm psr.dt // use physical addressing for data - mov r31=pr // save the predicate registers - mov r19=IA64_KR(PT_BASE) // get page table base address - shl r21=r16,3 // shift bit 60 into sign bit - shr.u r17=r16,61 // get the region number into r17 + rsm psr.dt // use physical addressing for data + mov r31=pr // save the predicate registers + mov r19=IA64_KR(PT_BASE) // get page table base address + shl r21=r16,3 // shift bit 60 into sign bit + shr.u r17=r16,61 // get the region number into r17 ;; shr r22=r21,3 #ifdef CONFIG_HUGETLB_PAGE @@ -146,56 +152,68 @@ ENTRY(vhpt_miss) (p8) shr r22=r22,r27 #endif ;; - cmp.eq p6,p7=5,r17 // is IFA pointing into to region 5? - shr.u r18=r22,PGDIR_SHIFT // get bits 33-63 of the faulting address + cmp.eq p6,p7=5,r17 // is IFA pointing into to region 5? + shr.u r18=r22,PGDIR_SHIFT // get bits 33-63 of faulting address ;; -(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place +(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place srlz.d - LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir + LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at + // swapper_pg_dir .pred.rel "mutex", p6, p7 (p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT (p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3 ;; (p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=PTA + IFA(33,42)*8 -(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=PTA + (((IFA(61,63) << 7) | IFA(33,39))*8) - cmp.eq p7,p6=0,r21 // unused address bits all zeroes? +(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=PTA + + // (((IFA(61,63) << 7) | + // IFA(33,39))*8) + cmp.eq p7,p6=0,r21 // unused address bits all zero? shr.u r18=r22,PMD_SHIFT // shift L2 index into position ;; ld8 r17=[r17] // fetch the L1 entry (may be 0) ;; (p7) cmp.eq p6,p7=r17,r0 // was L1 entry NULL? - dep r17=r18,r17,3,(PAGE_SHIFT-3) // compute address of L2 page table entry + dep r17=r18,r17,3,(PAGE_SHIFT-3) // compute address of L2 page + // table entry ;; (p7) ld8 r20=[r17] // fetch the L2 entry (may be 0) shr.u r19=r22,PAGE_SHIFT // shift L3 index into position ;; (p7) cmp.eq.or.andcm p6,p7=r20,r0 // was L2 entry NULL? - dep r21=r19,r20,3,(PAGE_SHIFT-3) // compute address of L3 page table entry + dep r21=r19,r20,3,(PAGE_SHIFT-3) // compute address of L3 page + // table entry ;; (p7) ld8 r18=[r21] // read the L3 PTE - mov r19=cr.isr // cr.isr bit 0 tells us if this is an insn miss + mov r19=cr.isr // cr.isr bit 0 tells us if + // this is an insn miss ;; (p7) tbit.z p6,p7=r18,_PAGE_P_BIT // page present bit cleared? - mov r22=cr.iha // get the VHPT address that caused the TLB miss + mov r22=cr.iha // get the VHPT address that + // caused the TLB miss ;; // avoid RAW on p7 -(p7) tbit.nz.unc p10,p11=r19,32 // is it an instruction TLB miss? - dep r23=0,r20,0,PAGE_SHIFT // clear low bits to get page address +(p7) tbit.nz.unc p10,p11=r19,32 // is it an instruction TLB + // miss? + dep r23=0,r20,0,PAGE_SHIFT // clear low bits to get page + // address ;; -(p10) itc.i r18 // insert the instruction TLB entry +(p10) itc.i r18 // insert the instruction TLB + // entry (p11) itc.d r18 // insert the data TLB entry -(p6) br.cond.spnt.many page_fault // handle bad address/page not present (page fault) +(p6) br.cond.spnt.many page_fault // handle bad address/page not + // present (page fault) mov cr.ifa=r22 #ifdef CONFIG_HUGETLB_PAGE -(p8) mov cr.itir=r25 // change to default page-size for VHPT +(p8) mov cr.itir=r25 // change to default page-size + // for VHPT #endif /* - * Now compute and insert the TLB entry for the virtual page table. We never - * execute in a page table page so there is no need to set the exception deferral - * bit. + * Now compute and insert the TLB entry for the virtual page table. + * We never execute in a page table page so there is no need to set + * the exception deferral bit. */ adds r24=__DIRTY_BITS_NO_ED|_PAGE_PL_0|_PAGE_AR_RW,r23 ;; @@ -203,15 +221,15 @@ ENTRY(vhpt_miss) ;; #ifdef CONFIG_SMP /* - * Tell the assemblers dependency-violation checker that the above "itc" instructions - * cannot possibly affect the following loads: + * Tell the assemblers dependency-violation checker that the above + * "itc" instructions cannot possibly affect the following loads: */ dv_serialize_data /* - * Re-check L2 and L3 pagetable. If they changed, we may have received a ptc.g - * between reading the pagetable and the "itc". If so, flush the entry we - * inserted and retry. + * Re-check L2 and L3 pagetable. If they changed, we may have + * received a ptc.g between reading the pagetable and the "itc". + * If so, flush the entry we inserted and retry. */ ld8 r25=[r21] // read L3 PTE again ld8 r26=[r17] // read L2 entry again @@ -231,7 +249,7 @@ ENTRY(vhpt_miss) END(vhpt_miss) .org ia64_ivt+0x400 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x0400 Entry 1 (size 64 bundles) ITLB (21) ENTRY(itlb_miss) DBG_FAULT(1) @@ -266,7 +284,8 @@ ENTRY(itlb_miss) mov r31=pr // save predicates .itlb_fault: mov r17=cr.iha // get virtual address of L3 PTE - movl r30=1f // load nested fault continuation point + movl r30=1f // load nested fault + // continuation point ;; 1: ld8 r18=[r17] // read L3 PTE ;; @@ -278,13 +297,13 @@ ENTRY(itlb_miss) ;; #ifdef CONFIG_SMP /* - * Tell the assemblers dependency-violation checker that the above "itc" instructions - * cannot possibly affect the following loads: + * Tell the assemblers dependency-violation checker that the above + * "itc" instructions cannot possibly affect the following loads: */ dv_serialize_data - ld8 r19=[r17] // read L3 PTE again and see if same - mov r20=PAGE_SHIFT<<2 // setup page size for purge + ld8 r19=[r17] // read L3 PTE again and see if same + mov r20=PAGE_SHIFT<<2 // setup page size for purge ;; cmp.ne p7,p0=r18,r19 ;; @@ -295,26 +314,25 @@ ENTRY(itlb_miss) END(itlb_miss) .org ia64_ivt+0x0800 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x0800 Entry 2 (size 64 bundles) DTLB (9,48) ENTRY(dtlb_miss) DBG_FAULT(2) #ifdef XEN - mov r16=cr.ifa // get virtual address + mov r16=cr.ifa // get virtual address mov r31=pr ;; extr.u r17=r16,59,5 ;; - /* If address belongs to VMM, go to alt tlb handler */ - cmp.eq p6,p0=0x1e,r17 + cmp.eq p6,p0=0x1e,r17 // if the address belongs to VMM, go + // to the alternate tlb handler (p6) br.cond.spnt late_alt_dtlb_miss ;; cmp.eq p6,p0=0x1d,r17 (p6) br.cond.spnt late_alt_dtlb_miss ;; #if VHPT_ENABLED - // XXX TODO optimization - mov r30=cr.ipsr + mov r30=cr.ipsr // XXX TODO optimization mov r28=cr.iip mov r17=cr.isr ;; @@ -324,15 +342,14 @@ ENTRY(dtlb_miss) cmp.ne p6, p0 = r0, r18 // cpl == 0? (p6) br.cond.sptk 2f - // is speculation bit on? - tbit.nz p7,p0=r17,IA64_ISR_SP_BIT + tbit.nz p7,p0=r17,IA64_ISR_SP_BIT // is speculation bit on? ;; (p7) br.cond.spnt 2f - // Is the faulted iip in vmm area? - // check [59:58] bit - // 00, 11: guest - // 01, 10: vmm + // Is the faulted iip in the vmm area? + // -- check [59:58] bit + // -- if 00, 11: guest + // -- if 01, 10: vmm extr.u r19 = r28, 58, 2 ;; cmp.eq p10, p0 = 0x0, r19 @@ -341,17 +358,16 @@ ENTRY(dtlb_miss) (p11) br.cond.sptk 2f // Is the faulted address is in the identity mapping area? - // 0xf000... or 0xe8000... + // must be either 0xf000... or 0xe8000... extr.u r20 = r16, 59, 5 ;; - cmp.eq p12, p0 = 0x1e, r20 // (0xf0 >> 3) = 0x1e + cmp.eq p12, p0 = 0x1e, r20 // (0xf0 >> 3) = 0x1e (p12) br.cond.spnt 1f - cmp.eq p0, p13 = 0x1d, r20 // (0xe8 >> 3) = 0x1d + cmp.eq p0, p13 = 0x1d, r20 // (0xe8 >> 3) = 0x1d (p13) br.cond.sptk 2f 1: - // xen identity mappin area. - movl r24=PAGE_KERNEL + movl r24=PAGE_KERNEL // xen identity mapping area. movl r25=(((1 << IA64_MAX_PHYS_BITS) - 1) & ~0xfff) ;; shr.u r26=r16,55 // move address bit 59 to bit 4 @@ -361,7 +377,8 @@ ENTRY(dtlb_miss) ;; or r25=r25,r24 // insert PTE control bits into r25 ;; - or r25=r25,r26 // set bit 4 (uncached) if the access was to region 6 + or r25=r25,r26 // set bit 4 (uncached) if the access was to + // region 6 ;; itc.d r25 // insert the TLB entry mov pr=r31,-1 @@ -388,7 +405,8 @@ ENTRY(dtlb_miss) #endif dtlb_fault: mov r17=cr.iha // get virtual address of L3 PTE - movl r30=1f // load nested fault continuation point + movl r30=1f // load nested fault + // continuation point ;; 1: ld8 r18=[r17] // read L3 PTE ;; @@ -400,13 +418,13 @@ dtlb_fault: ;; #ifdef CONFIG_SMP /* - * Tell the assemblers dependency-violation checker that the above "itc" instructions - * cannot possibly affect the following loads: + * Tell the assemblers dependency-violation checker that the above + * "itc" instructions cannot possibly affect the following loads: */ dv_serialize_data - ld8 r19=[r17] // read L3 PTE again and see if same - mov r20=PAGE_SHIFT<<2 // setup page size for purge + ld8 r19=[r17] // read L3 PTE again and see if same + mov r20=PAGE_SHIFT<<2 // setup page size for purge ;; cmp.ne p7,p0=r18,r19 ;; @@ -417,7 +435,7 @@ dtlb_fault: END(dtlb_miss) .org ia64_ivt+0x0c00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x0c00 Entry 3 (size 64 bundles) Alt ITLB (19) ENTRY(alt_itlb_miss) DBG_FAULT(3) @@ -439,14 +457,14 @@ late_alt_itlb_miss: ;; #endif #ifdef CONFIG_DISABLE_VHPT - shr.u r22=r16,61 // get the region number into r21 + shr.u r22=r16,61 // get the region number into r21 ;; - cmp.gt p8,p0=6,r22 // user mode + cmp.gt p8,p0=6,r22 // user mode ;; (p8) thash r17=r16 ;; (p8) mov cr.iha=r17 -(p8) mov r29=b0 // save b0 +(p8) mov r29=b0 // save b0 (p8) br.cond.dptk .itlb_fault #endif extr.u r23=r21,IA64_PSR_CPL0_BIT,2 // extract psr.cpl @@ -463,7 +481,8 @@ late_alt_itlb_miss: cmp.ne p8,p0=r0,r23 // psr.cpl != 0? or r19=r17,r19 // insert PTE control bits into r19 ;; - or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6 + or r19=r19,r18 // set bit 4 (uncached) if the access was to + // region 6 (p8) br.cond.spnt page_fault ;; itc.i r19 // insert the TLB entry @@ -472,7 +491,7 @@ late_alt_itlb_miss: END(alt_itlb_miss) .org ia64_ivt+0x1000 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x1000 Entry 4 (size 64 bundles) Alt DTLB (7,46) ENTRY(alt_dtlb_miss) DBG_FAULT(4) @@ -503,13 +522,15 @@ late_alt_dtlb_miss: tbit.nz p6,p7=r20,IA64_ISR_SP_BIT // is speculation bit on? #ifdef XEN shr.u r18=r16,55 // move address bit 59 to bit 4 - and r19=r19,r16 // clear ed, reserved bits, and PTE control bits + and r19=r19,r16 // clear ed, reserved bits, and + // PTE control bits tbit.nz p9,p0=r20,IA64_ISR_NA_BIT // is non-access bit on? ;; and r18=0x10,r18 // bit 4=address-bit(59) #else shr.u r18=r16,57 // move address bit 61 to bit 4 - and r19=r19,r16 // clear ed, reserved bits, and PTE control bits + and r19=r19,r16 // clear ed, reserved bits, and + // PTE control bits tbit.nz p9,p0=r20,IA64_ISR_NA_BIT // is non-access bit on? ;; andcm r18=0x10,r18 // bit 4=~address-bit(61) @@ -520,36 +541,41 @@ late_alt_dtlb_miss: #ifdef XEN ;; #ifdef CONFIG_VIRTUAL_FRAME_TABLE - // Test for the address of virtual frame_table - shr r22=r16,56;; + shr r22=r16,56 // Test for the address of virtual frame_table + ;; cmp.eq p8,p0=((VIRT_FRAME_TABLE_ADDR>>56)&0xff)-0x100,r22 (p8) br.cond.sptk frametable_miss ;; #endif - // Test for Xen address, if not handle via page_fault - // note that 0xf000 (cached) and 0xe800 (uncached) addresses + // If it is not a Xen address, handle it via page_fault. + // Note that 0xf000 (cached) and 0xe800 (uncached) addresses // should be OK. - extr.u r22=r16,59,5;; + extr.u r22=r16,59,5 + ;; cmp.eq p8,p0=0x1e,r22 -(p8) br.cond.spnt 1f;; +(p8) br.cond.spnt 1f + ;; cmp.ne p8,p0=0x1d,r22 -(p8) br.cond.sptk page_fault ;; +(p8) br.cond.sptk page_fault + ;; 1: #endif dep r21=-1,r21,IA64_PSR_ED_BIT,1 or r19=r19,r17 // insert PTE control bits into r19 ;; - or r19=r19,r18 // set bit 4 (uncached) if the access was to region 6 + or r19=r19,r18 // set bit 4 (uncached) if the access was to + // region 6 (p6) mov cr.ipsr=r21 ;; (p7) itc.d r19 // insert the TLB entry mov pr=r31,-1 rfi END(alt_dtlb_miss) + #ifdef CONFIG_VIRTUAL_FRAME_TABLE GLOBAL_ENTRY(frametable_miss) rsm psr.dt // switch to using physical data addressing - movl r24=(frametable_pg_dir-PAGE_OFFSET) // r24=__pa(frametable_pg_dir) + movl r24=(frametable_pg_dir-PAGE_OFFSET) // r24=__pa(frametable_pg_dir) ;; srlz.d extr.u r17=r16,PGDIR_SHIFT,(PAGE_SHIFT-3) @@ -583,6 +609,7 @@ GLOBAL_ENTRY(frametable_miss) mov pr=r31,-1 // restore predicate registers rfi END(frametable_miss) + ENTRY(frametable_fault) ssm psr.dt // switch to using virtual data addressing mov r18=cr.iip @@ -590,7 +617,8 @@ ENTRY(frametable_fault) ;; cmp.eq p6,p7=r18,r19 // is faulting addrress ia64_frametable_probe? mov r8=0 // assumes that 'probe.r' uses r8 - dep r21=-1,r21,IA64_PSR_RI_BIT+1,1 // return to next instrucition in bundle 2 + dep r21=-1,r21,IA64_PSR_RI_BIT+1,1 // return to next instruction in + // bundle 2 ;; (p6) mov cr.ipsr=r21 mov r19=4 // FAULT(4) @@ -599,6 +627,7 @@ ENTRY(frametable_fault) mov pr=r31,-1 rfi END(frametable_fault) + GLOBAL_ENTRY(ia64_frametable_probe) { probe.r r8=r32,0 // destination register must be r8 @@ -615,18 +644,19 @@ ENTRY(nested_dtlb_miss) DBG_FAULT(5) #ifdef XEN mov b0=r30 - br.sptk.many b0 // return to continuation point + br.sptk.many b0 // return to the continuation point ;; #else /* - * In the absence of kernel bugs, we get here when the virtually mapped linear - * page table is accessed non-speculatively (e.g., in the Dirty-bit, Instruction - * Access-bit, or Data Access-bit faults). If the DTLB entry for the virtual page - * table is missing, a nested TLB miss fault is triggered and control is - * transferred to this point. When this happens, we lookup the pte for the - * faulting address by walking the page table in physical mode and return to the - * continuation point passed in register r30 (or call page_fault if the address is - * not mapped). + * In the absence of kernel bugs, we get here when the virtually + * mapped linear page table is accessed non-speculatively (e.g., + * in the Dirty-bit, Instruction Access-bit, or Data Access-bit + * faults). If the DTLB entry for the virtual page table is missing, + * a nested TLB miss fault is triggered and control is transferred + * to this point. When this happens, we lookup the pte for the + * faulting address by walking the page table in physical mode + * and return to the continuation point passed in register r30 + * (or call page_fault if the address is not mapped). * * Input: r16: faulting address * r29: saved b0 @@ -640,47 +670,52 @@ ENTRY(nested_dtlb_miss) * * Clobbered: b0, r18, r19, r21, psr.dt (cleared) */ - rsm psr.dt // switch to using physical data addressing - mov r19=IA64_KR(PT_BASE) // get the page table base address - shl r21=r16,3 // shift bit 60 into sign bit + rsm psr.dt // switch to using physical data + // addressing + mov r19=IA64_KR(PT_BASE) // get the page table base address + shl r21=r16,3 // shift bit 60 into sign bit ;; - shr.u r17=r16,61 // get the region number into r17 + shr.u r17=r16,61 // get the region number into r17 ;; - cmp.eq p6,p7=5,r17 // is faulting address in region 5? - shr.u r18=r16,PGDIR_SHIFT // get bits 33-63 of faulting address + cmp.eq p6,p7=5,r17 // is faulting address in region 5? + shr.u r18=r16,PGDIR_SHIFT // get bits 33-63 of faulting address ;; -(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place +(p7) dep r17=r17,r19,(PAGE_SHIFT-3),3 // put region number bits in place srlz.d - LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at swapper_pg_dir + LOAD_PHYSICAL(p6, r19, swapper_pg_dir) // region 5 is rooted at + // swapper_pg_dir .pred.rel "mutex", p6, p7 (p6) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT (p7) shr.u r21=r21,PGDIR_SHIFT+PAGE_SHIFT-3 ;; -(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=PTA + IFA(33,42)*8 -(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=PTA + (((IFA(61,63) << 7) | IFA(33,39))*8) - cmp.eq p7,p6=0,r21 // unused address bits all zeroes? - shr.u r18=r16,PMD_SHIFT // shift L2 index into position +(p6) dep r17=r18,r19,3,(PAGE_SHIFT-3) // r17=PTA + IFA(33,42)*8 +(p7) dep r17=r18,r17,3,(PAGE_SHIFT-6) // r17=PTA + (((IFA(61,63) << 7) | + // IFA(33,39))*8) + cmp.eq p7,p6=0,r21 // unused address bits all zeroes? + shr.u r18=r16,PMD_SHIFT // shift L2 index into position ;; - ld8 r17=[r17] // fetch the L1 entry (may be 0) + ld8 r17=[r17] // fetch the L1 entry (may be 0) ;; -(p7) cmp.eq p6,p7=r17,r0 // was L1 entry NULL? - dep r17=r18,r17,3,(PAGE_SHIFT-3) // compute address of L2 page table entry +(p7) cmp.eq p6,p7=r17,r0 // was L1 entry NULL? + dep r17=r18,r17,3,(PAGE_SHIFT-3) // compute address of L2 page table + // entry ;; -(p7) ld8 r17=[r17] // fetch the L2 entry (may be 0) - shr.u r19=r16,PAGE_SHIFT // shift L3 index into position +(p7) ld8 r17=[r17] // fetch the L2 entry (may be 0) + shr.u r19=r16,PAGE_SHIFT // shift L3 index into position ;; -(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was L2 entry NULL? - dep r17=r19,r17,3,(PAGE_SHIFT-3) // compute address of L3 page table entry +(p7) cmp.eq.or.andcm p6,p7=r17,r0 // was L2 entry NULL? + dep r17=r19,r17,3,(PAGE_SHIFT-3) // compute address of L3 page table + // entry (p6) br.cond.spnt page_fault mov b0=r30 - br.sptk.many b0 // return to continuation point + br.sptk.many b0 // return to continuation point #endif END(nested_dtlb_miss) .org ia64_ivt+0x1800 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x1800 Entry 6 (size 64 bundles) Instruction Key Miss (24) ENTRY(ikey_miss) DBG_FAULT(6) @@ -691,8 +726,9 @@ ENTRY(ikey_miss) #endif END(ikey_miss) - //----------------------------------------------------------------------------------- - // call do_page_fault (predicates are in r31, psr.dt may be off, r16 is faulting address) + //---------------------------------------------------------------- + // call do_page_fault (predicates are in r31, psr.dt may be off, + // r16 is faulting address) #ifdef XEN GLOBAL_ENTRY(page_fault) #else @@ -713,24 +749,25 @@ ENTRY(page_fault) mov out0=cr.ifa mov out1=cr.isr #endif - adds r3=8,r2 // set up second base pointer + adds r3=8,r2 // set up second base pointer ;; ssm psr.ic | PSR_DEFAULT_BITS ;; - srlz.i // guarantee that interruption collectin is on + srlz.i // guarantee that interruption + // collection is on ;; -(p15) ssm psr.i // restore psr.i +(p15) ssm psr.i // restore psr.i movl r14=ia64_leave_kernel ;; SAVE_REST mov rp=r14 ;; - adds out2=16,r12 // out2 = pointer to pt_regs + adds out2=16,r12 // out2 = pointer to pt_regs br.call.sptk.many b6=ia64_do_page_fault // ignore return address END(page_fault) .org ia64_ivt+0x1c00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x1c00 Entry 7 (size 64 bundles) Data Key Miss (12,51) ENTRY(dkey_miss) DBG_FAULT(7) @@ -742,32 +779,33 @@ ENTRY(dkey_miss) END(dkey_miss) .org ia64_ivt+0x2000 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x2000 Entry 8 (size 64 bundles) Dirty-bit (54) ENTRY(dirty_bit) DBG_FAULT(8) #ifdef XEN mov r20=cr.ipsr - mov r31=pr;; - extr.u r20=r20,IA64_PSR_CPL0_BIT,2;; - mov r19=8 /* prepare to save predicates */ - cmp.eq p6,p0=r0,r20 /* cpl == 0?*/ + mov r31=pr + ;; + extr.u r20=r20,IA64_PSR_CPL0_BIT,2 + ;; + mov r19=8 // prepare to save predicates + cmp.eq p6,p0=r0,r20 // cpl == 0? (p6) br.sptk.few dispatch_to_fault_handler - /* If shadow mode is not enabled, reflect the fault. */ + // If shadow mode is not enabled, reflect the fault. movl r22=THIS_CPU(cpu_kr)+IA64_KR_CURRENT_OFFSET ;; ld8 r22=[r22] ;; add r22=IA64_VCPU_DOMAIN_OFFSET,r22 ;; - /* Read domain. */ - ld8 r22=[r22] + ld8 r22=[r22] // read domain ;; add r22=IA64_DOMAIN_SHADOW_BITMAP_OFFSET,r22 ;; ld8 r22=[r22] ;; - cmp.eq p6,p0=r0,r22 /* !shadow_bitmap ?*/ + cmp.eq p6,p0=r0,r22 // !shadow_bitmap ? (p6) br.dptk.many dispatch_reflection SAVE_MIN_WITH_COVER @@ -779,10 +817,11 @@ ENTRY(dirty_bit) ssm psr.ic | PSR_DEFAULT_BITS ;; - srlz.i // guarantee that interruption collection is on + srlz.i // guarantee that interruption + // collection is on ;; -(p15) ssm psr.i // restore psr.i - adds r3=8,r2 // set up second base pointer +(p15) ssm psr.i // restore psr.i + adds r3=8,r2 // set up second base pointer ;; SAVE_REST movl r14=ia64_leave_kernel @@ -791,65 +830,69 @@ ENTRY(dirty_bit) br.call.sptk.many b6=ia64_shadow_fault #else /* - * What we do here is to simply turn on the dirty bit in the PTE. We need to - * update both the page-table and the TLB entry. To efficiently access the PTE, - * we address it through the virtual page table. Most likely, the TLB entry for - * the relevant virtual page table page is still present in the TLB so we can - * normally do this without additional TLB misses. In case the necessary virtual - * page table TLB entry isn't present, we take a nested TLB miss hit where we look - * up the physical address of the L3 PTE and then continue at label 1 below. + * What we do here is to simply turn on the dirty bit in the PTE. + * We need to update both the page-table and the TLB entry. To + * efficiently access the PTE, we address it through the virtual + * page table. Most likely, the TLB entry for the relevant virtual + * page table page is still present in the TLB so we can normally + * do this without additional TLB misses. In case the necessary + * virtual page table TLB entry isn't present, we take a nested + * TLB miss hit where we look up the physical address of the L3 + * PTE and then continue at label 1 below. */ - mov r16=cr.ifa // get the address that caused the fault - movl r30=1f // load continuation point in case of nested fault + mov r16=cr.ifa // get the address that caused the + // fault + movl r30=1f // load continuation point in case + // of nested fault ;; - thash r17=r16 // compute virtual address of L3 PTE - mov r29=b0 // save b0 in case of nested fault - mov r31=pr // save pr + thash r17=r16 // compute virtual address of L3 PTE + mov r29=b0 // save b0 in case of nested fault + mov r31=pr // save pr #ifdef CONFIG_SMP - mov r28=ar.ccv // save ar.ccv + mov r28=ar.ccv // save ar.ccv ;; 1: ld8 r18=[r17] - ;; // avoid RAW on r18 - mov ar.ccv=r18 // set compare value for cmpxchg - or r25=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits + ;; // avoid RAW on r18 + mov ar.ccv=r18 // set compare value for cmpxchg + or r25=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits ;; cmpxchg8.acq r26=[r17],r25,ar.ccv mov r24=PAGE_SHIFT<<2 ;; cmp.eq p6,p7=r26,r18 ;; -(p6) itc.d r25 // install updated PTE +(p6) itc.d r25 // install updated PTE ;; /* - * Tell the assemblers dependency-violation checker that the above "itc" instructions - * cannot possibly affect the following loads: + * Tell the assemblers dependency-violation checker that the above + * "itc" instructions cannot possibly affect the following loads: */ dv_serialize_data - ld8 r18=[r17] // read PTE again + ld8 r18=[r17] // read PTE again ;; - cmp.eq p6,p7=r18,r25 // is it same as the newly installed + cmp.eq p6,p7=r18,r25 // is it same as the newly installed ;; (p7) ptc.l r16,r24 - mov b0=r29 // restore b0 + mov b0=r29 // restore b0 mov ar.ccv=r28 #else ;; 1: ld8 r18=[r17] - ;; // avoid RAW on r18 - or r18=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits - mov b0=r29 // restore b0 + ;; // avoid RAW on r18 + or r18=_PAGE_D|_PAGE_A,r18 // set the dirty and accessed bits + mov b0=r29 // restore b0 ;; - st8 [r17]=r18 // store back updated PTE - itc.d r18 // install updated PTE + st8 [r17]=r18 // store back updated PTE + itc.d r18 // install updated PTE #endif - mov pr=r31,-1 // restore pr + mov pr=r31,-1 // restore pr rfi #endif END(dirty_bit) .org ia64_ivt+0x2400 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x2400 Entry 9 (size 64 bundles) Instruction Access-bit (27) ENTRY(iaccess_bit) DBG_FAULT(9) @@ -862,9 +905,11 @@ ENTRY(iaccess_bit) br.sptk.many fast_access_reflect;; #else // Like Entry 8, except for instruction access - mov r16=cr.ifa // get the address that caused the fault - movl r30=1f // load continuation point in case of nested fault - mov r31=pr // save predicates + mov r16=cr.ifa // get the address that caused the + // fault + movl r30=1f // load continuation point in case + // of nested fault + mov r31=pr // save predicates #ifdef CONFIG_ITANIUM /* * Erratum 10 (IFA may contain incorrect address) has "NoFix" status. @@ -872,50 +917,50 @@ ENTRY(iaccess_bit) mov r17=cr.ipsr ;; mov r18=cr.iip - tbit.z p6,p0=r17,IA64_PSR_IS_BIT // IA64 instruction set? + tbit.z p6,p0=r17,IA64_PSR_IS_BIT // IA64 instruction set? ;; -(p6) mov r16=r18 // if so, use cr.iip instead of cr.ifa +(p6) mov r16=r18 // if so, use cr.iip instead of cr.ifa #endif /* CONFIG_ITANIUM */ ;; - thash r17=r16 // compute virtual address of L3 PTE - mov r29=b0 // save b0 in case of nested fault) + thash r17=r16 // compute virtual address of L3 PTE + mov r29=b0 // save b0 in case of nested fault) #ifdef CONFIG_SMP - mov r28=ar.ccv // save ar.ccv + mov r28=ar.ccv // save ar.ccv ;; 1: ld8 r18=[r17] ;; - mov ar.ccv=r18 // set compare value for cmpxchg - or r25=_PAGE_A,r18 // set the accessed bit + mov ar.ccv=r18 // set compare value for cmpxchg + or r25=_PAGE_A,r18 // set the accessed bit ;; cmpxchg8.acq r26=[r17],r25,ar.ccv mov r24=PAGE_SHIFT<<2 ;; cmp.eq p6,p7=r26,r18 ;; -(p6) itc.i r25 // install updated PTE +(p6) itc.i r25 // install updated PTE ;; /* - * Tell the assemblers dependency-violation checker that the above "itc" instructions - * cannot possibly affect the following loads: + * Tell the assemblers dependency-violation checker that the above + * "itc" instructions cannot possibly affect the following loads: */ dv_serialize_data - ld8 r18=[r17] // read PTE again + ld8 r18=[r17] // read PTE again ;; - cmp.eq p6,p7=r18,r25 // is it same as the newly installed + cmp.eq p6,p7=r18,r25 // is it same as the newly installed ;; (p7) ptc.l r16,r24 - mov b0=r29 // restore b0 + mov b0=r29 // restore b0 mov ar.ccv=r28 #else /* !CONFIG_SMP */ ;; 1: ld8 r18=[r17] ;; - or r18=_PAGE_A,r18 // set the accessed bit - mov b0=r29 // restore b0 + or r18=_PAGE_A,r18 // set the accessed bit + mov b0=r29 // restore b0 ;; - st8 [r17]=r18 // store back updated PTE - itc.i r18 // install updated PTE + st8 [r17]=r18 // store back updated PTE + itc.i r18 // install updated PTE #endif /* !CONFIG_SMP */ mov pr=r31,-1 rfi @@ -923,7 +968,7 @@ ENTRY(iaccess_bit) END(iaccess_bit) .org ia64_ivt+0x2800 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x2800 Entry 10 (size 64 bundles) Data Access-bit (15,55) ENTRY(daccess_bit) DBG_FAULT(10) @@ -933,74 +978,80 @@ ENTRY(daccess_bit) mov r31=pr mov r19=10 mov r20=0x2800 - br.sptk.many fast_access_reflect;; + br.sptk.many fast_access_reflect + ;; #else // Like Entry 8, except for data access - mov r16=cr.ifa // get the address that caused the fault - movl r30=1f // load continuation point in case of nested fault + mov r16=cr.ifa // get the address that caused the + // fault + movl r30=1f // load continuation point in case + // of nested fault ;; - thash r17=r16 // compute virtual address of L3 PTE + thash r17=r16 // compute virtual address of L3 PTE mov r31=pr - mov r29=b0 // save b0 in case of nested fault) + mov r29=b0 // save b0 in case of nested fault) #ifdef CONFIG_SMP - mov r28=ar.ccv // save ar.ccv + mov r28=ar.ccv // save ar.ccv ;; 1: ld8 r18=[r17] - ;; // avoid RAW on r18 - mov ar.ccv=r18 // set compare value for cmpxchg - or r25=_PAGE_A,r18 // set the dirty bit + ;; // avoid RAW on r18 + mov ar.ccv=r18 // set compare value for cmpxchg + or r25=_PAGE_A,r18 // set the dirty bit ;; cmpxchg8.acq r26=[r17],r25,ar.ccv mov r24=PAGE_SHIFT<<2 ;; cmp.eq p6,p7=r26,r18 ;; -(p6) itc.d r25 // install updated PTE +(p6) itc.d r25 // install updated PTE /* - * Tell the assemblers dependency-violation checker that the above "itc" instructions - * cannot possibly affect the following loads: + * Tell the assemblers dependency-violation checker that the above + * "itc" instructions cannot possibly affect the following loads: */ dv_serialize_data ;; - ld8 r18=[r17] // read PTE again + ld8 r18=[r17] // read PTE again ;; - cmp.eq p6,p7=r18,r25 // is it same as the newly installed + cmp.eq p6,p7=r18,r25 // is it same as the newly installed ;; (p7) ptc.l r16,r24 mov ar.ccv=r28 #else ;; 1: ld8 r18=[r17] - ;; // avoid RAW on r18 - or r18=_PAGE_A,r18 // set the accessed bit + ;; // avoid RAW on r18 + or r18=_PAGE_A,r18 // set the accessed bit ;; - st8 [r17]=r18 // store back updated PTE - itc.d r18 // install updated PTE + st8 [r17]=r18 // store back updated PTE + itc.d r18 // install updated PTE #endif - mov b0=r29 // restore b0 + mov b0=r29 // restore b0 mov pr=r31,-1 rfi #endif END(daccess_bit) .org ia64_ivt+0x2c00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x2c00 Entry 11 (size 64 bundles) Break instruction (33) ENTRY(break_fault) /* - * The streamlined system call entry/exit paths only save/restore the initial part - * of pt_regs. This implies that the callers of system-calls must adhere to the - * normal procedure calling conventions. + * The streamlined system call entry/exit paths only save/restore + * the initial part of pt_regs. This implies that the callers of + * system-calls must adhere to the normal procedure calling + * conventions. * * Registers to be saved & restored: * CR registers: cr.ipsr, cr.iip, cr.ifs - * AR registers: ar.unat, ar.pfs, ar.rsc, ar.rnat, ar.bspstore, ar.fpsr + * AR registers: ar.unat, ar.pfs, ar.rsc, ar.rnat, ar.bspstore, + * ar.fpsr * others: pr, b0, b6, loadrs, r1, r11, r12, r13, r15 * Registers to be restored only: * r8-r11: output value from the system call. * - * During system call exit, scratch registers (including r15) are modified/cleared - * to prevent leaking bits from kernel to user level. + * During system call exit, scratch registers (including r15) are + * modified/cleared to prevent leaking bits from kernel to user + * level. */ DBG_FAULT(11) #ifdef XEN @@ -1009,13 +1060,17 @@ ENTRY(break_fault) mov r31=pr ;; cmp.eq p7,p0=r17,r0 -(p7) br.spnt.few dispatch_break_fault ;; +(p7) br.spnt.few dispatch_break_fault + ;; #ifdef CRASH_DEBUG - // panic can occur before domain0 is created. - // in such case referencing XSI_PSR_IC causes nested_dtlb_miss - movl r18=CDB_BREAK_NUM ;; - cmp.eq p7,p0=r17,r18 ;; -(p7) br.spnt.few dispatch_break_fault ;; + // A panic can occur before domain0 is created. In such cases, + // referencing XSI_PSR_IC causes nested_dtlb_miss. + movl r18=CDB_BREAK_NUM + ;; + cmp.eq p7,p0=r17,r18 + ;; +(p7) br.spnt.few dispatch_break_fault + ;; #endif movl r18=THIS_CPU(current_psr_ic_addr) ;; @@ -1026,17 +1081,19 @@ ENTRY(break_fault) cmp.eq p7,p0=r0,r17 // is this a psuedo-cover? (p7) br.spnt.many dispatch_privop_fault ;; - // if vpsr.ic is off, we have a hyperprivop - // A hyperprivop is hand-coded assembly with psr.ic off - // which means no calls, no use of r1-r15 and no memory accesses - // except to pinned addresses! + // If vpsr.ic is off, we have a hyperprivop. A hyperprivop is + // hand-coded assembly with psr.ic off which means it can make + // no calls, cannot use r1-r15, and it can have no memory accesses + // unless they are to pinned addresses! cmp4.eq p7,p0=r0,r19 (p7) br.sptk.many fast_hyperprivop ;; - movl r22=THIS_CPU(cpu_kr)+IA64_KR_CURRENT_OFFSET;; + movl r22=THIS_CPU(cpu_kr)+IA64_KR_CURRENT_OFFSET + ;; ld8 r22 = [r22] ;; - adds r22=IA64_VCPU_BREAKIMM_OFFSET,r22;; + adds r22=IA64_VCPU_BREAKIMM_OFFSET,r22 + ;; ld4 r23=[r22];; cmp4.eq p6,p7=r23,r17 // Xen-reserved breakimm? (p6) br.spnt.many dispatch_break_fault @@ -1056,78 +1113,86 @@ ENTRY(break_fault) mov r26=ar.pfs mov r28=cr.iip #ifndef XEN - mov r31=pr // prepare to save predicates + mov r31=pr // prepare to save predicates #endif mov r20=r1 ;; adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16 - cmp.eq p0,p7=r18,r17 // is this a system call? (p7 <- false, if so) + cmp.eq p0,p7=r18,r17 // is this a system call? + // (p7 <- false, if so) (p7) br.cond.spnt non_syscall ;; - ld1 r17=[r16] // load current->thread.on_ustack flag - st1 [r16]=r0 // clear current->thread.on_ustack flag - add r1=-IA64_TASK_THREAD_ON_USTACK_OFFSET,r16 // set r1 for MINSTATE_START_SAVE_MIN_VIRT + ld1 r17=[r16] // load current->thread.on_ustack flag + st1 [r16]=r0 // clear current->thread.on_ustack flag + add r1=-IA64_TASK_THREAD_ON_USTACK_OFFSET,r16 + // set r1 for + // MINSTATE_START_SAVE_MIN_VIRT ;; invala /* adjust return address so we skip over the break instruction: */ - extr.u r8=r29,41,2 // extract ei field from cr.ipsr + extr.u r8=r29,41,2 // extract ei field from cr.ipsr ;; - cmp.eq p6,p7=2,r8 // isr.ei==2? - mov r2=r1 // setup r2 for ia64_syscall_setup + cmp.eq p6,p7=2,r8 // isr.ei==2? + mov r2=r1 // setup r2 for ia64_syscall_setup ;; -(p6) mov r8=0 // clear ei to 0 -(p6) adds r28=16,r28 // switch cr.iip to next bundle cr.ipsr.ei wrapped -(p7) adds r8=1,r8 // increment ei to next slot +(p6) mov r8=0 // clear ei to 0 +(p6) adds r28=16,r28 // switch cr.iip to next bundle + // cr.ipsr.ei wrapped +(p7) adds r8=1,r8 // increment ei to next slot ;; - cmp.eq pKStk,pUStk=r0,r17 // are we in kernel mode already? - dep r29=r8,r29,41,2 // insert new ei into cr.ipsr + cmp.eq pKStk,pUStk=r0,r17 // are we in kernel mode already? + dep r29=r8,r29,41,2 // insert new ei into cr.ipsr ;; // switch from user to kernel RBS: MINSTATE_START_SAVE_MIN_VIRT br.call.sptk.many b7=ia64_syscall_setup ;; - MINSTATE_END_SAVE_MIN_VIRT // switch to bank 1 + MINSTATE_END_SAVE_MIN_VIRT // switch to bank 1 ssm psr.ic | PSR_DEFAULT_BITS ;; - srlz.i // guarantee that interruption collection is on + srlz.i // guarantee that interruption + // collection is on mov r3=NR_syscalls - 1 ;; -(p15) ssm psr.i // restore psr.i +(p15) ssm psr.i // restore psr.i // p10==true means out registers are more than 8 or r15's Nat is true (p10) br.cond.spnt.many ia64_ret_from_syscall ;; movl r16=sys_call_table - adds r15=-1024,r15 // r15 contains the syscall number---subtract 1024 + adds r15=-1024,r15 // r15 contains the syscall number -- + // subtract 1024 from it movl r2=ia64_ret_from_syscall ;; - shladd r20=r15,3,r16 // r20 = sys_call_table + 8*(syscall-1024) - cmp.leu p6,p7=r15,r3 // (syscall > 0 && syscall < 1024 + NR_syscalls) ? - mov rp=r2 // set the real return addr + shladd r20=r15,3,r16 // r20 = sys_call_table + + // 8*(syscall-1024) + cmp.leu p6,p7=r15,r3 // (syscall > 0 && syscall < 1024 + + // NR_syscalls) ? + mov rp=r2 // set the real return addr ;; -(p6) ld8 r20=[r20] // load address of syscall entry point +(p6) ld8 r20=[r20] // load address of syscall entry point (p7) movl r20=sys_ni_syscall add r2=TI_FLAGS+IA64_TASK_SIZE,r13 ;; - ld4 r2=[r2] // r2 = current_thread_info()->flags + ld4 r2=[r2] // r2 = current_thread_info()->flags ;; - and r2=_TIF_SYSCALL_TRACEAUDIT,r2 // mask trace or audit + and r2=_TIF_SYSCALL_TRACEAUDIT,r2 // mask trace or audit ;; cmp.eq p8,p0=r2,r0 mov b6=r20 ;; -(p8) br.call.sptk.many b6=b6 // ignore this return addr +(p8) br.call.sptk.many b6=b6 // ignore this return addr br.cond.sptk ia64_trace_syscall // NOT REACHED #endif END(break_fault) .org ia64_ivt+0x3000 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x3000 Entry 12 (size 64 bundles) External Interrupt (4) ENTRY(interrupt) DBG_FAULT(12) @@ -1138,11 +1203,16 @@ ENTRY(interrupt) // FIXME: this is a hack... use cpuinfo.ksoftirqd because its // not used anywhere else and we need a place to stash ivr and // there's no registers available unused by SAVE_MIN/REST - movl r29=THIS_CPU(cpu_info)+IA64_CPUINFO_KSOFTIRQD_OFFSET;; - st8 [r29]=r30;; - movl r28=slow_interrupt;; - mov r29=rp;; - mov rp=r28;; + movl r29=THIS_CPU(cpu_info)+IA64_CPUINFO_KSOFTIRQD_OFFSET + ;; + st8 [r29]=r30 + ;; + movl r28=slow_interrupt + ;; + mov r29=rp + ;; + mov rp=r28 + ;; br.cond.sptk.many fast_tick_reflect ;; slow_interrupt: @@ -1175,16 +1245,16 @@ slow_interrupt: END(interrupt) .org ia64_ivt+0x3400 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x3400 Entry 13 (size 64 bundles) Reserved DBG_FAULT(13) FAULT(13) #ifdef XEN - // There is no particular reason for this code to be here, other than that - // there happens to be space here that would go unused otherwise. If this - // fault ever gets "unreserved", simply moved the following code to a more - // suitable spot... + // There is no particular reason for this code to be here, other + // than that there happens to be space here that would go unused + // otherwise. If this fault ever gets "unreserved", simply move + // the following code to a more suitable spot... GLOBAL_ENTRY(dispatch_break_fault) SAVE_MIN_WITH_COVER @@ -1198,32 +1268,32 @@ dispatch_break_fault_post_save: ssm psr.ic | PSR_DEFAULT_BITS ;; - srlz.i // guarantee that interruption collection is on + srlz.i // guarantee that interruption collection is on ;; -(p15) ssm psr.i // restore psr.i - adds r3=8,r2 // set up second base pointer +(p15) ssm psr.i // restore psr.i + adds r3=8,r2 // set up second base pointer ;; SAVE_REST movl r14=ia64_leave_kernel ;; mov rp=r14 -// br.sptk.many ia64_prepare_handle_break - br.call.sptk.many b6=ia64_handle_break +// br.sptk.many ia64_prepare_handle_break // TODO: why commented out? + br.call.sptk.many b6=ia64_handle_break END(dispatch_break_fault) #endif .org ia64_ivt+0x3800 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x3800 Entry 14 (size 64 bundles) Reserved DBG_FAULT(14) FAULT(14) #ifndef XEN /* - * There is no particular reason for this code to be here, other than that - * there happens to be space here that would go unused otherwise. If this - * fault ever gets "unreserved", simply moved the following code to a more - * suitable spot... + * There is no particular reason for this code to be here, other + * than that there happens to be space here that would go unused + * otherwise. If this fault ever gets "unreserved", simply move + * the following code to a more suitable spot... * * ia64_syscall_setup() is a separate subroutine so that it can * allocate stacked registers so it can safely demine any @@ -1271,11 +1341,11 @@ GLOBAL_ENTRY(ia64_syscall_setup) # error This code assumes that b6 is the first field in pt_regs. #endif #endif - st8 [r1]=r19 // save b6 - add r16=PT(CR_IPSR),r1 // initialize first base pointer - add r17=PT(R11),r1 // initialize second base pointer + st8 [r1]=r19 // save b6 + add r16=PT(CR_IPSR),r1 // initialize first base pointer + add r17=PT(R11),r1 // initialize second base pointer ;; - alloc r19=ar.pfs,8,0,0,0 // ensure in0-in7 are writable + alloc r19=ar.pfs,8,0,0,0 // ensure in0-in7 are writable st8 [r16]=r29,PT(AR_PFS)-PT(CR_IPSR) // save cr.ipsr tnat.nz p8,p0=in0 @@ -1312,18 +1382,20 @@ GLOBAL_ENTRY(ia64_syscall_setup) tnat.nz p11,p0=in3 ;; (p10) mov in2=-1 - tnat.nz p12,p0=in4 // [I0] + tnat.nz p12,p0=in4 // [I0] (p11) mov in3=-1 ;; (pUStk) st8 [r16]=r24,PT(PR)-PT(AR_RNAT) // save ar.rnat (pUStk) st8 [r17]=r23,PT(B0)-PT(AR_BSPSTORE) // save ar.bspstore - shl r18=r18,16 // compute ar.rsc to be used for "loadrs" + shl r18=r18,16 // compute ar.rsc to be used + // for "loadrs" ;; st8 [r16]=r31,PT(LOADRS)-PT(PR) // save predicates st8 [r17]=r28,PT(R1)-PT(B0) // save b0 - tnat.nz p13,p0=in5 // [I0] + tnat.nz p13,p0=in5 // [I0] ;; - st8 [r16]=r18,PT(R12)-PT(LOADRS) // save ar.rsc value for "loadrs" + st8 [r16]=r18,PT(R12)-PT(LOADRS) // save ar.rsc value for + // "loadrs" st8.spill [r17]=r20,PT(R13)-PT(R1) // save original r1 (p12) mov in4=-1 ;; @@ -1336,32 +1408,34 @@ GLOBAL_ENTRY(ia64_syscall_setup) tnat.nz p14,p0=in6 cmp.lt p10,p9=r11,r8 // frame size can't be more than local+8 ;; - stf8 [r16]=f1 // ensure pt_regs.r8 != 0 (see handle_syscall_error) + stf8 [r16]=f1 // ensure pt_regs.r8 != 0 + // (see handle_syscall_error) (p9) tnat.nz p10,p0=r15 - adds r12=-16,r1 // switch to kernel memory stack (with 16 bytes of scratch) + adds r12=-16,r1 // switch to kernel memory stack (with 16 + // bytes of scratch) - st8.spill [r17]=r15 // save r15 + st8.spill [r17]=r15 // save r15 tnat.nz p8,p0=in7 nop.i 0 - mov r13=r2 // establish `current' - movl r1=__gp // establish kernel global pointer + mov r13=r2 // establish `current' + movl r1=__gp // establish kernel global pointer ;; (p14) mov in6=-1 (p8) mov in7=-1 nop.i 0 - cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0 + cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0 movl r17=FPSR_DEFAULT ;; - mov.m ar.fpsr=r17 // set ar.fpsr to kernel default value + mov.m ar.fpsr=r17 // set ar.fpsr to kernel default value (p10) mov r8=-EINVAL br.ret.sptk.many b7 END(ia64_syscall_setup) #endif /* XEN */ .org ia64_ivt+0x3c00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x3c00 Entry 15 (size 64 bundles) Reserved DBG_FAULT(15) FAULT(15) @@ -1370,11 +1444,12 @@ END(ia64_syscall_setup) /* * Squatting in this space ... * - * This special case dispatcher for illegal operation faults allows preserved - * registers to be modified through a callback function (asm only) that is handed - * back from the fault handler in r8. Up to three arguments can be passed to the - * callback function by returning an aggregate with the callback as its first - * element, followed by the arguments. + * This special case dispatcher for illegal operation faults + * allows preserved registers to be modified through a callback + * function (asm only) that is handed back from the fault handler + * in r8. Up to three arguments can be passed to the callback + * function by returning an aggregate with the callback as its + * first element, followed by the arguments. */ ENTRY(dispatch_illegal_op_fault) SAVE_MIN_WITH_COVER @@ -1408,21 +1483,22 @@ END(dispatch_illegal_op_fault) #endif .org ia64_ivt+0x4000 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x4000 Entry 16 (size 64 bundles) Reserved DBG_FAULT(16) FAULT(16) #ifdef XEN - // There is no particular reason for this code to be here, other than that - // there happens to be space here that would go unused otherwise. If this - // fault ever gets "unreserved", simply moved the following code to a more - // suitable spot... + // There is no particular reason for this code to be here, other + // than that there happens to be space here that would go unused + // otherwise. If this fault ever gets "unreserved", simply move + // the following code to a more suitable spot... ENTRY(dispatch_privop_fault) SAVE_MIN_WITH_COVER ;; - alloc r14=ar.pfs,0,0,4,0 // now it's safe (must be first in insn group!) + alloc r14=ar.pfs,0,0,4,0 // now it's safe (must be first in + // insn group!) mov out0=cr.ifa adds out1=16,sp mov out2=cr.isr // FIXME: pity to make this slow access twice @@ -1430,23 +1506,24 @@ ENTRY(dispatch_privop_fault) ssm psr.ic | PSR_DEFAULT_BITS ;; - srlz.i // guarantee that interruption collection is on + srlz.i // guarantee that interruption + // collection is on ;; -(p15) ssm psr.i // restore psr.i - adds r3=8,r2 // set up second base pointer +(p15) ssm psr.i // restore psr.i + adds r3=8,r2 // set up second base pointer ;; SAVE_REST movl r14=ia64_leave_kernel ;; mov rp=r14 -// br.sptk.many ia64_prepare_handle_privop - br.call.sptk.many b6=ia64_handle_privop +// br.sptk.many ia64_prepare_handle_privop // TODO: why commented out? + br.call.sptk.many b6=ia64_handle_privop END(dispatch_privop_fault) #endif .org ia64_ivt+0x4400 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x4400 Entry 17 (size 64 bundles) Reserved DBG_FAULT(17) FAULT(17) @@ -1455,77 +1532,80 @@ END(dispatch_privop_fault) ENTRY(non_syscall) SAVE_MIN_WITH_COVER - // There is no particular reason for this code to be here, other than that - // there happens to be space here that would go unused otherwise. If this - // fault ever gets "unreserved", simply moved the following code to a more - // suitable spot... + // There is no particular reason for this code to be here, other + // than that there happens to be space here that would go unused + // otherwise. If this fault ever gets "unreserved", simply move + // the following code to a more suitable spot... alloc r14=ar.pfs,0,0,2,0 mov out0=cr.iim add out1=16,sp - adds r3=8,r2 // set up second base pointer for SAVE_REST + adds r3=8,r2 // set up second base pointer for SAVE_REST ssm psr.ic | PSR_DEFAULT_BITS ;; - srlz.i // guarantee that interruption collection is on + srlz.i // guarantee that interruption collection is on ;; -(p15) ssm psr.i // restore psr.i +(p15) ssm psr.i // restore psr.i movl r15=ia64_leave_kernel ;; SAVE_REST mov rp=r15 ;; - br.call.sptk.many b6=ia64_bad_break // avoid WAW on CFM and ignore return addr + br.call.sptk.many b6=ia64_bad_break // avoid WAW on CFM and + // ignore return addr END(non_syscall) #endif .org ia64_ivt+0x4800 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x4800 Entry 18 (size 64 bundles) Reserved DBG_FAULT(18) FAULT(18) #ifndef XEN /* - * There is no particular reason for this code to be here, other than that - * there happens to be space here that would go unused otherwise. If this - * fault ever gets "unreserved", simply moved the following code to a more - * suitable spot... + * There is no particular reason for this code to be here, other + * than that there happens to be space here that would go unused + * otherwise. If this fault ever gets "unreserved", simply move + * the following code to a more suitable spot... */ ENTRY(dispatch_unaligned_handler) SAVE_MIN_WITH_COVER ;; - alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in insn group!) + alloc r14=ar.pfs,0,0,2,0 // now it's safe (must be first in + // insn group!) mov out0=cr.ifa adds out1=16,sp ssm psr.ic | PSR_DEFAULT_BITS ;; - srlz.i // guarantee that interruption collection is on + srlz.i // guarantee that interruption + // collection is on ;; -(p15) ssm psr.i // restore psr.i - adds r3=8,r2 // set up second base pointer +(p15) ssm psr.i // restore psr.i + adds r3=8,r2 // set up second base pointer ;; SAVE_REST movl r14=ia64_leave_kernel ;; mov rp=r14 -// br.sptk.many ia64_prepare_handle_unaligned - br.call.sptk.many b6=ia64_handle_unaligned +// br.sptk.many ia64_prepare_handle_unaligned // TODO: why commented out? + br.call.sptk.many b6=ia64_handle_unaligned END(dispatch_unaligned_handler) #endif .org ia64_ivt+0x4c00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x4c00 Entry 19 (size 64 bundles) Reserved DBG_FAULT(19) FAULT(19) /* - * There is no particular reason for this code to be here, other than that - * there happens to be space here that would go unused otherwise. If this - * fault ever gets "unreserved", simply moved the following code to a more - * suitable spot... + * There is no particular reason for this code to be here, other + * than that there happens to be space here that would go unused + * otherwise. If this fault ever gets "unreserved", simply move + * the following code to a more suitable spot... */ GLOBAL_ENTRY(dispatch_to_fault_handler) @@ -1545,10 +1625,12 @@ GLOBAL_ENTRY(dispatch_to_fault_handler) ;; ssm psr.ic | PSR_DEFAULT_BITS ;; - srlz.i // guarantee that interruption collection is on + srlz.i // guarantee that interruption + // collection is on ;; -(p15) ssm psr.i // restore psr.i - adds r3=8,r2 // set up second base pointer for SAVE_REST +(p15) ssm psr.i // restore psr.i + adds r3=8,r2 // set up second base pointer for + // SAVE_REST ;; SAVE_REST movl r14=ia64_leave_kernel @@ -1562,7 +1644,7 @@ END(dispatch_to_fault_handler) // .org ia64_ivt+0x5000 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5000 Entry 20 (size 16 bundles) Page Not Present (10,22,49) ENTRY(page_not_present) DBG_FAULT(20) @@ -1572,8 +1654,9 @@ ENTRY(page_not_present) mov r16=cr.ifa rsm psr.dt /* - * The Linux page fault handler doesn't expect non-present pages to be in - * the TLB. Flush the existing entry now, so we meet that expectation. + * The Linux page fault handler doesn't expect non-present pages + * to be in the TLB. Flush the existing entry now, so we meet + * that expectation. */ mov r17=PAGE_SHIFT<<2 ;; @@ -1586,7 +1669,7 @@ ENTRY(page_not_present) END(page_not_present) .org ia64_ivt+0x5100 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5100 Entry 21 (size 16 bundles) Key Permission (13,25,52) ENTRY(key_permission) DBG_FAULT(21) @@ -1603,7 +1686,7 @@ ENTRY(key_permission) END(key_permission) .org ia64_ivt+0x5200 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5200 Entry 22 (size 16 bundles) Instruction Access Rights (26) ENTRY(iaccess_rights) DBG_FAULT(22) @@ -1620,17 +1703,19 @@ ENTRY(iaccess_rights) END(iaccess_rights) .org ia64_ivt+0x5300 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5300 Entry 23 (size 16 bundles) Data Access Rights (14,53) ENTRY(daccess_rights) DBG_FAULT(23) #ifdef XEN - mov r31=pr; + mov r31=pr + ;; mov r16=cr.isr mov r17=cr.ifa mov r19=23 movl r20=0x5300 - br.sptk.many fast_access_reflect;; + br.sptk.many fast_access_reflect + ;; #else mov r16=cr.ifa rsm psr.dt @@ -1642,7 +1727,7 @@ ENTRY(daccess_rights) END(daccess_rights) .org ia64_ivt+0x5400 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5400 Entry 24 (size 16 bundles) General Exception (5,32,34,36,38,39) ENTRY(general_exception) DBG_FAULT(24) @@ -1662,12 +1747,12 @@ ENTRY(general_exception) END(general_exception) .org ia64_ivt+0x5500 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5500 Entry 25 (size 16 bundles) Disabled FP-Register (35) ENTRY(disabled_fp_reg) DBG_FAULT(25) #ifdef XEN -#if 0 +#if 0 // TODO: can this be removed? mov r20=pr movl r16=0x2000000000000000 movl r17=0x2000000000176b60 @@ -1686,7 +1771,7 @@ ENTRY(disabled_fp_reg) ;; #endif FAULT_OR_REFLECT(25) -//floating_panic: +//floating_panic: // TODO: can this be removed? // br.sptk.many floating_panic ;; #endif @@ -1699,7 +1784,7 @@ ENTRY(disabled_fp_reg) END(disabled_fp_reg) .org ia64_ivt+0x5600 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5600 Entry 26 (size 16 bundles) Nat Consumption (11,23,37,50) ENTRY(nat_consumption) DBG_FAULT(26) @@ -1711,7 +1796,7 @@ ENTRY(nat_consumption) END(nat_consumption) .org ia64_ivt+0x5700 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5700 Entry 27 (size 16 bundles) Speculation (40) ENTRY(speculation_vector) DBG_FAULT(27) @@ -1720,12 +1805,13 @@ ENTRY(speculation_vector) FAULT_OR_REFLECT(27) #else /* - * A [f]chk.[as] instruction needs to take the branch to the recovery code but - * this part of the architecture is not implemented in hardware on some CPUs, such - * as Itanium. Thus, in general we need to emulate the behavior. IIM contains - * the relative target (not yet sign extended). So after sign extending it we - * simply add it to IIP. We also need to reset the EI field of the IPSR to zero, - * i.e., the slot to restart into. + * A [f]chk.[as] instruction needs to take the branch to the + * recovery code but this part of the architecture is not + * implemented in hardware on some CPUs, such as Itanium. Thus, + * in general we need to emulate the behavior. IIM contains the + * relative target (not yet sign extended). So after sign extending + * it we simply add it to IIP. We also need to reset the EI field + * of the IPSR to zero, i.e., the slot to restart into. * * cr.imm contains zero_ext(imm21) */ @@ -1753,13 +1839,13 @@ ENTRY(speculation_vector) END(speculation_vector) .org ia64_ivt+0x5800 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5800 Entry 28 (size 16 bundles) Reserved DBG_FAULT(28) FAULT(28) .org ia64_ivt+0x5900 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5900 Entry 29 (size 16 bundles) Debug (16,28,56) ENTRY(debug_vector) DBG_FAULT(29) @@ -1771,7 +1857,7 @@ ENTRY(debug_vector) END(debug_vector) .org ia64_ivt+0x5a00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5a00 Entry 30 (size 16 bundles) Unaligned Reference (57) ENTRY(unaligned_access) DBG_FAULT(30) @@ -1786,7 +1872,7 @@ ENTRY(unaligned_access) END(unaligned_access) .org ia64_ivt+0x5b00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5b00 Entry 31 (size 16 bundles) Unsupported Data Reference (57) ENTRY(unsupported_data_reference) DBG_FAULT(31) @@ -1798,7 +1884,7 @@ ENTRY(unsupported_data_reference) END(unsupported_data_reference) .org ia64_ivt+0x5c00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5c00 Entry 32 (size 16 bundles) Floating-Point Fault (64) ENTRY(floating_point_fault) DBG_FAULT(32) @@ -1810,7 +1896,7 @@ ENTRY(floating_point_fault) END(floating_point_fault) .org ia64_ivt+0x5d00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5d00 Entry 33 (size 16 bundles) Floating Point Trap (66) ENTRY(floating_point_trap) DBG_FAULT(33) @@ -1822,7 +1908,7 @@ ENTRY(floating_point_trap) END(floating_point_trap) .org ia64_ivt+0x5e00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5e00 Entry 34 (size 16 bundles) Lower Privilege Transfer Trap (66) ENTRY(lower_privilege_trap) DBG_FAULT(34) @@ -1834,7 +1920,7 @@ ENTRY(lower_privilege_trap) END(lower_privilege_trap) .org ia64_ivt+0x5f00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x5f00 Entry 35 (size 16 bundles) Taken Branch Trap (68) ENTRY(taken_branch_trap) DBG_FAULT(35) @@ -1846,7 +1932,7 @@ ENTRY(taken_branch_trap) END(taken_branch_trap) .org ia64_ivt+0x6000 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6000 Entry 36 (size 16 bundles) Single Step Trap (69) ENTRY(single_step_trap) DBG_FAULT(36) @@ -1858,56 +1944,58 @@ ENTRY(single_step_trap) END(single_step_trap) .org ia64_ivt+0x6100 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6100 Entry 37 (size 16 bundles) Reserved DBG_FAULT(37) FAULT(37) .org ia64_ivt+0x6200 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6200 Entry 38 (size 16 bundles) Reserved DBG_FAULT(38) FAULT(38) .org ia64_ivt+0x6300 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6300 Entry 39 (size 16 bundles) Reserved DBG_FAULT(39) FAULT(39) .org ia64_ivt+0x6400 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6400 Entry 40 (size 16 bundles) Reserved DBG_FAULT(40) FAULT(40) .org ia64_ivt+0x6500 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6500 Entry 41 (size 16 bundles) Reserved DBG_FAULT(41) FAULT(41) .org ia64_ivt+0x6600 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6600 Entry 42 (size 16 bundles) Reserved DBG_FAULT(42) FAULT(42) .org ia64_ivt+0x6700 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6700 Entry 43 (size 16 bundles) Reserved DBG_FAULT(43) FAULT(43) .org ia64_ivt+0x6800 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6800 Entry 44 (size 16 bundles) Reserved DBG_FAULT(44) FAULT(44) .org ia64_ivt+0x6900 -///////////////////////////////////////////////////////////////////////////////////////// -// 0x6900 Entry 45 (size 16 bundles) IA-32 Exeception (17,18,29,41,42,43,44,58,60,61,62,72,73,75,76,77) +////////////////////////////////////////////////////////////////////////// +// 0x6900 Entry 45 (size 16 bundles) IA-32 Exeception (17,18,29,41,42,43, +// 44,58,60,61,62,72, +// 73,75,76,77) ENTRY(ia32_exception) DBG_FAULT(45) #ifdef XEN @@ -1918,7 +2006,7 @@ ENTRY(ia32_exception) END(ia32_exception) .org ia64_ivt+0x6a00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6a00 Entry 46 (size 16 bundles) IA-32 Intercept (30,31,59,70,71) ENTRY(ia32_intercept) DBG_FAULT(46) @@ -1952,7 +2040,7 @@ ENTRY(ia32_intercept) END(ia32_intercept) .org ia64_ivt+0x6b00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6b00 Entry 47 (size 16 bundles) IA-32 Interrupt (74) ENTRY(ia32_interrupt) DBG_FAULT(47) @@ -1969,121 +2057,121 @@ ENTRY(ia32_interrupt) END(ia32_interrupt) .org ia64_ivt+0x6c00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6c00 Entry 48 (size 16 bundles) Reserved DBG_FAULT(48) FAULT(48) .org ia64_ivt+0x6d00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6d00 Entry 49 (size 16 bundles) Reserved DBG_FAULT(49) FAULT(49) .org ia64_ivt+0x6e00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6e00 Entry 50 (size 16 bundles) Reserved DBG_FAULT(50) FAULT(50) .org ia64_ivt+0x6f00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x6f00 Entry 51 (size 16 bundles) Reserved DBG_FAULT(51) FAULT(51) .org ia64_ivt+0x7000 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7000 Entry 52 (size 16 bundles) Reserved DBG_FAULT(52) FAULT(52) .org ia64_ivt+0x7100 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7100 Entry 53 (size 16 bundles) Reserved DBG_FAULT(53) FAULT(53) .org ia64_ivt+0x7200 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7200 Entry 54 (size 16 bundles) Reserved DBG_FAULT(54) FAULT(54) .org ia64_ivt+0x7300 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7300 Entry 55 (size 16 bundles) Reserved DBG_FAULT(55) FAULT(55) .org ia64_ivt+0x7400 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7400 Entry 56 (size 16 bundles) Reserved DBG_FAULT(56) FAULT(56) .org ia64_ivt+0x7500 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7500 Entry 57 (size 16 bundles) Reserved DBG_FAULT(57) FAULT(57) .org ia64_ivt+0x7600 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7600 Entry 58 (size 16 bundles) Reserved DBG_FAULT(58) FAULT(58) .org ia64_ivt+0x7700 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7700 Entry 59 (size 16 bundles) Reserved DBG_FAULT(59) FAULT(59) .org ia64_ivt+0x7800 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7800 Entry 60 (size 16 bundles) Reserved DBG_FAULT(60) FAULT(60) .org ia64_ivt+0x7900 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7900 Entry 61 (size 16 bundles) Reserved DBG_FAULT(61) FAULT(61) .org ia64_ivt+0x7a00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7a00 Entry 62 (size 16 bundles) Reserved DBG_FAULT(62) FAULT(62) .org ia64_ivt+0x7b00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7b00 Entry 63 (size 16 bundles) Reserved DBG_FAULT(63) FAULT(63) .org ia64_ivt+0x7c00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7c00 Entry 64 (size 16 bundles) Reserved DBG_FAULT(64) FAULT(64) .org ia64_ivt+0x7d00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7d00 Entry 65 (size 16 bundles) Reserved DBG_FAULT(65) FAULT(65) .org ia64_ivt+0x7e00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7e00 Entry 66 (size 16 bundles) Reserved DBG_FAULT(66) FAULT(66) .org ia64_ivt+0x7f00 -///////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// // 0x7f00 Entry 67 (size 16 bundles) Reserved DBG_FAULT(67) FAULT(67) @@ -2104,21 +2192,22 @@ GLOBAL_ENTRY(dispatch_reflection) adds out1=16,sp mov out2=cr.isr mov out3=cr.iim -// mov out3=cr.itir +// mov out3=cr.itir // TODO: why commented out? ssm psr.ic | PSR_DEFAULT_BITS ;; - srlz.i // guarantee that interruption collection is on + srlz.i // guarantee that interruption + // collection is on ;; -(p15) ssm psr.i // restore psr.i - adds r3=8,r2 // set up second base pointer +(p15) ssm psr.i // restore psr.i + adds r3=8,r2 // set up second base pointer ;; SAVE_REST movl r14=ia64_leave_kernel ;; mov rp=r14 -// br.sptk.many ia64_prepare_handle_reflection - br.call.sptk.many b6=ia64_handle_reflection +// br.sptk.many ia64_prepare_handle_reflection // TODO: why commented out? + br.call.sptk.many b6=ia64_handle_reflection END(dispatch_reflection) #define SAVE_MIN_COVER_DONE DO_SAVE_MIN(,mov r30=cr.ifs,) @@ -2134,10 +2223,10 @@ END(dispatch_slow_hyperprivop) #ifdef CONFIG_IA32_SUPPORT /* - * There is no particular reason for this code to be here, other than that - * there happens to be space here that would go unused otherwise. If this - * fault ever gets "unreserved", simply moved the following code to a more - * suitable spot... + * There is no particular reason for this code to be here, other + * than that there happens to be space here that would go unused + * otherwise. If this fault ever gets "unreserved", simply move + * the following code to a more suitable spot... */ // IA32 interrupt entry point @@ -2148,7 +2237,7 @@ ENTRY(dispatch_to_ia32_handler) mov r14=cr.isr ssm psr.ic | PSR_DEFAULT_BITS ;; - srlz.i // guarantee that interruption collection is on + srlz.i // guarantee that interruption collection is on ;; (p15) ssm psr.i adds r3=8,r2 // Base pointer for SAVE_REST @@ -2161,15 +2250,17 @@ ENTRY(dispatch_to_ia32_handler) cmp.ne p6,p0=r14,r15 (p6) br.call.dpnt.many b6=non_ia32_syscall - adds r14=IA64_PT_REGS_R8_OFFSET + 16,sp // 16 byte hole per SW conventions + adds r14=IA64_PT_REGS_R8_OFFSET + 16,sp // 16 byte hole per SW + // conventions adds r15=IA64_PT_REGS_R1_OFFSET + 16,sp ;; cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0 ld8 r8=[r14] // get r8 ;; - st8 [r15]=r8 // save original EAX in r1 (IA32 procs don't use the GP) + st8 [r15]=r8 // save original EAX in r1 (IA32 procs + // don't use the GP) ;; - alloc r15=ar.pfs,0,0,6,0 // must first in an insn group + alloc r15=ar.pfs,0,0,6,0 // must be first in an insn group ;; ld4 r8=[r14],8 // r8 == eax (syscall number) mov r15=IA32_NR_syscalls @@ -2208,7 +2299,7 @@ non_ia32_syscall: alloc r15=ar.pfs,0,0,2,0 mov out0=r14 // interrupt # add out1=16,sp // pointer to pt_regs - ;; // avoid WAW on CFM + ;; // avoid WAW on CFM br.call.sptk.many rp=ia32_bad_interrupt .ret1: movl r15=ia64_leave_kernel ;; From 86196de264354c591b06c0993e3e9567b6b88d9e Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Mon, 14 Aug 2006 13:42:00 -0600 Subject: [PATCH 05/58] [IA64] cleanup Cleanup of the week: Perf counters added. Use BUILD_BUG_ON instead of #error+macros. CPL is checked before calling ia64_hypercall(). Reformatting in hypercall.c multicall now check hypercall number. Signed-off-by: Tristan Gingold --- xen/arch/ia64/asm-offsets.c | 1 - xen/arch/ia64/linux-xen/irq_ia64.c | 6 +- xen/arch/ia64/linux-xen/smp.c | 3 + xen/arch/ia64/xen/faults.c | 3 +- xen/arch/ia64/xen/hypercall.c | 62 +++++++++---------- xen/arch/ia64/xen/irq.c | 3 - xen/arch/ia64/xen/privop.c | 2 +- xen/arch/ia64/xen/xensetup.c | 8 +-- xen/include/asm-ia64/dom_fw.h | 5 +- .../asm-ia64/linux-xen/asm/processor.h | 8 +++ xen/include/asm-ia64/multicall.h | 7 ++- 11 files changed, 54 insertions(+), 54 deletions(-) diff --git a/xen/arch/ia64/asm-offsets.c b/xen/arch/ia64/asm-offsets.c index f100c5f153..67b5725c56 100644 --- a/xen/arch/ia64/asm-offsets.c +++ b/xen/arch/ia64/asm-offsets.c @@ -31,7 +31,6 @@ void foo(void) DEFINE(IA64_SWITCH_STACK_SIZE, sizeof (struct switch_stack)); DEFINE(IA64_CPU_SIZE, sizeof (struct cpuinfo_ia64)); DEFINE(UNW_FRAME_INFO_SIZE, sizeof (struct unw_frame_info)); - DEFINE(SHARED_INFO_SIZE, sizeof (struct shared_info)); DEFINE(MAPPED_REGS_T_SIZE, sizeof (mapped_regs_t)); BLANK(); diff --git a/xen/arch/ia64/linux-xen/irq_ia64.c b/xen/arch/ia64/linux-xen/irq_ia64.c index ca2473a9ff..dccecdf250 100644 --- a/xen/arch/ia64/linux-xen/irq_ia64.c +++ b/xen/arch/ia64/linux-xen/irq_ia64.c @@ -108,6 +108,9 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs) { unsigned long saved_tpr; +#ifdef XEN + perfc_incrc(irqs); +#endif #if IRQ_DEBUG #ifdef XEN xen_debug_irq(vector, regs); @@ -290,8 +293,5 @@ ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect) ipi_data = (delivery_mode << 8) | (vector & 0xff); ipi_addr = ipi_base_addr + ((phys_cpu_id << 4) | ((redirect & 1) << 3)); -#ifdef XEN - //printf ("send_ipi to %d (%x)\n", cpu, phys_cpu_id); -#endif writeq(ipi_data, ipi_addr); } diff --git a/xen/arch/ia64/linux-xen/smp.c b/xen/arch/ia64/linux-xen/smp.c index 8801d28f64..67b80710f7 100644 --- a/xen/arch/ia64/linux-xen/smp.c +++ b/xen/arch/ia64/linux-xen/smp.c @@ -146,6 +146,9 @@ handle_IPI (int irq, void *dev_id, struct pt_regs *regs) unsigned long *pending_ipis = &__ia64_per_cpu_var(ipi_operation); unsigned long ops; +#ifdef XEN + perfc_incrc(ipis); +#endif mb(); /* Order interrupt and bit testing. */ while ((ops = xchg(pending_ipis, 0)) != 0) { mb(); /* Order bit clearing and data access. */ diff --git a/xen/arch/ia64/xen/faults.c b/xen/arch/ia64/xen/faults.c index 16bef26b31..171fddd041 100644 --- a/xen/arch/ia64/xen/faults.c +++ b/xen/arch/ia64/xen/faults.c @@ -515,7 +515,8 @@ ia64_handle_break (unsigned long ifa, struct pt_regs *regs, unsigned long isr, u debugger_trap_fatal(0 /* don't care */, regs); } #endif - else if (iim == d->arch.breakimm) { + else if (iim == d->arch.breakimm && + ia64_get_cpl(regs->cr_ipsr) == 2) { /* by default, do not continue */ v->arch.hypercall_continuation = 0; diff --git a/xen/arch/ia64/xen/hypercall.c b/xen/arch/ia64/xen/hypercall.c index 6fcc1ef72e..46d279b5b2 100644 --- a/xen/arch/ia64/xen/hypercall.c +++ b/xen/arch/ia64/xen/hypercall.c @@ -33,75 +33,81 @@ static long do_physdev_op_compat(XEN_GUEST_HANDLE(physdev_op_t) uop); static long do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg); static long do_callback_op(int cmd, XEN_GUEST_HANDLE(void) arg); -hypercall_t ia64_hypercall_table[] = - { - (hypercall_t)do_ni_hypercall, /* do_set_trap_table */ /* 0 */ +const hypercall_t ia64_hypercall_table[NR_hypercalls] = +{ + (hypercall_t)do_ni_hypercall, /* do_set_trap_table *//* 0 */ (hypercall_t)do_ni_hypercall, /* do_mmu_update */ (hypercall_t)do_ni_hypercall, /* do_set_gdt */ (hypercall_t)do_ni_hypercall, /* do_stack_switch */ (hypercall_t)do_ni_hypercall, /* do_set_callbacks */ - (hypercall_t)do_ni_hypercall, /* do_fpu_taskswitch */ /* 5 */ + (hypercall_t)do_ni_hypercall, /* do_fpu_taskswitch *//* 5 */ (hypercall_t)do_sched_op_compat, (hypercall_t)do_dom0_op, (hypercall_t)do_ni_hypercall, /* do_set_debugreg */ (hypercall_t)do_ni_hypercall, /* do_get_debugreg */ - (hypercall_t)do_ni_hypercall, /* do_update_descriptor */ /* 10 */ + (hypercall_t)do_ni_hypercall, /* do_update_descriptor * 10 */ (hypercall_t)do_ni_hypercall, /* do_ni_hypercall */ (hypercall_t)do_memory_op, (hypercall_t)do_multicall, (hypercall_t)do_ni_hypercall, /* do_update_va_mapping */ - (hypercall_t)do_ni_hypercall, /* do_set_timer_op */ /* 15 */ + (hypercall_t)do_ni_hypercall, /* do_set_timer_op */ /* 15 */ (hypercall_t)do_event_channel_op_compat, (hypercall_t)do_xen_version, (hypercall_t)do_console_io, (hypercall_t)do_physdev_op_compat, - (hypercall_t)do_grant_table_op, /* 20 */ + (hypercall_t)do_grant_table_op, /* 20 */ (hypercall_t)do_ni_hypercall, /* do_vm_assist */ - (hypercall_t)do_ni_hypercall, /* do_update_va_mapping_otherdomain */ + (hypercall_t)do_ni_hypercall, /* do_update_va_mapping_othe */ (hypercall_t)do_ni_hypercall, /* (x86 only) */ (hypercall_t)do_ni_hypercall, /* do_vcpu_op */ - (hypercall_t)do_ni_hypercall, /* (x86_64 only) */ /* 25 */ + (hypercall_t)do_ni_hypercall, /* (x86_64 only) */ /* 25 */ (hypercall_t)do_ni_hypercall, /* do_mmuext_op */ (hypercall_t)do_ni_hypercall, /* do_acm_op */ (hypercall_t)do_ni_hypercall, /* do_nmi_op */ (hypercall_t)do_sched_op, - (hypercall_t)do_callback_op, /* */ /* 30 */ + (hypercall_t)do_callback_op, /* */ /* 30 */ (hypercall_t)do_ni_hypercall, /* */ (hypercall_t)do_event_channel_op, (hypercall_t)do_physdev_op, (hypercall_t)do_hvm_op, /* */ - (hypercall_t)do_ni_hypercall, /* */ /* 35 */ + (hypercall_t)do_ni_hypercall, /* */ /* 35 */ (hypercall_t)do_ni_hypercall, /* */ (hypercall_t)do_ni_hypercall, /* */ (hypercall_t)do_ni_hypercall, /* */ (hypercall_t)do_ni_hypercall, /* */ - (hypercall_t)do_ni_hypercall, /* */ /* 40 */ + (hypercall_t)do_ni_hypercall, /* */ /* 40 */ (hypercall_t)do_ni_hypercall, /* */ (hypercall_t)do_ni_hypercall, /* */ (hypercall_t)do_ni_hypercall, /* */ (hypercall_t)do_ni_hypercall, /* */ - (hypercall_t)do_ni_hypercall, /* */ /* 45 */ + (hypercall_t)do_ni_hypercall, /* */ /* 45 */ (hypercall_t)do_ni_hypercall, /* */ (hypercall_t)do_ni_hypercall, /* */ - (hypercall_t)do_dom0vp_op, /* dom0vp_op */ + (hypercall_t)do_dom0vp_op, /* dom0vp_op */ (hypercall_t)do_ni_hypercall, /* arch_1 */ - (hypercall_t)do_ni_hypercall, /* arch_2 */ /* 50 */ + (hypercall_t)do_ni_hypercall, /* arch_2 */ /* 50 */ (hypercall_t)do_ni_hypercall, /* arch_3 */ (hypercall_t)do_ni_hypercall, /* arch_4 */ (hypercall_t)do_ni_hypercall, /* arch_5 */ (hypercall_t)do_ni_hypercall, /* arch_6 */ - (hypercall_t)do_ni_hypercall /* arch_7 */ /* 55 */ - }; - -uint32_t nr_hypercalls = - sizeof(ia64_hypercall_table) / sizeof(hypercall_t); + (hypercall_t)do_ni_hypercall, /* arch_7 */ /* 55 */ + (hypercall_t)do_ni_hypercall, + (hypercall_t)do_ni_hypercall, + (hypercall_t)do_ni_hypercall, + (hypercall_t)do_ni_hypercall, + (hypercall_t)do_ni_hypercall, /* 60 */ + (hypercall_t)do_ni_hypercall, + (hypercall_t)do_ni_hypercall, + (hypercall_t)do_ni_hypercall +}; static IA64FAULT xen_hypercall (struct pt_regs *regs) { uint32_t cmd = (uint32_t)regs->r2; - if (cmd < nr_hypercalls) + if (cmd < NR_hypercalls) { + perfc_incra(hypercalls, cmd); regs->r8 = (*ia64_hypercall_table[cmd])( regs->r14, regs->r15, @@ -109,13 +115,12 @@ xen_hypercall (struct pt_regs *regs) regs->r17, regs->r18, regs->r19); - else + } else regs->r8 = -ENOSYS; return IA64_NO_FAULT; } - static void fw_hypercall_ipi (struct pt_regs *regs) { @@ -277,18 +282,7 @@ fw_hypercall (struct pt_regs *regs) IA64FAULT ia64_hypercall (struct pt_regs *regs) { - struct vcpu *v = current; unsigned long index = regs->r2; - int privlvl = (regs->cr_ipsr & IA64_PSR_CPL) >> IA64_PSR_CPL0_BIT; - - /* Hypercalls are only allowed by kernel. - Kernel checks memory accesses. */ - if (VMX_DOMAIN(v) ? (privlvl != 0) : (privlvl != 2)) { - /* FIXME: Return a better error value ? - Reflection ? Illegal operation ? */ - regs->r8 = -1; - return IA64_NO_FAULT; - } if (index >= FW_HYPERCALL_FIRST_ARCH) return fw_hypercall (regs); diff --git a/xen/arch/ia64/xen/irq.c b/xen/arch/ia64/xen/irq.c index 26af99a7e5..7dd075cd1d 100644 --- a/xen/arch/ia64/xen/irq.c +++ b/xen/arch/ia64/xen/irq.c @@ -236,9 +236,6 @@ int setup_vector(unsigned int irq, struct irqaction * new) struct irqaction *old, **p; irq_desc_t *desc = irq_descp(irq); - printf ("setup_vector(%d): handler=%p, flags=%x\n", - irq, desc->handler, desc->status); - /* * The following block of code has to be executed atomically */ diff --git a/xen/arch/ia64/xen/privop.c b/xen/arch/ia64/xen/privop.c index 2053317e51..a66e215321 100644 --- a/xen/arch/ia64/xen/privop.c +++ b/xen/arch/ia64/xen/privop.c @@ -681,7 +681,7 @@ priv_emulate(VCPU *vcpu, REGS *regs, UINT64 isr) return IA64_ILLOP_FAULT; } //if (isrcode != 1 && isrcode != 2) return 0; - privlvl = (ipsr & IA64_PSR_CPL) >> IA64_PSR_CPL0_BIT; + privlvl = ia64_get_cpl(ipsr); // its OK for a privified-cover to be executed in user-land fault = priv_handle_op(vcpu,regs,privlvl); if ((fault == IA64_NO_FAULT) || (fault == IA64_EXTINT_VECTOR)) { // success!! diff --git a/xen/arch/ia64/xen/xensetup.c b/xen/arch/ia64/xen/xensetup.c index 2120c1ebf4..c9830575bf 100644 --- a/xen/arch/ia64/xen/xensetup.c +++ b/xen/arch/ia64/xen/xensetup.c @@ -26,11 +26,6 @@ #include #include -/* Be sure the struct shared_info size is <= XSI_SIZE. */ -#if SHARED_INFO_SIZE > XSI_SIZE -#error "struct shared_info bigger than XSI_SIZE" -#endif - unsigned long xenheap_phys_end, total_pages; char saved_command_line[COMMAND_LINE_SIZE]; @@ -258,6 +253,9 @@ void start_kernel(void) int i; #endif + /* Be sure the struct shared_info size is <= XSI_SIZE. */ + BUILD_BUG_ON(sizeof(struct shared_info) > XSI_SIZE); + running_on_sim = is_platform_hp_ski(); /* Kernel may be relocated by EFI loader */ xen_pstart = ia64_tpa(KERNEL_START); diff --git a/xen/include/asm-ia64/dom_fw.h b/xen/include/asm-ia64/dom_fw.h index 49980dc15d..10d7c2e380 100644 --- a/xen/include/asm-ia64/dom_fw.h +++ b/xen/include/asm-ia64/dom_fw.h @@ -150,14 +150,11 @@ /* Hypercalls index bellow _FIRST_ARCH are reserved by Xen, while those above are for the architecture. - Note: this limit was defined by Xen/ia64 (and not by Xen).² + Note: this limit was defined by Xen/ia64 (and not by Xen). This can be renumbered safely. */ #define FW_HYPERCALL_FIRST_ARCH 0x300UL -/* Xen/ia64 user hypercalls. Only used for debugging. */ -#define FW_HYPERCALL_FIRST_USER 0xff00UL - /* Interrupt vector used for os boot rendez vous. */ #define XEN_SAL_BOOT_RENDEZ_VEC 0xF3 diff --git a/xen/include/asm-ia64/linux-xen/asm/processor.h b/xen/include/asm-ia64/linux-xen/asm/processor.h index 1a713f4a0d..65f65538bc 100644 --- a/xen/include/asm-ia64/linux-xen/asm/processor.h +++ b/xen/include/asm-ia64/linux-xen/asm/processor.h @@ -717,6 +717,14 @@ prefetchw (const void *x) extern unsigned long boot_option_idle_override; +#ifdef XEN +static inline unsigned int +ia64_get_cpl(unsigned long psr) +{ + return (psr & IA64_PSR_CPL) >> IA64_PSR_CPL0_BIT; +} +#endif + #endif /* !__ASSEMBLY__ */ #endif /* _ASM_IA64_PROCESSOR_H */ diff --git a/xen/include/asm-ia64/multicall.h b/xen/include/asm-ia64/multicall.h index 53bb171c32..ea104e5efa 100644 --- a/xen/include/asm-ia64/multicall.h +++ b/xen/include/asm-ia64/multicall.h @@ -11,17 +11,20 @@ typedef unsigned long (*hypercall_t)( unsigned long arg4, unsigned long arg5); -extern hypercall_t ia64_hypercall_table[]; +extern const hypercall_t ia64_hypercall_table[]; static inline void do_multicall_call(multicall_entry_t *call) { - call->result = (*ia64_hypercall_table[call->op])( + if (call->op < NR_hypercalls) + call->result = (*ia64_hypercall_table[call->op])( call->args[0], call->args[1], call->args[2], call->args[3], call->args[4], call->args[5]); + else + call->result = -ENOSYS; } #endif /* __ASM_IA64_MULTICALL_H__ */ From 13600e97011a35c6f614028eeed94f853aea0879 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Mon, 14 Aug 2006 13:43:31 -0600 Subject: [PATCH 06/58] [IA64] 80-column reformatting for flushd.S Minor reformatting so that flushd.S can be used with 80-column displays, in accordance with Linux coding style. No instructions were changed. Signed-off-by: Al Stone --- xen/arch/ia64/xen/flushd.S | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/xen/arch/ia64/xen/flushd.S b/xen/arch/ia64/xen/flushd.S index 1a83e79a1c..76ac5f4b2a 100644 --- a/xen/arch/ia64/xen/flushd.S +++ b/xen/arch/ia64/xen/flushd.S @@ -16,8 +16,9 @@ * * Flush cache. * - * Must deal with range from start to end-1 but nothing else (need to - * be careful not to touch addresses that may be unmapped). + * Must deal with range from start to end-1 but nothing else + * (need to be careful not to touch addresses that may be + * unmapped). * * Note: "in0" and "in1" are preserved for debugging purposes. */ @@ -37,7 +38,8 @@ GLOBAL_ENTRY(flush_dcache_range) ;; sub r8=r22,r23 // number of strides - 1 shl r24=r23,r20 // r24: addresses for "fc" = - // "start" rounded down to stride boundary + // "start" rounded down to stride + // boundary .save ar.lc,r3 mov r3=ar.lc // save ar.lc ;; @@ -49,7 +51,8 @@ GLOBAL_ENTRY(flush_dcache_range) * 32 byte aligned loop, even number of (actually 2) bundles */ .Loop: fc r24 // issuable on M0 only - add r24=r21,r24 // we flush "stride size" bytes per iteration + add r24=r21,r24 // we flush "stride size" bytes per + // iteration nop.i 0 br.cloop.sptk.few .Loop ;; From e9b5dc88982b241b7c3c51a344b0aaf3f313e0d5 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Mon, 14 Aug 2006 13:46:05 -0600 Subject: [PATCH 07/58] [IA64] reformatting cleanup for xen.lds.S Minor reformatting changes to make xen.lds.S 80-column usable, in accordance with Linux coding style. Signed-off-by: Al Stone --- xen/arch/ia64/xen/xen.lds.S | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/xen/arch/ia64/xen/xen.lds.S b/xen/arch/ia64/xen/xen.lds.S index b9f0db4c1b..3884f80679 100644 --- a/xen/arch/ia64/xen/xen.lds.S +++ b/xen/arch/ia64/xen/xen.lds.S @@ -169,7 +169,9 @@ SECTIONS *(.data.gate) __stop_gate_section = .; } - . = ALIGN(PAGE_SIZE); /* make sure the gate page doesn't expose kernel data */ + . = ALIGN(PAGE_SIZE); /* make sure the gate page doesn't expose + * kernel data + */ .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) { *(.data.cacheline_aligned) } @@ -184,7 +186,9 @@ SECTIONS *(.data.percpu) __per_cpu_end = .; } - . = __phys_per_cpu_start + PERCPU_PAGE_SIZE; /* ensure percpu data fits into percpu page size */ + . = __phys_per_cpu_start + PERCPU_PAGE_SIZE; /* ensure percpu data fits + * into percpu page size + */ data : { } :data .data : AT(ADDR(.data) - LOAD_OFFSET) From ad81630fe1dfca00b4a1ce7e992ef65eff0e6543 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Mon, 14 Aug 2006 14:21:21 -0600 Subject: [PATCH 08/58] [IA64] copy_from/to_guest This patch fixes the copy_from/to_guest problem. As Akio reported, modularised netback causes dom0's down. The following process is happened in gnttab_transfer()@ xen/common/grant_table.c: gnttab_transfer() => steal_page() => assign_domain_page_cmpxchg_rel() => domain_page_flush() => domain_flush_vtlb_all() // all TLBs are flushed ... => __copy_to_guest_offset() // always fail to copy The embedded netback module has no problem because it uses TR pinned data. But modularised one is out of TR. So copy_from/to_guest issue must be solved in order to modularise drivers. Signed-off-by: Kouya SHIMURA --- .../arch/ia64/xen/hypervisor.c | 27 +++++++++++++++++-- .../include/asm-ia64/hypercall.h | 5 ++-- xen/arch/ia64/xen/hypercall.c | 13 +++++++++ xen/arch/ia64/xen/vcpu.c | 25 +++++++++++++++++ xen/include/asm-ia64/domain.h | 9 +++++++ xen/include/asm-ia64/uaccess.h | 18 +++++++++++-- 6 files changed, 91 insertions(+), 6 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c b/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c index 00efd9a1f7..10dc6a6477 100644 --- a/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c +++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c @@ -371,6 +371,8 @@ gnttab_map_grant_ref_pre(struct gnttab_map_grant_ref *uop) int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count) { + __u64 va1, va2, pa1, pa2; + if (cmd == GNTTABOP_map_grant_ref) { unsigned int i; for (i = 0; i < count; i++) { @@ -378,8 +380,29 @@ HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count) (struct gnttab_map_grant_ref*)uop + i); } } - - return ____HYPERVISOR_grant_table_op(cmd, uop, count); + va1 = (__u64)uop & PAGE_MASK; + pa1 = pa2 = 0; + if ((REGION_NUMBER(va1) == 5) && + ((va1 - KERNEL_START) >= KERNEL_TR_PAGE_SIZE)) { + pa1 = ia64_tpa(va1); + if (cmd <= GNTTABOP_transfer) { + static uint32_t uop_size[GNTTABOP_transfer + 1] = { + sizeof(struct gnttab_map_grant_ref), + sizeof(struct gnttab_unmap_grant_ref), + sizeof(struct gnttab_setup_table), + sizeof(struct gnttab_dump_table), + sizeof(struct gnttab_transfer), + }; + va2 = (__u64)uop + (uop_size[cmd] * count) - 1; + va2 &= PAGE_MASK; + if (va1 != va2) { + /* maximum size of uop is 2pages */ + BUG_ON(va2 > va1 + PAGE_SIZE); + pa2 = ia64_tpa(va2); + } + } + } + return ____HYPERVISOR_grant_table_op(cmd, uop, count, pa1, pa2); } EXPORT_SYMBOL(HYPERVISOR_grant_table_op); diff --git a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h index e2fe103e65..cc43e9bf15 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h @@ -275,9 +275,10 @@ HYPERVISOR_physdev_op( //XXX __HYPERVISOR_grant_table_op is used for this hypercall constant. static inline int ____HYPERVISOR_grant_table_op( - unsigned int cmd, void *uop, unsigned int count) + unsigned int cmd, void *uop, unsigned int count, + unsigned long pa1, unsigned long pa2) { - return _hypercall3(int, grant_table_op, cmd, uop, count); + return _hypercall5(int, grant_table_op, cmd, uop, count, pa1, pa2); } int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count); diff --git a/xen/arch/ia64/xen/hypercall.c b/xen/arch/ia64/xen/hypercall.c index 46d279b5b2..2c00024686 100644 --- a/xen/arch/ia64/xen/hypercall.c +++ b/xen/arch/ia64/xen/hypercall.c @@ -105,6 +105,19 @@ static IA64FAULT xen_hypercall (struct pt_regs *regs) { uint32_t cmd = (uint32_t)regs->r2; + struct vcpu *v = current; + + if (cmd == __HYPERVISOR_grant_table_op) { + XEN_GUEST_HANDLE(void) uop; + + v->arch.hypercall_param.va = regs->r15; + v->arch.hypercall_param.pa1 = regs->r17; + v->arch.hypercall_param.pa2 = regs->r18; + set_xen_guest_handle(uop, (void *)regs->r15); + regs->r8 = do_grant_table_op(regs->r14, uop, regs->r16); + v->arch.hypercall_param.va = 0; + return IA64_NO_FAULT; + } if (cmd < NR_hypercalls) { perfc_incra(hypercalls, cmd); diff --git a/xen/arch/ia64/xen/vcpu.c b/xen/arch/ia64/xen/vcpu.c index acbc492686..39f9b1d8ed 100644 --- a/xen/arch/ia64/xen/vcpu.c +++ b/xen/arch/ia64/xen/vcpu.c @@ -2215,3 +2215,28 @@ IA64FAULT vcpu_ptr_i(VCPU *vcpu,UINT64 vadr,UINT64 log_range) return IA64_NO_FAULT; } + +int ia64_map_hypercall_param(void) +{ + struct vcpu *v = current; + struct domain *d = current->domain; + u64 vaddr = v->arch.hypercall_param.va & PAGE_MASK; + volatile pte_t* pte; + + if (v->arch.hypercall_param.va == 0) + return FALSE; + pte = lookup_noalloc_domain_pte(d, v->arch.hypercall_param.pa1); + if (!pte || !pte_present(*pte)) + return FALSE; + vcpu_itc_no_srlz(v, 2, vaddr, pte_val(*pte), -1UL, PAGE_SHIFT); + if (v->arch.hypercall_param.pa2) { + vaddr += PAGE_SIZE; + pte = lookup_noalloc_domain_pte(d, v->arch.hypercall_param.pa2); + if (pte && pte_present(*pte)) { + vcpu_itc_no_srlz(v, 2, vaddr, pte_val(*pte), + -1UL, PAGE_SHIFT); + } + } + ia64_srlz_d(); + return TRUE; +} diff --git a/xen/include/asm-ia64/domain.h b/xen/include/asm-ia64/domain.h index 9c565cff9f..55882fcfab 100644 --- a/xen/include/asm-ia64/domain.h +++ b/xen/include/asm-ia64/domain.h @@ -142,6 +142,12 @@ struct arch_domain { (sizeof(vcpu_info_t) * (v)->vcpu_id + \ offsetof(vcpu_info_t, evtchn_upcall_mask)) +struct hypercall_param { + unsigned long va; + unsigned long pa1; + unsigned long pa2; +}; + struct arch_vcpu { /* Save the state of vcpu. This is the first entry to speed up accesses. */ @@ -185,6 +191,9 @@ struct arch_vcpu { char irq_new_pending; char irq_new_condition; // vpsr.i/vtpr change, check for pending VHPI char hypercall_continuation; + + struct hypercall_param hypercall_param; // used to remap a hypercall param + //for phycial emulation unsigned long old_rsc; int mode_flags; diff --git a/xen/include/asm-ia64/uaccess.h b/xen/include/asm-ia64/uaccess.h index 6cf5158954..17e2a17f9d 100644 --- a/xen/include/asm-ia64/uaccess.h +++ b/xen/include/asm-ia64/uaccess.h @@ -211,16 +211,30 @@ extern void __put_user_unknown (void); extern unsigned long __must_check __copy_user (void __user *to, const void __user *from, unsigned long count); +extern int ia64_map_hypercall_param(void); + static inline unsigned long __copy_to_user (void __user *to, const void *from, unsigned long count) { - return __copy_user(to, (void __user *) from, count); + unsigned long len; + len = __copy_user(to, (void __user *)from, count); + if (len == 0) + return 0; + if (ia64_map_hypercall_param()) + len = __copy_user(to, (void __user *)from, count); /* retry */ + return len; } static inline unsigned long __copy_from_user (void *to, const void __user *from, unsigned long count) { - return __copy_user((void __user *) to, from, count); + unsigned long len; + len = __copy_user((void __user *)to, from, count); + if (len == 0) + return 0; + if (ia64_map_hypercall_param()) + len = __copy_user((void __user *) to, from, count); /* retry */ + return len; } #define __copy_to_user_inatomic __copy_to_user From 696f5043df0ed8537a3410326ecf92370f210d8f Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Wed, 16 Aug 2006 09:13:03 -0600 Subject: [PATCH 09/58] [IA64] xenasm.S 80-column reformatting Minor reformatting (and fix a couple of typos) in xenasm.S so that it is readable in 80-column displays, in accordance with Linux coding style. Signed-off-by: Al Stone --- xen/arch/ia64/xen/xenasm.S | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/xen/arch/ia64/xen/xenasm.S b/xen/arch/ia64/xen/xenasm.S index 7477532152..890329b9ea 100644 --- a/xen/arch/ia64/xen/xenasm.S +++ b/xen/arch/ia64/xen/xenasm.S @@ -31,7 +31,7 @@ // loc0=rp, loc1=ar.pfs, loc2=percpu_paddr, loc3=psr, loc4=ar.rse // loc5=pal_vaddr, loc6=xen_paddr, loc7=shared_archinfo_paddr, GLOBAL_ENTRY(ia64_new_rr7) - // not sure this unwind statement is correct... + // FIXME? not sure this unwind statement is correct... .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(1) alloc loc1 = ar.pfs, 5, 8, 0, 0 movl loc2=PERCPU_ADDR @@ -162,7 +162,7 @@ GLOBAL_ENTRY(ia64_new_rr7) dep r25=0,loc5,60,4 // convert pal vaddr to paddr ;; ptr.i loc5,r23 - or r25=r25,r26 // construct PA | page properties + or r25=r25,r26 // construct PA | page properties mov cr.itir=r23 mov cr.ifa=loc5 ;; @@ -191,10 +191,10 @@ GLOBAL_ENTRY(ia64_prepare_handle_privop) */ mov r16=r0 DO_SAVE_SWITCH_STACK - br.call.sptk.many rp=ia64_handle_privop // stack frame setup in ivt + br.call.sptk.many rp=ia64_handle_privop // stack frame setup in ivt .ret22: .body DO_LOAD_SWITCH_STACK - br.cond.sptk.many rp // goes to ia64_leave_kernel + br.cond.sptk.many rp // goes to ia64_leave_kernel END(ia64_prepare_handle_privop) GLOBAL_ENTRY(ia64_prepare_handle_break) @@ -217,7 +217,7 @@ GLOBAL_ENTRY(ia64_prepare_handle_reflection) */ mov r16=r0 DO_SAVE_SWITCH_STACK - br.call.sptk.many rp=ia64_handle_reflection // stack frame setup in ivt + br.call.sptk.many rp=ia64_handle_reflection // stack frame setup in ivt .ret24: .body DO_LOAD_SWITCH_STACK br.cond.sptk.many rp // goes to ia64_leave_kernel @@ -301,7 +301,7 @@ static: cmp.eq p7,p8=6,r32 /* PAL_PTCE_INFO */ (p8) br.cond.sptk.few 1f #if 0 mov r9=ar.lc - movl r8=524288 /* flush 512k million cache lines (16MB) */ + movl r8=524288 /* flush 512k million cache lines (16MB) */ ;; mov ar.lc=r8 movl r8=0xe000000000000000 @@ -319,7 +319,9 @@ static: cmp.eq p7,p8=6,r32 /* PAL_PTCE_INFO */ 1: cmp.eq p7,p8=15,r32 /* PAL_PERF_MON_INFO */ (p8) br.cond.sptk.few 1f mov r8=0 /* status = 0 */ - movl r9 =0x08122f04 /* generic=4 width=47 retired=8 cycles=18 */ + movl r9 =0x08122f04 /* generic=4 width=47 retired=8 + * cycles=18 + */ mov r10=0 /* reserved */ mov r11=0 /* reserved */ mov r16=0xffff /* implemented PMC */ @@ -361,8 +363,8 @@ stacked: END(pal_emulator_static) // These instructions are copied in the domains. -// This is the virtual PAL, which simply does an hypercall. -// The size is 2 bunldes (32 Bytes). It handles both static and stacked +// This is the virtual PAL, which simply does a hypercall. +// The size is 2 bundles (32 Bytes). It handles both static and stacked // convention. // If you modify this code, you have to modify dom_fw.h (for the size) and // dom_fw_pal_hypercall_patch. @@ -376,7 +378,7 @@ GLOBAL_ENTRY(pal_call_stub) } { .mbb - break 0x1000 // Hypercall vector (Value is patched). + break 0x1000 // Hypercall vector (Value is patched). (p7) br.cond.sptk.few rp (p8) br.ret.sptk.few rp } From 28efc9d73d9209ce5878cb8a5ce302a820475473 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Wed, 16 Aug 2006 09:15:17 -0600 Subject: [PATCH 10/58] [IA64] fix non-CONFIG_XEN sparse tree build This patch fixes some over-zealous code removal with the P==M cleanup. Some of the P==M code was shared with the bare metal kernel. Also cleaned up a couple places we should have used CONFIG_XEN. From: Juan Quintela Signed-off-by: Alex Williamson --- linux-2.6-xen-sparse/arch/ia64/kernel/setup.c | 2 ++ linux-2.6-xen-sparse/include/asm-ia64/agp.h | 12 +++++++++++ .../include/asm-ia64/dma-mapping.h | 20 +++++++++++++++++++ linux-2.6-xen-sparse/include/asm-ia64/io.h | 6 ++++++ .../include/asm-ia64/machvec.h | 2 ++ linux-2.6-xen-sparse/include/asm-ia64/page.h | 3 +++ .../include/asm-ia64/pgalloc.h | 4 ++++ 7 files changed, 49 insertions(+) diff --git a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c index 12ab159f0d..fd49563dd7 100644 --- a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c +++ b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c @@ -565,7 +565,9 @@ setup_arch (char **cmdline_p) platform_setup(cmdline_p); paging_init(); +#ifdef CONFIG_XEN contiguous_bitmap_init(max_pfn); +#endif } /* diff --git a/linux-2.6-xen-sparse/include/asm-ia64/agp.h b/linux-2.6-xen-sparse/include/asm-ia64/agp.h index 31bf2831ed..e0bf8a4ab1 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/agp.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/agp.h @@ -19,10 +19,21 @@ #define flush_agp_cache() mb() /* Convert a physical address to an address suitable for the GART. */ +#ifndef CONFIG_XEN +#define phys_to_gart(x) (x) +#define gart_to_phys(x) (x) +#else #define phys_to_gart(x) phys_to_machine_for_dma(x) #define gart_to_phys(x) machine_to_phys_for_dma(x) +#endif /* GATT allocation. Returns/accepts GATT kernel virtual address. */ +#ifndef CONFIG_XEN +#define alloc_gatt_pages(order) \ + ((char *)__get_free_pages(GFP_KERNEL, (order))) +#define free_gatt_pages(table, order) \ + free_pages((unsigned long)(table), (order)) +#else #include static inline char* alloc_gatt_pages(unsigned int order) @@ -46,5 +57,6 @@ free_gatt_pages(void* table, unsigned int order) xen_destroy_contiguous_region((unsigned long)table, order); free_pages((unsigned long)table, order); } +#endif /* CONFIG_XEN */ #endif /* _ASM_IA64_AGP_H */ diff --git a/linux-2.6-xen-sparse/include/asm-ia64/dma-mapping.h b/linux-2.6-xen-sparse/include/asm-ia64/dma-mapping.h index a0e6f4200f..5d0206c469 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/dma-mapping.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/dma-mapping.h @@ -7,11 +7,28 @@ */ #include #include +#ifdef CONFIG_XEN /* Needed for arch/i386/kernel/swiotlb.c and arch/i386/kernel/pci-dma-xen.c */ #include /* Needed for arch/i386/kernel/swiotlb.c */ #include +#endif +#ifndef CONFIG_XEN +#define dma_alloc_coherent platform_dma_alloc_coherent +#define dma_alloc_noncoherent platform_dma_alloc_coherent /* coherent mem. is cheap */ +#define dma_free_coherent platform_dma_free_coherent +#define dma_free_noncoherent platform_dma_free_coherent +#define dma_map_single platform_dma_map_single +#define dma_map_sg platform_dma_map_sg +#define dma_unmap_single platform_dma_unmap_single +#define dma_unmap_sg platform_dma_unmap_sg +#define dma_sync_single_for_cpu platform_dma_sync_single_for_cpu +#define dma_sync_sg_for_cpu platform_dma_sync_sg_for_cpu +#define dma_sync_single_for_device platform_dma_sync_single_for_device +#define dma_sync_sg_for_device platform_dma_sync_sg_for_device +#define dma_mapping_error platform_dma_mapping_error +#else int dma_map_sg(struct device *hwdev, struct scatterlist *sg, int nents, enum dma_data_direction direction); void dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents, @@ -50,6 +67,7 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, swiotlb_sync_sg_for_device(dev,sg,nelems,direction); flush_write_buffers(); } +#endif #define dma_map_page(dev, pg, off, size, dir) \ dma_map_single(dev, page_address(pg) + (off), (size), (dir)) @@ -91,6 +109,7 @@ dma_cache_sync (void *vaddr, size_t size, enum dma_data_direction dir) #define dma_is_consistent(dma_handle) (1) /* all we do is coherent memory... */ +#ifdef CONFIG_XEN /* arch/i386/kernel/swiotlb.o requires */ void contiguous_bitmap_init(unsigned long end_pfn); @@ -111,5 +130,6 @@ range_straddles_page_boundary(void *p, size_t size) return (((((unsigned long)p & ~PAGE_MASK) + size) > PAGE_SIZE) && !test_bit(__pa(p) >> PAGE_SHIFT, contiguous_bitmap)); } +#endif #endif /* _ASM_IA64_DMA_MAPPING_H */ diff --git a/linux-2.6-xen-sparse/include/asm-ia64/io.h b/linux-2.6-xen-sparse/include/asm-ia64/io.h index 86f6297e38..a841d78d79 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/io.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/io.h @@ -97,6 +97,11 @@ extern int valid_mmap_phys_addr_range (unsigned long addr, size_t *count); * The following two macros are deprecated and scheduled for removal. * Please use the PCI-DMA interface defined in instead. */ +#ifndef CONFIG_XEN +#define bus_to_virt phys_to_virt +#define virt_to_bus virt_to_phys +#define page_to_bus page_to_phys +#else #define bus_to_virt(bus) \ phys_to_virt(machine_to_phys_for_dma(bus)) #define virt_to_bus(virt) \ @@ -124,6 +129,7 @@ extern int valid_mmap_phys_addr_range (unsigned long addr, size_t *count); (((bvec_to_bus((vec1)) + (vec1)->bv_len) == bvec_to_bus((vec2))) && \ ((bvec_to_pseudophys((vec1)) + (vec1)->bv_len) == \ bvec_to_pseudophys((vec2)))) +#endif /* CONFIG_XEN */ # endif /* KERNEL */ diff --git a/linux-2.6-xen-sparse/include/asm-ia64/machvec.h b/linux-2.6-xen-sparse/include/asm-ia64/machvec.h index 1a5158b8d1..ba0da7b7cf 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/machvec.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/machvec.h @@ -247,6 +247,7 @@ extern void machvec_init (const char *name); # error Unknown configuration. Update asm-ia64/machvec.h. # endif /* CONFIG_IA64_GENERIC */ +#ifdef CONFIG_XEN # define platform_dma_map_sg dma_map_sg # define platform_dma_unmap_sg dma_unmap_sg # define platform_dma_mapping_error dma_mapping_error @@ -259,6 +260,7 @@ extern void machvec_init (const char *name); dma_sync_single_for_cpu # define platform_dma_sync_single_for_device \ dma_sync_single_for_device +#endif /* * Declare default routines which aren't declared anywhere else: diff --git a/linux-2.6-xen-sparse/include/asm-ia64/page.h b/linux-2.6-xen-sparse/include/asm-ia64/page.h index 9a32648e71..67312ea310 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/page.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/page.h @@ -117,6 +117,9 @@ extern unsigned long max_low_pfn; # define pfn_to_page(pfn) (vmem_map + (pfn)) #endif +#ifndef CONFIG_XEN +#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) +#endif #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) #define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) diff --git a/linux-2.6-xen-sparse/include/asm-ia64/pgalloc.h b/linux-2.6-xen-sparse/include/asm-ia64/pgalloc.h index 3918324230..125eeb5362 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/pgalloc.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/pgalloc.h @@ -126,7 +126,11 @@ static inline void pmd_free(pmd_t * pmd) static inline void pmd_populate(struct mm_struct *mm, pmd_t * pmd_entry, struct page *pte) { +#ifndef CONFIG_XEN + pmd_val(*pmd_entry) = page_to_phys(pte); +#else pmd_val(*pmd_entry) = page_to_pseudophys(pte); +#endif } static inline void From 85116646bf1562eff274629f8771b7eafb277290 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Wed, 16 Aug 2006 09:18:16 -0600 Subject: [PATCH 11/58] [IA64] enable credit schedule on VTI-domain Signed-off-by: Anthony Xu --- xen/arch/ia64/xen/domain.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index 5258c40f95..b1d7fea427 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -111,6 +111,8 @@ void schedule_tail(struct vcpu *prev) if (VMX_DOMAIN(current)) { vmx_do_launch(current); + migrate_timer(¤t->arch.arch_vmx.vtm.vtm_timer, + current->processor); } else { ia64_set_iva(&ia64_ivt); ia64_set_pta(VHPT_ADDR | (1 << 8) | (VHPT_SIZE_LOG2 << 2) | @@ -147,6 +149,8 @@ void context_switch(struct vcpu *prev, struct vcpu *next) if (VMX_DOMAIN(current)){ vmx_load_all_rr(current); + migrate_timer(¤t->arch.arch_vmx.vtm.vtm_timer, + current->processor); } else { struct domain *nd; extern char ia64_ivt; From ede40297a7646896c3e797b5621ec31c90c2a02e Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Wed, 16 Aug 2006 10:21:13 -0600 Subject: [PATCH 12/58] [IA64] resolve VTI address wrap issue This patch resolves the address wrap issue in vtlb_purge and vhpt_purge Signed-off-by: Anthony Xu --- xen/arch/ia64/vmx/vtlb.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/xen/arch/ia64/vmx/vtlb.c b/xen/arch/ia64/vmx/vtlb.c index 1fffd1366d..8d2da7f308 100644 --- a/xen/arch/ia64/vmx/vtlb.c +++ b/xen/arch/ia64/vmx/vtlb.c @@ -245,7 +245,6 @@ u64 guest_vhpt_lookup(u64 iha, u64 *pte) return ret; } - /* * purge software guest tlb */ @@ -253,29 +252,29 @@ u64 guest_vhpt_lookup(u64 iha, u64 *pte) void vtlb_purge(VCPU *v, u64 va, u64 ps) { thash_data_t *cur; - u64 start, end, curadr, size, psbits, tag, def_size; + u64 start, curadr, size, psbits, tag, rr_ps, num; ia64_rr vrr; thash_cb_t *hcb = &v->arch.vtlb; + vcpu_get_rr(v, va, &vrr.rrval); psbits = VMX(v, psbits[(va >> 61)]); - size = PSIZE(ps); - start = va & (-size); - end = start + size; + start = va & ~((1UL << ps) - 1); while (psbits) { curadr = start; - ps = __ffs(psbits); - psbits &= ~(1UL << ps); - def_size = PSIZE(ps); - vrr.ps = ps; - /* Be careful about overflow. */ - while (curadr < end && curadr >= start) { + rr_ps = __ffs(psbits); + psbits &= ~(1UL << rr_ps); + num = 1UL << ((ps < rr_ps) ? 0 : (ps - rr_ps)); + size = PSIZE(rr_ps); + vrr.ps = rr_ps; + while (num) { cur = vsa_thash(hcb->pta, curadr, vrr.rrval, &tag); while (cur) { - if (cur->etag == tag && cur->ps == ps) + if (cur->etag == tag && cur->ps == rr_ps) cur->etag = 1UL << 63; cur = cur->next; } - curadr += def_size; + curadr += size; + num--; } } } @@ -288,14 +287,14 @@ static void vhpt_purge(VCPU *v, u64 va, u64 ps) { //thash_cb_t *hcb = &v->arch.vhpt; thash_data_t *cur; - u64 start, end, size, tag; + u64 start, size, tag, num; ia64_rr rr; - size = PSIZE(ps); - start = va & (-size); - end = start + size; - rr.rrval = ia64_get_rr(va); - size = PSIZE(rr.ps); - while(start < end){ + + start = va & ~((1UL << ps) - 1); + rr.rrval = ia64_get_rr(va); + size = PSIZE(rr.ps); + num = 1UL << ((ps < rr.ps) ? 0 : (ps - rr.ps)); + while (num) { cur = (thash_data_t *)ia64_thash(start); tag = ia64_ttag(start); while (cur) { @@ -304,6 +303,7 @@ static void vhpt_purge(VCPU *v, u64 va, u64 ps) cur = cur->next; } start += size; + num--; } machine_tlb_purge(va, ps); } From 9375145b1a8441e665b018042e6afb3cdf1ae417 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Wed, 16 Aug 2006 10:40:17 -0600 Subject: [PATCH 13/58] [IA64] efibootmgr support This patch supports the efibootmgr on Domain-0. This patch adds the following EFI runtime service emulations for the efibootmgr support. - GetVariable - GetNextVariableName - SetVariable Signed-off-by: Masaki Kanno --- xen/arch/ia64/xen/fw_emul.c | 164 +++++++++++++++++++++++++++++++++++- 1 file changed, 160 insertions(+), 4 deletions(-) diff --git a/xen/arch/ia64/xen/fw_emul.c b/xen/arch/ia64/xen/fw_emul.c index 3509ed446f..be96f92a6f 100644 --- a/xen/arch/ia64/xen/fw_emul.c +++ b/xen/arch/ia64/xen/fw_emul.c @@ -419,6 +419,141 @@ efi_emulate_get_time( return status; } +static efi_status_t +efi_emulate_get_variable( + unsigned long name_addr, unsigned long vendor_addr, + unsigned long attr_addr, unsigned long data_size_addr, + unsigned long data_addr, IA64FAULT *fault) +{ + unsigned long name, vendor, attr, data_size, data; + struct page_info *name_page = NULL, *vendor_page = NULL, + *attr_page = NULL, *data_size_page = NULL, + *data_page = NULL; + efi_status_t status = 0; + + if (current->domain != dom0) + return EFI_UNSUPPORTED; + + name = efi_translate_domain_addr(name_addr, fault, &name_page); + if (*fault != IA64_NO_FAULT) + goto errout; + vendor = efi_translate_domain_addr(vendor_addr, fault, &vendor_page); + if (*fault != IA64_NO_FAULT) + goto errout; + data_size = efi_translate_domain_addr(data_size_addr, fault, + &data_size_page); + if (*fault != IA64_NO_FAULT) + goto errout; + data = efi_translate_domain_addr(data_addr, fault, &data_page); + if (*fault != IA64_NO_FAULT) + goto errout; + if (attr_addr) { + attr = efi_translate_domain_addr(attr_addr, fault, &attr_page); + if (*fault != IA64_NO_FAULT) + goto errout; + } + + status = (*efi.get_variable)((efi_char16_t *)name, + (efi_guid_t *)vendor, + (u32 *)attr, + (unsigned long *)data_size, + (void *)data); + +errout: + if (name_page != NULL) + put_page(name_page); + if (vendor_page != NULL) + put_page(vendor_page); + if (attr_page != NULL) + put_page(attr_page); + if (data_size_page != NULL) + put_page(data_size_page); + if (data_page != NULL) + put_page(data_page); + + return status; +} + +static efi_status_t +efi_emulate_get_next_variable( + unsigned long name_size_addr, unsigned long name_addr, + unsigned long vendor_addr, IA64FAULT *fault) +{ + unsigned long name_size, name, vendor; + struct page_info *name_size_page = NULL, *name_page = NULL, + *vendor_page = NULL; + efi_status_t status = 0; + + if (current->domain != dom0) + return EFI_UNSUPPORTED; + + name_size = efi_translate_domain_addr(name_size_addr, fault, + &name_size_page); + if (*fault != IA64_NO_FAULT) + goto errout; + name = efi_translate_domain_addr(name_addr, fault, &name_page); + if (*fault != IA64_NO_FAULT) + goto errout; + vendor = efi_translate_domain_addr(vendor_addr, fault, &vendor_page); + if (*fault != IA64_NO_FAULT) + goto errout; + + status = (*efi.get_next_variable)((unsigned long *)name_size, + (efi_char16_t *)name, + (efi_guid_t *)vendor); + +errout: + if (name_size_page != NULL) + put_page(name_size_page); + if (name_page != NULL) + put_page(name_page); + if (vendor_page != NULL) + put_page(vendor_page); + + return status; +} + +static efi_status_t +efi_emulate_set_variable( + unsigned long name_addr, unsigned long vendor_addr, + unsigned long attr, unsigned long data_size, + unsigned long data_addr, IA64FAULT *fault) +{ + unsigned long name, vendor, data; + struct page_info *name_page = NULL, *vendor_page = NULL, + *data_page = NULL; + efi_status_t status = 0; + + if (current->domain != dom0) + return EFI_UNSUPPORTED; + + name = efi_translate_domain_addr(name_addr, fault, &name_page); + if (*fault != IA64_NO_FAULT) + goto errout; + vendor = efi_translate_domain_addr(vendor_addr, fault, &vendor_page); + if (*fault != IA64_NO_FAULT) + goto errout; + data = efi_translate_domain_addr(data_addr, fault, &data_page); + if (*fault != IA64_NO_FAULT) + goto errout; + + status = (*efi.set_variable)((efi_char16_t *)name, + (efi_guid_t *)vendor, + attr, + data_size, + (void *)data); + +errout: + if (name_page != NULL) + put_page(name_page); + if (vendor_page != NULL) + put_page(vendor_page); + if (data_page != NULL) + put_page(data_page); + + return status; +} + static efi_status_t efi_emulate_set_virtual_address_map( unsigned long memory_map_size, unsigned long descriptor_size, @@ -527,6 +662,31 @@ efi_emulator (struct pt_regs *regs, IA64FAULT *fault) vcpu_get_gr(v,33), fault); break; + case FW_HYPERCALL_EFI_GET_VARIABLE: + status = efi_emulate_get_variable ( + vcpu_get_gr(v,32), + vcpu_get_gr(v,33), + vcpu_get_gr(v,34), + vcpu_get_gr(v,35), + vcpu_get_gr(v,36), + fault); + break; + case FW_HYPERCALL_EFI_GET_NEXT_VARIABLE: + status = efi_emulate_get_next_variable ( + vcpu_get_gr(v,32), + vcpu_get_gr(v,33), + vcpu_get_gr(v,34), + fault); + break; + case FW_HYPERCALL_EFI_SET_VARIABLE: + status = efi_emulate_set_variable ( + vcpu_get_gr(v,32), + vcpu_get_gr(v,33), + vcpu_get_gr(v,34), + vcpu_get_gr(v,35), + vcpu_get_gr(v,36), + fault); + break; case FW_HYPERCALL_EFI_SET_VIRTUAL_ADDRESS_MAP: status = efi_emulate_set_virtual_address_map ( vcpu_get_gr(v,32), @@ -538,10 +698,6 @@ efi_emulator (struct pt_regs *regs, IA64FAULT *fault) case FW_HYPERCALL_EFI_GET_WAKEUP_TIME: case FW_HYPERCALL_EFI_SET_WAKEUP_TIME: // FIXME: need fixes in efi.h from 2.6.9 - case FW_HYPERCALL_EFI_GET_VARIABLE: - // FIXME: need fixes in efi.h from 2.6.9 - case FW_HYPERCALL_EFI_GET_NEXT_VARIABLE: - case FW_HYPERCALL_EFI_SET_VARIABLE: case FW_HYPERCALL_EFI_GET_NEXT_HIGH_MONO_COUNT: // FIXME: need fixes in efi.h from 2.6.9 status = EFI_UNSUPPORTED; From 5ee87bcc2be6f40ed1d861776387435102cc0067 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Wed, 16 Aug 2006 14:28:57 -0600 Subject: [PATCH 14/58] [IA64] handle ld.s on guest tr mapped page (VTI) Windows does an ld.s on a tr mapped page. Currently xen/ipf uses tc/vtlb to emulate guest TR, that may cause guest ld.s on tr page to be deferred, it is not correct. For trapping this ld.s intruction, xen/ipf always set machine dcr.dm=0. Signed-off-by: Anthony Xu [Moved cr.dcr restore to only impact vti -> non-vti switch] Signed-off-by: Alex Williamson --- xen/arch/ia64/vmx/vmx_phy_mode.c | 3 ++- xen/arch/ia64/xen/domain.c | 14 +++++++++++--- xen/include/asm-ia64/vmx_vcpu.h | 7 ++++--- xen/include/asm-ia64/vmx_vpd.h | 1 + 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/xen/arch/ia64/vmx/vmx_phy_mode.c b/xen/arch/ia64/vmx/vmx_phy_mode.c index bab3199dae..4d55c62bf6 100644 --- a/xen/arch/ia64/vmx/vmx_phy_mode.c +++ b/xen/arch/ia64/vmx/vmx_phy_mode.c @@ -195,7 +195,8 @@ vmx_load_all_rr(VCPU *vcpu) (void *)vcpu->domain->shared_info, (void *)vcpu->arch.privregs, (void *)vcpu->arch.vhpt.hash, pal_vaddr ); - ia64_set_pta(vcpu->arch.arch_vmx.mpta); + ia64_set_pta(VMX(vcpu, mpta)); + ia64_set_dcr(VMX(vcpu, mdcr)); ia64_srlz_d(); ia64_set_psr(psr); diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index b1d7fea427..4aababfd68 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -136,10 +136,18 @@ void context_switch(struct vcpu *prev, struct vcpu *next) __ia64_save_fpu(prev->arch._thread.fph); __ia64_load_fpu(next->arch._thread.fph); - if (VMX_DOMAIN(prev)) - vmx_save_state(prev); + if (VMX_DOMAIN(prev)) { + vmx_save_state(prev); + if (!VMX_DOMAIN(next)) { + /* VMX domains can change the physical cr.dcr. + * Restore default to prevent leakage. */ + ia64_setreg(_IA64_REG_CR_DCR, (IA64_DCR_DP | IA64_DCR_DK + | IA64_DCR_DX | IA64_DCR_DR | IA64_DCR_PP + | IA64_DCR_DA | IA64_DCR_DD | IA64_DCR_LC)); + } + } if (VMX_DOMAIN(next)) - vmx_load_state(next); + vmx_load_state(next); /*ia64_psr(ia64_task_regs(next))->dfh = !ia64_is_local_fpu_owner(next);*/ prev = ia64_switch_to(next); diff --git a/xen/include/asm-ia64/vmx_vcpu.h b/xen/include/asm-ia64/vmx_vcpu.h index 461bc6b710..a82e31fb7f 100644 --- a/xen/include/asm-ia64/vmx_vcpu.h +++ b/xen/include/asm-ia64/vmx_vcpu.h @@ -239,12 +239,13 @@ vmx_vcpu_set_dcr(VCPU *vcpu, u64 val) { u64 mdcr, mask; VCPU(vcpu,dcr)=val; - /* All vDCR bits will go to mDCR, except for be/pp bit */ + /* All vDCR bits will go to mDCR, except for be/pp/dm bits */ mdcr = ia64_get_dcr(); - mask = IA64_DCR_BE | IA64_DCR_PP; + /* Machine dcr.dm masked to handle guest ld.s on tr mapped page */ + mask = IA64_DCR_BE | IA64_DCR_PP | IA64_DCR_DM; mdcr = ( mdcr & mask ) | ( val & (~mask) ); ia64_set_dcr( mdcr); - + VMX(vcpu, mdcr) = mdcr; return IA64_NO_FAULT; } diff --git a/xen/include/asm-ia64/vmx_vpd.h b/xen/include/asm-ia64/vmx_vpd.h index 77d79fb704..e6a7ee48c5 100644 --- a/xen/include/asm-ia64/vmx_vpd.h +++ b/xen/include/asm-ia64/vmx_vpd.h @@ -89,6 +89,7 @@ struct arch_vmx_struct { // unsigned long mrr5; // unsigned long mrr6; // unsigned long mrr7; + unsigned long mdcr; unsigned long mpta; // unsigned long rfi_pfs; // unsigned long rfi_iip; From d54d68fc92b80b1ea9ff9ec9dfdb9cdbb530d9b2 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Fri, 18 Aug 2006 13:31:48 -0600 Subject: [PATCH 15/58] [IA64] reformatting hyperprivop.S for 80-column readability Minor reformatting to hyperprivop.S to make it readable on 80-column displays, as requested by Linux coding style. Minor formatting changes and typo corrections to get the style more in line with the other .S files. Signed-off-by: Al Stone --- xen/arch/ia64/xen/hyperprivop.S | 81 +++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 29 deletions(-) diff --git a/xen/arch/ia64/xen/hyperprivop.S b/xen/arch/ia64/xen/hyperprivop.S index 67efc3fc96..a93d7591b1 100644 --- a/xen/arch/ia64/xen/hyperprivop.S +++ b/xen/arch/ia64/xen/hyperprivop.S @@ -18,7 +18,8 @@ #define _PAGE_PPN_MASK 0x0003fffffffff000 //asm/pgtable.h doesn't do assembly -#define PAGE_PHYS 0x0010000000000761 //__pgprot(__DIRTY_BITS|_PAGE_PL_2|_PAGE_AR_RWX) +#define PAGE_PHYS 0x0010000000000761 //__pgprot(__DIRTY_BITS| + // _PAGE_PL_2|_PAGE_AR_RWX) #define _PAGE_PL_2 (2<<7) #if 1 // change to 0 to turn off all fast paths @@ -32,10 +33,10 @@ //#define FAST_TICK // mostly working (unat problems) but default off for now //#define FAST_TLB_MISS_REFLECT // mostly working but default off for now -# undef FAST_ITC //XXX TODO fast_itc doesn't suport dom0 vp yet. +# undef FAST_ITC //XXX TODO fast_itc doesn't support dom0 vp yet # define FAST_BREAK -# undef FAST_ACCESS_REFLECT //XXX TODO fast_access_reflect - // doesn't support dom0 vp yet. +# undef FAST_ACCESS_REFLECT //XXX TODO fast_access_reflect + // doesn't support dom0 vp yet. # define FAST_RFI # define FAST_SSM_I # define FAST_PTC_GA @@ -104,79 +105,100 @@ GLOBAL_ENTRY(fast_hyperprivop) 1: // when we get to here r20=~=interrupts pending // Check pending event indication (p7) movl r20=THIS_CPU(current_psr_i_addr);; -(p7) ld8 r20=[r20];; -(p7) adds r20=-1,r20;; /* evtchn_upcall_pending */ -(p7) ld1 r20=[r20];; +(p7) ld8 r20=[r20] + ;; +(p7) adds r20=-1,r20 // evtchn_upcall_pending + ;; +(p7) ld1 r20=[r20] + ;; // HYPERPRIVOP_RFI? cmp.eq p7,p6=HYPERPRIVOP_RFI,r17 -(p7) br.sptk.many hyper_rfi;; +(p7) br.sptk.many hyper_rfi + ;; // HYPERPRIVOP_GET_IVR? cmp.eq p7,p6=HYPERPRIVOP_GET_IVR,r17 -(p7) br.sptk.many hyper_get_ivr;; +(p7) br.sptk.many hyper_get_ivr + ;; cmp.ne p7,p0=r20,r0 -(p7) br.spnt.many dispatch_break_fault ;; +(p7) br.spnt.many dispatch_break_fault + ;; // HYPERPRIVOP_COVER? cmp.eq p7,p6=HYPERPRIVOP_COVER,r17 -(p7) br.sptk.many hyper_cover;; +(p7) br.sptk.many hyper_cover + ;; // HYPERPRIVOP_SSM_DT? cmp.eq p7,p6=HYPERPRIVOP_SSM_DT,r17 -(p7) br.sptk.many hyper_ssm_dt;; +(p7) br.sptk.many hyper_ssm_dt + ;; // HYPERPRIVOP_RSM_DT? cmp.eq p7,p6=HYPERPRIVOP_RSM_DT,r17 -(p7) br.sptk.many hyper_rsm_dt;; +(p7) br.sptk.many hyper_rsm_dt + ;; // HYPERPRIVOP_GET_TPR? cmp.eq p7,p6=HYPERPRIVOP_GET_TPR,r17 -(p7) br.sptk.many hyper_get_tpr;; +(p7) br.sptk.many hyper_get_tpr + ;; // HYPERPRIVOP_SET_TPR? cmp.eq p7,p6=HYPERPRIVOP_SET_TPR,r17 -(p7) br.sptk.many hyper_set_tpr;; +(p7) br.sptk.many hyper_set_tpr + ;; // HYPERPRIVOP_EOI? cmp.eq p7,p6=HYPERPRIVOP_EOI,r17 -(p7) br.sptk.many hyper_eoi;; +(p7) br.sptk.many hyper_eoi + ;; // HYPERPRIVOP_SET_ITM? cmp.eq p7,p6=HYPERPRIVOP_SET_ITM,r17 -(p7) br.sptk.many hyper_set_itm;; +(p7) br.sptk.many hyper_set_itm + ;; // HYPERPRIVOP_SET_RR? cmp.eq p7,p6=HYPERPRIVOP_SET_RR,r17 -(p7) br.sptk.many hyper_set_rr;; +(p7) br.sptk.many hyper_set_rr + ;; // HYPERPRIVOP_GET_RR? cmp.eq p7,p6=HYPERPRIVOP_GET_RR,r17 -(p7) br.sptk.many hyper_get_rr;; +(p7) br.sptk.many hyper_get_rr + ;; // HYPERPRIVOP_PTC_GA? cmp.eq p7,p6=HYPERPRIVOP_PTC_GA,r17 -(p7) br.sptk.many hyper_ptc_ga;; +(p7) br.sptk.many hyper_ptc_ga + ;; // HYPERPRIVOP_ITC_D? cmp.eq p7,p6=HYPERPRIVOP_ITC_D,r17 -(p7) br.sptk.many hyper_itc_d;; +(p7) br.sptk.many hyper_itc_d + ;; // HYPERPRIVOP_ITC_I? cmp.eq p7,p6=HYPERPRIVOP_ITC_I,r17 -(p7) br.sptk.many hyper_itc_i;; +(p7) br.sptk.many hyper_itc_i + ;; // HYPERPRIVOP_THASH? cmp.eq p7,p6=HYPERPRIVOP_THASH,r17 -(p7) br.sptk.many hyper_thash;; +(p7) br.sptk.many hyper_thash + ;; // HYPERPRIVOP_SET_KR? cmp.eq p7,p6=HYPERPRIVOP_SET_KR,r17 -(p7) br.sptk.many hyper_set_kr;; +(p7) br.sptk.many hyper_set_kr + ;; // if not one of the above, give up for now and do it the slow way - br.sptk.many dispatch_break_fault ;; + br.sptk.many dispatch_break_fault + ;; END(fast_hyperprivop) // give up for now if: ipsr.be==1, ipsr.pp==1 @@ -701,9 +723,9 @@ ENTRY(fast_reflect) .mem.offset 0,0; st8.spill [r2]=r30,16; .mem.offset 8,0; st8.spill [r3]=r31,16 ;; #ifdef HANDLE_AR_UNAT - // r16~r23 are preserved regsin bank0 regs, we need to restore them, - // r24~r31 are scratch regs, we don't need to handle NaT bit, - // because OS handler must assign it before access it + // r16~r23 are preserved regs in bank0 regs, we need to restore them, + // r24~r31 are scratch regs, we don't need to handle NaT bit, + // because OS handler must assign it before access it ld8 r16=[r2],16; ld8 r17=[r3],16;; ld8 r18=[r2],16; @@ -1114,7 +1136,8 @@ just_do_rfi: (p7) st4 [r18]=r19;; (p6) st4 [r18]=r0;; // force on psr.ic, i, dt, rt, it, bn - movl r20=(IA64_PSR_I|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_IT|IA64_PSR_BN) + movl r20=(IA64_PSR_I|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT| \ + IA64_PSR_IT|IA64_PSR_BN) ;; or r21=r21,r20 ;; From 4164bca7765b0ccc1ed04e9ecda93db9a4388747 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Fri, 18 Aug 2006 13:34:25 -0600 Subject: [PATCH 16/58] [IA64] perfc compile error patch Signed-off-by: Ken Hironaka --- xen/arch/ia64/xen/hypercall.c | 1 + 1 file changed, 1 insertion(+) diff --git a/xen/arch/ia64/xen/hypercall.c b/xen/arch/ia64/xen/hypercall.c index 2c00024686..6d4927e849 100644 --- a/xen/arch/ia64/xen/hypercall.c +++ b/xen/arch/ia64/xen/hypercall.c @@ -28,6 +28,7 @@ #include #include #include +#include static long do_physdev_op_compat(XEN_GUEST_HANDLE(physdev_op_t) uop); static long do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg); From 4748dbf76f5e8a0fad19da152ac0db51c8e759d5 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Fri, 18 Aug 2006 15:01:04 -0600 Subject: [PATCH 17/58] [IA64] makes some includes explicit Make some includes explicit. Do not compile anymore vmx/mm.c: not used. Signed-off-by: Tristan Gingold --- xen/arch/ia64/linux-xen/iosapic.c | 2 ++ xen/arch/ia64/linux-xen/irq_ia64.c | 4 ++++ xen/arch/ia64/linux-xen/mca.c | 1 + xen/arch/ia64/linux-xen/process-linux-xen.c | 3 +++ xen/arch/ia64/linux-xen/smp.c | 1 + xen/arch/ia64/linux-xen/unwind.c | 3 +++ xen/arch/ia64/vmx/Makefile | 2 +- xen/arch/ia64/vmx/mmio.c | 2 +- xen/arch/ia64/vmx/vmmu.c | 1 + xen/arch/ia64/vmx/vtlb.c | 2 +- xen/arch/ia64/xen/acpi.c | 3 +++ xen/arch/ia64/xen/dom0_ops.c | 1 + xen/arch/ia64/xen/dom_fw.c | 1 + xen/arch/ia64/xen/faults.c | 3 +++ xen/arch/ia64/xen/fw_emul.c | 1 + xen/arch/ia64/xen/hypercall.c | 1 + xen/arch/ia64/xen/irq.c | 1 - xen/arch/ia64/xen/mm.c | 3 ++- xen/arch/ia64/xen/pcdp.c | 1 + xen/arch/ia64/xen/privop.c | 1 + xen/arch/ia64/xen/vcpu.c | 2 ++ xen/include/asm-ia64/multicall.h | 1 + 22 files changed, 35 insertions(+), 5 deletions(-) diff --git a/xen/arch/ia64/linux-xen/iosapic.c b/xen/arch/ia64/linux-xen/iosapic.c index 29a20c58df..90d9ba38f4 100644 --- a/xen/arch/ia64/linux-xen/iosapic.c +++ b/xen/arch/ia64/linux-xen/iosapic.c @@ -77,6 +77,8 @@ #include #ifndef XEN #include +#else +#include #endif #include #include diff --git a/xen/arch/ia64/linux-xen/irq_ia64.c b/xen/arch/ia64/linux-xen/irq_ia64.c index dccecdf250..b7b82c24e8 100644 --- a/xen/arch/ia64/linux-xen/irq_ia64.c +++ b/xen/arch/ia64/linux-xen/irq_ia64.c @@ -40,6 +40,10 @@ #include #include +#ifdef XEN +#include +#endif + #ifdef CONFIG_PERFMON # include #endif diff --git a/xen/arch/ia64/linux-xen/mca.c b/xen/arch/ia64/linux-xen/mca.c index 6d37730942..1e4a86061b 100644 --- a/xen/arch/ia64/linux-xen/mca.c +++ b/xen/arch/ia64/linux-xen/mca.c @@ -79,6 +79,7 @@ #ifdef XEN #include +#include #endif #if defined(IA64_MCA_DEBUG_INFO) diff --git a/xen/arch/ia64/linux-xen/process-linux-xen.c b/xen/arch/ia64/linux-xen/process-linux-xen.c index 228280f2b8..aaaaaca0fe 100644 --- a/xen/arch/ia64/linux-xen/process-linux-xen.c +++ b/xen/arch/ia64/linux-xen/process-linux-xen.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -166,6 +167,7 @@ show_regs (struct pt_regs *regs) printk("r26 : %016lx r27 : %016lx r28 : %016lx\n", regs->r26, regs->r27, regs->r28); printk("r29 : %016lx r30 : %016lx r31 : %016lx\n", regs->r29, regs->r30, regs->r31); +#ifndef XEN if (user_mode(regs)) { /* print the stacked registers */ unsigned long val, *bsp, ndirty; @@ -180,6 +182,7 @@ show_regs (struct pt_regs *regs) ((i == sof - 1) || (i % 3) == 2) ? "\n" : " "); } } else +#endif show_stack(NULL, NULL); } diff --git a/xen/arch/ia64/linux-xen/smp.c b/xen/arch/ia64/linux-xen/smp.c index 67b80710f7..2f4ed8b6a9 100644 --- a/xen/arch/ia64/linux-xen/smp.c +++ b/xen/arch/ia64/linux-xen/smp.c @@ -48,6 +48,7 @@ #include #include #ifdef XEN +#include #include #include #endif diff --git a/xen/arch/ia64/linux-xen/unwind.c b/xen/arch/ia64/linux-xen/unwind.c index 168948ecc0..2933a5b02f 100644 --- a/xen/arch/ia64/linux-xen/unwind.c +++ b/xen/arch/ia64/linux-xen/unwind.c @@ -33,6 +33,7 @@ #include #include #include +#include // work around #ifdef CONFIG_SMP @@ -2315,6 +2316,7 @@ unw_init (void) __start_unwind, __end_unwind); } +#ifndef XEN /* * DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED * @@ -2353,3 +2355,4 @@ sys_getunwind (void __user *buf, size_t buf_size) return -EFAULT; return unw.gate_table_size; } +#endif diff --git a/xen/arch/ia64/vmx/Makefile b/xen/arch/ia64/vmx/Makefile index 0db1f84a4b..9e90d955c9 100644 --- a/xen/arch/ia64/vmx/Makefile +++ b/xen/arch/ia64/vmx/Makefile @@ -1,5 +1,5 @@ obj-y += hvm_vioapic.o -obj-y += mm.o +#obj-y += mm.o obj-y += mmio.o obj-y += pal_emul.o obj-y += vlsapic.o diff --git a/xen/arch/ia64/vmx/mmio.c b/xen/arch/ia64/vmx/mmio.c index c1de4a786f..5501acb74d 100644 --- a/xen/arch/ia64/vmx/mmio.c +++ b/xen/arch/ia64/vmx/mmio.c @@ -22,6 +22,7 @@ */ #include +#include #include #include #include @@ -30,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/xen/arch/ia64/vmx/vmmu.c b/xen/arch/ia64/vmx/vmmu.c index 4bff1727ea..9412810f3d 100644 --- a/xen/arch/ia64/vmx/vmmu.c +++ b/xen/arch/ia64/vmx/vmmu.c @@ -33,6 +33,7 @@ #include #include #include +#include /* * Get the machine page frame number in 16KB unit diff --git a/xen/arch/ia64/vmx/vtlb.c b/xen/arch/ia64/vmx/vtlb.c index 8d2da7f308..bc6fe21d8f 100644 --- a/xen/arch/ia64/vmx/vtlb.c +++ b/xen/arch/ia64/vmx/vtlb.c @@ -23,7 +23,7 @@ #include #include -#include +#include #include #include #include diff --git a/xen/arch/ia64/xen/acpi.c b/xen/arch/ia64/xen/acpi.c index 7635cb053d..af1748f1cb 100644 --- a/xen/arch/ia64/xen/acpi.c +++ b/xen/arch/ia64/xen/acpi.c @@ -51,6 +51,9 @@ #include #include #include +#ifdef XEN +#include +#endif #define BAD_MADT_ENTRY(entry, end) ( \ (!entry) || (unsigned long)entry + sizeof(*entry) > end || \ diff --git a/xen/arch/ia64/xen/dom0_ops.c b/xen/arch/ia64/xen/dom0_ops.c index e08da03964..f8d2757c2c 100644 --- a/xen/arch/ia64/xen/dom0_ops.c +++ b/xen/arch/ia64/xen/dom0_ops.c @@ -21,6 +21,7 @@ #include #include #include +#include void build_physmap_table(struct domain *d); diff --git a/xen/arch/ia64/xen/dom_fw.c b/xen/arch/ia64/xen/dom_fw.c index 5eb6643959..2a70b66e66 100644 --- a/xen/arch/ia64/xen/dom_fw.c +++ b/xen/arch/ia64/xen/dom_fw.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include diff --git a/xen/arch/ia64/xen/faults.c b/xen/arch/ia64/xen/faults.c index 171fddd041..f2e3a1bef7 100644 --- a/xen/arch/ia64/xen/faults.c +++ b/xen/arch/ia64/xen/faults.c @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include @@ -28,6 +30,7 @@ #include #include #include +#include extern void die_if_kernel(char *str, struct pt_regs *regs, long err); /* FIXME: where these declarations shold be there ? */ diff --git a/xen/arch/ia64/xen/fw_emul.c b/xen/arch/ia64/xen/fw_emul.c index be96f92a6f..5b8c91cabf 100644 --- a/xen/arch/ia64/xen/fw_emul.c +++ b/xen/arch/ia64/xen/fw_emul.c @@ -28,6 +28,7 @@ #include "hpsim_ssc.h" #include #include +#include extern unsigned long running_on_sim; diff --git a/xen/arch/ia64/xen/hypercall.c b/xen/arch/ia64/xen/hypercall.c index 6d4927e849..b5321e030c 100644 --- a/xen/arch/ia64/xen/hypercall.c +++ b/xen/arch/ia64/xen/hypercall.c @@ -11,6 +11,7 @@ #include #include #include +#include #include /* FOR EFI_UNIMPLEMENTED */ #include /* FOR struct ia64_sal_retval */ diff --git a/xen/arch/ia64/xen/irq.c b/xen/arch/ia64/xen/irq.c index 7dd075cd1d..98f11cad11 100644 --- a/xen/arch/ia64/xen/irq.c +++ b/xen/arch/ia64/xen/irq.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include diff --git a/xen/arch/ia64/xen/mm.c b/xen/arch/ia64/xen/mm.c index 35e299c951..eab9391bb5 100644 --- a/xen/arch/ia64/xen/mm.c +++ b/xen/arch/ia64/xen/mm.c @@ -166,7 +166,8 @@ #include #include #include -#include +#include +#include #include #include #include diff --git a/xen/arch/ia64/xen/pcdp.c b/xen/arch/ia64/xen/pcdp.c index 6c97d87f3c..4f968cd330 100644 --- a/xen/arch/ia64/xen/pcdp.c +++ b/xen/arch/ia64/xen/pcdp.c @@ -18,6 +18,7 @@ #ifdef XEN #include #include +#include #include #include #include diff --git a/xen/arch/ia64/xen/privop.c b/xen/arch/ia64/xen/privop.c index a66e215321..31e1ebc198 100644 --- a/xen/arch/ia64/xen/privop.c +++ b/xen/arch/ia64/xen/privop.c @@ -13,6 +13,7 @@ #include #include #include +#include long priv_verbose=0; unsigned long privop_trace = 0; diff --git a/xen/arch/ia64/xen/vcpu.c b/xen/arch/ia64/xen/vcpu.c index 39f9b1d8ed..7ab3197393 100644 --- a/xen/arch/ia64/xen/vcpu.c +++ b/xen/arch/ia64/xen/vcpu.c @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -22,6 +23,7 @@ #include #include #include +#include /* FIXME: where these declarations should be there ? */ extern void getreg(unsigned long regnum, unsigned long *val, int *nat, struct pt_regs *regs); diff --git a/xen/include/asm-ia64/multicall.h b/xen/include/asm-ia64/multicall.h index ea104e5efa..15b825bbf0 100644 --- a/xen/include/asm-ia64/multicall.h +++ b/xen/include/asm-ia64/multicall.h @@ -2,6 +2,7 @@ #define __ASM_IA64_MULTICALL_H__ #include +#include typedef unsigned long (*hypercall_t)( unsigned long arg0, From 90eb4e2617926931627c38d872afa880d4c230d0 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Tue, 22 Aug 2006 14:40:48 -0600 Subject: [PATCH 18/58] [IA64] HMVOP_get_param return parameter value HMVOP_get_param return parameter value within the provided parameter struct for IPF Signed-off-by: Tsunehisa Doi Signed-off-by: Tomonari Horikoshi --- xen/arch/ia64/vmx/vmx_hypercall.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/xen/arch/ia64/vmx/vmx_hypercall.c b/xen/arch/ia64/vmx/vmx_hypercall.c index 3d34babe15..bc3c6e7cab 100644 --- a/xen/arch/ia64/vmx/vmx_hypercall.c +++ b/xen/arch/ia64/vmx/vmx_hypercall.c @@ -59,21 +59,23 @@ do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) } else if (IS_PRIV(current->domain)) { d = find_domain_by_id(a.domid); - if (!d) + if (d == NULL) return -ESRCH; } else return -EPERM; if (op == HVMOP_set_param) { - rc = 0; d->arch.hvm_domain.params[a.index] = a.value; + rc = 0; + } + else { + a.value = d->arch.hvm_domain.params[a.index]; + rc = copy_to_guest(arg, &a, 1) ? -EFAULT : 0; } - else - rc = d->arch.hvm_domain.params[a.index]; put_domain(d); - return rc; + break; } default: From 85cbac388ebe141eb1e423ee4e8b124b55641f3a Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Tue, 22 Aug 2006 14:42:05 -0600 Subject: [PATCH 19/58] [IA64] Add support for sending event channel interrupts to VT-i guest Signed-off-by: Tsunehisa Doi Signed-off-by: Tomonari Horikoshi --- xen/arch/ia64/vmx/vmx_process.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/xen/arch/ia64/vmx/vmx_process.c b/xen/arch/ia64/vmx/vmx_process.c index e36d81820d..b56d8e7665 100644 --- a/xen/arch/ia64/vmx/vmx_process.c +++ b/xen/arch/ia64/vmx/vmx_process.c @@ -186,6 +186,7 @@ void leave_hypervisor_tail(struct pt_regs *regs) { struct domain *d = current->domain; struct vcpu *v = current; + int callback_irq; // FIXME: Will this work properly if doing an RFI??? if (!is_idle_domain(d) ) { // always comes from guest // struct pt_regs *user_regs = vcpu_regs(current); @@ -213,6 +214,13 @@ void leave_hypervisor_tail(struct pt_regs *regs) // v->arch.irq_new_pending = 1; // } + callback_irq = d->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ]; + if (callback_irq != 0 && local_events_need_delivery()) { + /*inject para-device call back irq*/ + v->vcpu_info->evtchn_upcall_mask = 1; + vmx_vcpu_pend_interrupt(v, callback_irq); + } + if ( v->arch.irq_new_pending ) { v->arch.irq_new_pending = 0; v->arch.irq_new_condition = 0; From 417209a93ebcacb37e049d580779cbfd937c4349 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Tue, 22 Aug 2006 14:44:13 -0600 Subject: [PATCH 20/58] [IA64] Add stubs to Linux/IPF for the new hvm_op hypercall. Signed-off-by: Tsunehisa Doi Signed-off-by: Tomonari Horikoshi --- linux-2.6-xen-sparse/include/asm-ia64/hypercall.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h index cc43e9bf15..b0daed8ee2 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h @@ -292,6 +292,13 @@ HYPERVISOR_vcpu_op( extern int HYPERVISOR_suspend(unsigned long srec); +static inline unsigned long +HYPERVISOR_hvm_op( + int cmd, void *arg) +{ + return _hypercall2(unsigned long, hvm_op, cmd, arg); +} + static inline int HYPERVISOR_callback_op( int cmd, void *arg) From 4ff30e11b25d8e526a2b79382e778b671c6f33cc Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Tue, 22 Aug 2006 14:45:49 -0600 Subject: [PATCH 21/58] [IA64] Remove PIN processing for Domain-0 vcpu0 This patch removes PIN processing for Domain-0 vcpu0 executed at the time of Xen initialization. Signed-off-by: Masaki Kanno --- xen/arch/ia64/xen/xensetup.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/xen/arch/ia64/xen/xensetup.c b/xen/arch/ia64/xen/xensetup.c index c9830575bf..05e8b8dc57 100644 --- a/xen/arch/ia64/xen/xensetup.c +++ b/xen/arch/ia64/xen/xensetup.c @@ -516,9 +516,6 @@ printk("num_online_cpus=%d, max_cpus=%d\n",num_online_cpus(),max_cpus); 0) != 0) panic("Could not set up DOM0 guest OS\n"); - /* PIN domain0 on CPU 0. */ - dom0->vcpu[0]->cpu_affinity = cpumask_of_cpu(0); - if (!running_on_sim) // slow on ski and pages are pre-initialized to zero scrub_heap_pages(); From 760268640cd778988ff1072e1b034691f734862f Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Wed, 23 Aug 2006 11:14:52 -0600 Subject: [PATCH 22/58] [IA64] only setup extra vga console support on dom0 Signed-off-by: Alex Williamson --- linux-2.6-xen-sparse/arch/ia64/dig/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-2.6-xen-sparse/arch/ia64/dig/setup.c b/linux-2.6-xen-sparse/arch/ia64/dig/setup.c index ebe45c7950..90d6ab64fa 100644 --- a/linux-2.6-xen-sparse/arch/ia64/dig/setup.c +++ b/linux-2.6-xen-sparse/arch/ia64/dig/setup.c @@ -69,7 +69,7 @@ dig_setup (char **cmdline_p) screen_info.orig_video_isVGA = 1; /* XXX fake */ screen_info.orig_video_ega_bx = 3; /* XXX fake */ #ifdef CONFIG_XEN - if (!is_running_on_xen()) + if (!is_running_on_xen() || !is_initial_xendomain()) return; if (xen_start_info->console.dom0.info_size >= From 3edc42f9210d4d7a9640370aa1c88a8a3e4ee272 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Wed, 23 Aug 2006 11:15:29 -0600 Subject: [PATCH 23/58] [IA64] split parts of page.h into maddr.h ia64 support for xen-unstable.hg cset 11081:9c953e1b6fad Signed-off-by: Alex Williamson --- linux-2.6-xen-sparse/include/asm-ia64/maddr.h | 81 +++++++++++++++++++ linux-2.6-xen-sparse/include/asm-ia64/page.h | 66 +-------------- 2 files changed, 82 insertions(+), 65 deletions(-) create mode 100644 linux-2.6-xen-sparse/include/asm-ia64/maddr.h diff --git a/linux-2.6-xen-sparse/include/asm-ia64/maddr.h b/linux-2.6-xen-sparse/include/asm-ia64/maddr.h new file mode 100644 index 0000000000..dbff05b338 --- /dev/null +++ b/linux-2.6-xen-sparse/include/asm-ia64/maddr.h @@ -0,0 +1,81 @@ +#ifndef _ASM_IA64_MADDR_H +#define _ASM_IA64_MADDR_H + +#ifndef __ASSEMBLY__ +#ifdef CONFIG_XEN + +#define INVALID_P2M_ENTRY (~0UL) + +#include +#include +#include // to compile netback, netfront +typedef unsigned long maddr_t; // to compile netback, netfront + + +/* XXX xen page size != page size */ + +static inline unsigned long +pfn_to_mfn_for_dma(unsigned long pfn) +{ + unsigned long mfn; + mfn = HYPERVISOR_phystomach(pfn); + BUG_ON(mfn == 0); // XXX + BUG_ON(mfn == INVALID_P2M_ENTRY); // XXX + BUG_ON(mfn == INVALID_MFN); + return mfn; +} + +static inline unsigned long +phys_to_machine_for_dma(unsigned long phys) +{ + unsigned long machine = + pfn_to_mfn_for_dma(phys >> PAGE_SHIFT) << PAGE_SHIFT; + machine |= (phys & ~PAGE_MASK); + return machine; +} + +static inline unsigned long +mfn_to_pfn_for_dma(unsigned long mfn) +{ + unsigned long pfn; + pfn = HYPERVISOR_machtophys(mfn); + BUG_ON(pfn == 0); + //BUG_ON(pfn == INVALID_M2P_ENTRY); + return pfn; +} + +static inline unsigned long +machine_to_phys_for_dma(unsigned long machine) +{ + unsigned long phys = + mfn_to_pfn_for_dma(machine >> PAGE_SHIFT) << PAGE_SHIFT; + phys |= (machine & ~PAGE_MASK); + return phys; +} + +#define set_phys_to_machine(pfn, mfn) do { } while (0) +#define xen_machphys_update(mfn, pfn) do { } while (0) + +/* XXX to compile set_phys_to_machine(vaddr, FOREIGN_FRAME(m)) */ +#define FOREIGN_FRAME(m) (INVALID_P2M_ENTRY) + +#define mfn_to_pfn(mfn) (mfn) +#define mfn_to_virt(mfn) (__va((mfn) << PAGE_SHIFT)) +#define pfn_to_mfn(pfn) (pfn) +#define virt_to_mfn(virt) (__pa(virt) >> PAGE_SHIFT) +#define virt_to_machine(virt) __pa(virt) // for tpmfront.c + +static inline unsigned long +mfn_to_local_pfn(unsigned long mfn) +{ + extern unsigned long max_mapnr; + unsigned long pfn = mfn_to_pfn_for_dma(mfn); + if (!pfn_valid(pfn)) + return INVALID_P2M_ENTRY; + return pfn; +} + +#endif /* CONFIG_XEN */ +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_IA64_MADDR_H */ diff --git a/linux-2.6-xen-sparse/include/asm-ia64/page.h b/linux-2.6-xen-sparse/include/asm-ia64/page.h index 67312ea310..fca73f00ef 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/page.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/page.h @@ -224,12 +224,9 @@ get_order (unsigned long size) #ifndef __ASSEMBLY__ #ifdef CONFIG_XEN -#define INVALID_P2M_ENTRY (~0UL) - #include #include #include // to compile netback, netfront -typedef unsigned long maddr_t; // to compile netback, netfront /* * XXX hack! @@ -268,68 +265,7 @@ extern struct address_space xen_ia64_foreign_dummy_mapping; }) #define HAVE_ARCH_FREE_PAGE -/* XXX xen page size != page size */ - -static inline unsigned long -pfn_to_mfn_for_dma(unsigned long pfn) -{ - unsigned long mfn; - mfn = HYPERVISOR_phystomach(pfn); - BUG_ON(mfn == 0); // XXX - BUG_ON(mfn == INVALID_P2M_ENTRY); // XXX - BUG_ON(mfn == INVALID_MFN); - return mfn; -} - -static inline unsigned long -phys_to_machine_for_dma(unsigned long phys) -{ - unsigned long machine = - pfn_to_mfn_for_dma(phys >> PAGE_SHIFT) << PAGE_SHIFT; - machine |= (phys & ~PAGE_MASK); - return machine; -} - -static inline unsigned long -mfn_to_pfn_for_dma(unsigned long mfn) -{ - unsigned long pfn; - pfn = HYPERVISOR_machtophys(mfn); - BUG_ON(pfn == 0); - //BUG_ON(pfn == INVALID_M2P_ENTRY); - return pfn; -} - -static inline unsigned long -machine_to_phys_for_dma(unsigned long machine) -{ - unsigned long phys = - mfn_to_pfn_for_dma(machine >> PAGE_SHIFT) << PAGE_SHIFT; - phys |= (machine & ~PAGE_MASK); - return phys; -} - -#define set_phys_to_machine(pfn, mfn) do { } while (0) -#define xen_machphys_update(mfn, pfn) do { } while (0) - -/* XXX to compile set_phys_to_machine(vaddr, FOREIGN_FRAME(m)) */ -#define FOREIGN_FRAME(m) (INVALID_P2M_ENTRY) - -#define mfn_to_pfn(mfn) (mfn) -#define mfn_to_virt(mfn) (__va((mfn) << PAGE_SHIFT)) -#define pfn_to_mfn(pfn) (pfn) -#define virt_to_mfn(virt) (__pa(virt) >> PAGE_SHIFT) -#define virt_to_machine(virt) __pa(virt) // for tpmfront.c - -static inline unsigned long -mfn_to_local_pfn(unsigned long mfn) -{ - extern unsigned long max_mapnr; - unsigned long pfn = mfn_to_pfn_for_dma(mfn); - if (!pfn_valid(pfn)) - return INVALID_P2M_ENTRY; - return pfn; -} +#include #endif /* CONFIG_XEN */ #endif /* __ASSEMBLY__ */ From 05b473fc64d4efd393b4b1b126e13fa5eebab5b0 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Wed, 23 Aug 2006 11:16:11 -0600 Subject: [PATCH 24/58] [IA64] replace gnttab_log_dirty with gnttab_mark_dirty Signed-off-by: Alex Williamson --- xen/include/asm-ia64/grant_table.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xen/include/asm-ia64/grant_table.h b/xen/include/asm-ia64/grant_table.h index 5e6b1cff22..442e4fa4e1 100644 --- a/xen/include/asm-ia64/grant_table.h +++ b/xen/include/asm-ia64/grant_table.h @@ -35,7 +35,7 @@ void guest_physmap_add_page(struct domain *d, unsigned long gpfn, unsigned long gnttab_shared_maddr((d), (t), (i))); \ (IA64_GRANT_TABLE_PADDR >> PAGE_SHIFT) + (i);}) -#define gnttab_log_dirty(d, f) ((void)0) +#define gnttab_mark_dirty(d, f) ((void)0) static inline void gnttab_clear_flag(unsigned long nr, uint16_t *addr) { From 0c6850e9657445e9fbac91d292c8680206d79f0d Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Wed, 23 Aug 2006 11:16:26 -0600 Subject: [PATCH 25/58] [IA64] update xc_shadow_control call with new parameters Signed-off-by: Alex Williamson --- tools/libxc/ia64/xc_ia64_linux_save.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/libxc/ia64/xc_ia64_linux_save.c b/tools/libxc/ia64/xc_ia64_linux_save.c index 72183f1383..4490aa90b7 100644 --- a/tools/libxc/ia64/xc_ia64_linux_save.c +++ b/tools/libxc/ia64/xc_ia64_linux_save.c @@ -79,7 +79,7 @@ static int xc_ia64_shadow_control(int xc_handle, } return xc_shadow_control(xc_handle, domid, sop, - dirty_bitmap, pages, stats); + dirty_bitmap, pages, NULL, 0, stats); } static inline ssize_t From dbd913c110343f077292659b25de4922549115f3 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Wed, 23 Aug 2006 11:16:41 -0600 Subject: [PATCH 26/58] [IA64] DOM0_SHADOW_CONTROL_OP_GET/SET_ALLOCATION stubs Signed-off-by: Alex Williamson --- xen/arch/ia64/xen/domain.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index 7b43dfd4c7..889d5eccb8 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -727,6 +727,15 @@ int shadow_mode_control(struct domain *d, dom0_shadow_control_t *sc) } break; } + case DOM0_SHADOW_CONTROL_OP_GET_ALLOCATION: + sc->mb = 0; + break; + case DOM0_SHADOW_CONTROL_OP_SET_ALLOCATION: + if (sc->mb > 0) { + BUG(); + rc = -ENOMEM; + } + break; default: rc = -EINVAL; break; From 0bbee1ed751608f2be6b2f71c59cffad226f61e1 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Wed, 23 Aug 2006 12:56:10 -0600 Subject: [PATCH 27/58] [IA64] PV-to-HVM prep for maddr.h Signed-off-by: Tsunehisa Doi Signed-off-by: Tomonari Horikoshi [merged with existing maddr.h] Signed-off-by: Alex Williamson --- linux-2.6-xen-sparse/include/asm-ia64/maddr.h | 51 +++++++++++-------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/linux-2.6-xen-sparse/include/asm-ia64/maddr.h b/linux-2.6-xen-sparse/include/asm-ia64/maddr.h index dbff05b338..d80345b9b9 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/maddr.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/maddr.h @@ -1,19 +1,16 @@ #ifndef _ASM_IA64_MADDR_H #define _ASM_IA64_MADDR_H -#ifndef __ASSEMBLY__ -#ifdef CONFIG_XEN - -#define INVALID_P2M_ENTRY (~0UL) - #include #include -#include // to compile netback, netfront -typedef unsigned long maddr_t; // to compile netback, netfront +#include +#include +#ifdef CONFIG_XEN + +#define INVALID_P2M_ENTRY (~0UL) /* XXX xen page size != page size */ - static inline unsigned long pfn_to_mfn_for_dma(unsigned long pfn) { @@ -53,18 +50,6 @@ machine_to_phys_for_dma(unsigned long machine) return phys; } -#define set_phys_to_machine(pfn, mfn) do { } while (0) -#define xen_machphys_update(mfn, pfn) do { } while (0) - -/* XXX to compile set_phys_to_machine(vaddr, FOREIGN_FRAME(m)) */ -#define FOREIGN_FRAME(m) (INVALID_P2M_ENTRY) - -#define mfn_to_pfn(mfn) (mfn) -#define mfn_to_virt(mfn) (__va((mfn) << PAGE_SHIFT)) -#define pfn_to_mfn(pfn) (pfn) -#define virt_to_mfn(virt) (__pa(virt) >> PAGE_SHIFT) -#define virt_to_machine(virt) __pa(virt) // for tpmfront.c - static inline unsigned long mfn_to_local_pfn(unsigned long mfn) { @@ -75,7 +60,29 @@ mfn_to_local_pfn(unsigned long mfn) return pfn; } -#endif /* CONFIG_XEN */ -#endif /* __ASSEMBLY__ */ +#else /* !CONFIG_XEN */ + +#define pfn_to_mfn_for_dma(pfn) (pfn) +#define mfn_to_pfn_for_dma(mfn) (mfn) +#define phys_to_machine_for_dma(phys) (phys) +#define machine_to_phys_for_dma(machine) (machine) +#define mfn_to_local_pfn(mfn) (mfn) + +#endif /* !CONFIG_XEN */ + +/* XXX to compile set_phys_to_machine(vaddr, FOREIGN_FRAME(m)) */ +#define FOREIGN_FRAME(m) (INVALID_P2M_ENTRY) + +#define mfn_to_pfn(mfn) (mfn) +#define pfn_to_mfn(pfn) (pfn) + +#define mfn_to_virt(mfn) (__va((mfn) << PAGE_SHIFT)) +#define virt_to_mfn(virt) (__pa(virt) >> PAGE_SHIFT) +#define virt_to_machine(virt) __pa(virt) // for tpmfront.c + +#define set_phys_to_machine(pfn, mfn) do { } while (0) +#define xen_machphys_update(mfn, pfn) do { } while (0) + +typedef unsigned long maddr_t; // to compile netback, netfront #endif /* _ASM_IA64_MADDR_H */ From 69a6495152d483dc2bbe004af57914e5a7e63fcf Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Wed, 23 Aug 2006 13:13:51 -0600 Subject: [PATCH 28/58] [IA64] catch up `new Xen event channels' DM over to using the new Xen event channels for IPF Signed-off-by: Tsunehisa Doi Signed-off-by: Tomonari Horikoshi --- xen/arch/ia64/vmx/mmio.c | 13 ++-- xen/arch/ia64/vmx/vmx_init.c | 44 ++++++++--- xen/arch/ia64/vmx/vmx_support.c | 132 +++++++++++++++----------------- xen/arch/ia64/xen/domain.c | 3 + xen/include/asm-ia64/vmx.h | 7 +- xen/include/asm-ia64/vmx_vpd.h | 3 +- 6 files changed, 106 insertions(+), 96 deletions(-) diff --git a/xen/arch/ia64/vmx/mmio.c b/xen/arch/ia64/vmx/mmio.c index ed635a478b..36cee507ec 100644 --- a/xen/arch/ia64/vmx/mmio.c +++ b/xen/arch/ia64/vmx/mmio.c @@ -155,10 +155,9 @@ static void low_mmio_access(VCPU *vcpu, u64 pa, u64 *val, size_t s, int dir) p->type = 1; p->df = 0; - set_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags); - p->state = STATE_IOREQ_READY; - evtchn_send(iopacket_port(v)); - vmx_wait_io(); + p->io_count++; + + vmx_send_assist_req(v); if(dir==IOREQ_READ){ //read *val=p->u.data; } @@ -187,11 +186,9 @@ static void legacy_io_access(VCPU *vcpu, u64 pa, u64 *val, size_t s, int dir) p->type = 0; p->df = 0; - set_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags); - p->state = STATE_IOREQ_READY; - evtchn_send(iopacket_port(v)); + p->io_count++; - vmx_wait_io(); + vmx_send_assist_req(v); if(dir==IOREQ_READ){ //read *val=p->u.data; } diff --git a/xen/arch/ia64/vmx/vmx_init.c b/xen/arch/ia64/vmx/vmx_init.c index cb0d24045f..bf85b7df0c 100644 --- a/xen/arch/ia64/vmx/vmx_init.c +++ b/xen/arch/ia64/vmx/vmx_init.c @@ -206,7 +206,7 @@ vmx_create_vp(struct vcpu *v) u64 ret; vpd_t *vpd = (vpd_t *)v->arch.privregs; u64 ivt_base; - extern char vmx_ia64_ivt; + extern char vmx_ia64_ivt; /* ia64_ivt is function pointer, so need this tranlation */ ivt_base = (u64) &vmx_ia64_ivt; printk("ivt_base: 0x%lx\n", ivt_base); @@ -265,6 +265,29 @@ vmx_load_state(struct vcpu *v) * anchored in vcpu */ } +static void vmx_create_event_channels(struct vcpu *v) +{ + vcpu_iodata_t *p; + struct vcpu *o; + + if (v->vcpu_id == 0) { + /* Ugly: create event channels for every vcpu when vcpu 0 + starts, so that they're available for ioemu to bind to. */ + for_each_vcpu(v->domain, o) { + p = get_vio(v->domain, o->vcpu_id); + o->arch.arch_vmx.xen_port = p->vp_eport = + alloc_unbound_xen_event_channel(o, 0); + DPRINTK("Allocated port %d for hvm.\n", + o->arch.arch_vmx.xen_port); + } + } +} + +static void vmx_release_assist_channel(struct vcpu *v) +{ + free_xen_event_channel(v, v->arch.arch_vmx.xen_port); +} + /* * Initialize VMX envirenment for guest. Only the 1st vp/vcpu * is registered here. @@ -286,6 +309,8 @@ vmx_final_setup_guest(struct vcpu *v) #ifndef HASH_VHPT init_domain_tlb(v); #endif + vmx_create_event_channels(v); + /* v->arch.schedule_tail = arch_vmx_do_launch; */ vmx_create_vp(v); @@ -303,6 +328,15 @@ vmx_final_setup_guest(struct vcpu *v) set_bit(ARCH_VMX_DOMAIN, &v->arch.arch_vmx.flags); } +void +vmx_relinquish_guest_resources(struct domain *d) +{ + struct vcpu *v; + + for_each_vcpu(d, v) + vmx_release_assist_channel(v); +} + void vmx_relinquish_vcpu_resources(struct vcpu *v) { @@ -420,13 +454,5 @@ void vmx_setup_platform(struct domain *d) void vmx_do_launch(struct vcpu *v) { - if (evtchn_bind_vcpu(iopacket_port(v), v->vcpu_id) < 0) { - printk("VMX domain bind port %d to vcpu %d failed!\n", - iopacket_port(v), v->vcpu_id); - domain_crash_synchronous(); - } - - clear_bit(iopacket_port(v), &v->domain->shared_info->evtchn_mask[0]); - vmx_load_all_rr(v); } diff --git a/xen/arch/ia64/vmx/vmx_support.c b/xen/arch/ia64/vmx/vmx_support.c index 602f077874..3f8c4bcf0c 100644 --- a/xen/arch/ia64/vmx/vmx_support.c +++ b/xen/arch/ia64/vmx/vmx_support.c @@ -1,4 +1,3 @@ - /* -*- Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */ /* * vmx_support.c: vmx specific support interface. @@ -22,46 +21,12 @@ #include #include #include +#include #include #include #include #include -/* - * I/O emulation should be atomic from domain point of view. However, - * when emulation code is waiting for I/O completion by blocking, - * other events like DM interrupt, VBD, etc. may come and unblock - * current exection flow. So we have to prepare for re-block if unblocked - * by non I/O completion event. After io emulation is done, re-enable - * pending indicaion if other ports are pending - */ -void vmx_wait_io(void) -{ - struct vcpu *v = current; - struct domain *d = v->domain; - int port = iopacket_port(v); - - for (;;) { - if (test_and_clear_bit(0, &v->vcpu_info->evtchn_upcall_pending) && - test_and_clear_bit(port / BITS_PER_LONG, - &v->vcpu_info->evtchn_pending_sel) && - test_and_clear_bit(port, &d->shared_info->evtchn_pending[0])) - vmx_io_assist(v); - - if (!test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) - break; - - do_sched_op_compat(SCHEDOP_block, 0); - } - - /* re-enable indication if other pending events */ - if (d->shared_info->evtchn_pending[port / BITS_PER_LONG]) - set_bit(port / BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel); - - if (v->vcpu_info->evtchn_pending_sel) - set_bit(0, &v->vcpu_info->evtchn_upcall_pending); -} - /* * Only place to call vmx_io_assist is mmio/legacy_io emulation. * Since I/O emulation is synchronous, it shouldn't be called in @@ -83,17 +48,15 @@ void vmx_io_assist(struct vcpu *v) p = &vio->vp_ioreq; - if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) { - if (p->state != STATE_IORESP_READY) { - /* Can't block here, for the same reason as other places to - * use vmx_wait_io. Simple return is safe since vmx_wait_io will - * try to block again - */ - return; - } else - p->state = STATE_INVALID; - - clear_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags); + if (p->state == STATE_IORESP_READY) { + p->state = STATE_INVALID; + } + else { + /* Can't block here, for the same reason as other places to + * use vmx_wait_io. Simple return is safe since vmx_wait_io will + * try to block again + */ + return; } } @@ -108,31 +71,6 @@ void vmx_io_assist(struct vcpu *v) */ void vmx_intr_assist(struct vcpu *v) { - vcpu_iodata_t *vio; - struct domain *d = v->domain; - extern void vmx_vcpu_pend_batch_interrupt(VCPU *vcpu, - unsigned long *pend_irr); - int port = iopacket_port(v); - - if (test_bit(port, &d->shared_info->evtchn_pending[0]) || - test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) - vmx_wait_io(); - - /* I/O emulation is atomic, so it's impossible to see execution flow - * out of vmx_wait_io, when guest is still waiting for response. - */ - if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) - panic_domain(vcpu_regs(v),"!!!Bad resume to guest before I/O emulation is done.\n"); - - /* Even without event pending, we still need to sync pending bits - * between DM and vlsapic. The reason is that interrupt delivery - * shares same event channel as I/O emulation, with corresponding - * indicator possibly cleared when vmx_wait_io(). - */ - vio = get_vio(v->domain, v->vcpu_id); - if (!vio) - panic_domain(vcpu_regs(v),"Corruption: bad shared page: %lx\n", (unsigned long)vio); - #ifdef V_IOSAPIC_READY /* Confirm virtual interrupt line signals, and set pending bits in vpd */ if(v->vcpu_id==0) @@ -140,3 +78,53 @@ void vmx_intr_assist(struct vcpu *v) #endif return; } + +void vmx_send_assist_req(struct vcpu *v) +{ + ioreq_t *p; + + p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq; + if (unlikely(p->state != STATE_INVALID)) { + /* This indicates a bug in the device model. Crash the + domain. */ + printk("Device model set bad IO state %d.\n", p->state); + domain_crash(v->domain); + return; + } + wmb(); + p->state = STATE_IOREQ_READY; + notify_via_xen_event_channel(v->arch.arch_vmx.xen_port); + + /* + * Waiting for MMIO completion + * like the wait_on_xen_event_channel() macro like... + * but, we can't call do_softirq() at this point.. + */ + for (;;) { + if (p->state != STATE_IOREQ_READY && + p->state != STATE_IOREQ_INPROCESS) + break; + + set_bit(_VCPUF_blocked_in_xen, ¤t->vcpu_flags); + mb(); /* set blocked status /then/ re-evaluate condition */ + if (p->state != STATE_IOREQ_READY && + p->state != STATE_IOREQ_INPROCESS) + { + clear_bit(_VCPUF_blocked_in_xen, ¤t->vcpu_flags); + break; + } + + /* I want to call __enter_scheduler() only */ + do_sched_op_compat(SCHEDOP_yield, 0); + mb(); + } + + /* the code under this line is completer phase... */ + vmx_io_assist(v); +} + +/* Wake up a vcpu whihc is waiting for interrupts to come in */ +void vmx_prod_vcpu(struct vcpu *v) +{ + vcpu_unblock(v); +} diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index 889d5eccb8..2130361cc3 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -543,6 +543,9 @@ void domain_relinquish_resources(struct domain *d) // relase page traversing d->arch.mm. relinquish_mm(d); + if (d->vcpu[0] && VMX_DOMAIN(d->vcpu[0])) + vmx_relinquish_guest_resources(d); + relinquish_memory(d, &d->xenpage_list); relinquish_memory(d, &d->page_list); diff --git a/xen/include/asm-ia64/vmx.h b/xen/include/asm-ia64/vmx.h index 043903d368..f2e6de5cea 100644 --- a/xen/include/asm-ia64/vmx.h +++ b/xen/include/asm-ia64/vmx.h @@ -35,7 +35,6 @@ extern void vmx_final_setup_guest(struct vcpu *v); extern void vmx_save_state(struct vcpu *v); extern void vmx_load_state(struct vcpu *v); extern void vmx_setup_platform(struct domain *d); -extern void vmx_wait_io(void); extern void vmx_io_assist(struct vcpu *v); extern int ia64_hypercall (struct pt_regs *regs); extern void vmx_save_state(struct vcpu *v); @@ -53,6 +52,7 @@ extern void inject_guest_interruption(struct vcpu *vcpu, u64 vec); extern void vmx_intr_assist(struct vcpu *v); extern void set_illegal_op_isr (struct vcpu *vcpu); extern void illegal_op (struct vcpu *vcpu); +extern void vmx_relinquish_guest_resources(struct domain *d); extern void vmx_relinquish_vcpu_resources(struct vcpu *v); extern void vmx_die_if_kernel(char *str, struct pt_regs *regs, long err); @@ -61,11 +61,6 @@ static inline vcpu_iodata_t *get_vio(struct domain *d, unsigned long cpu) return &((shared_iopage_t *)d->arch.vmx_platform.shared_page_va)->vcpu_iodata[cpu]; } -static inline int iopacket_port(struct vcpu *v) -{ - return get_vio(v->domain, v->vcpu_id)->vp_eport; -} - static inline shared_iopage_t *get_sp(struct domain *d) { return (shared_iopage_t *)d->arch.vmx_platform.shared_page_va; diff --git a/xen/include/asm-ia64/vmx_vpd.h b/xen/include/asm-ia64/vmx_vpd.h index eea27d8bf3..82363a2876 100644 --- a/xen/include/asm-ia64/vmx_vpd.h +++ b/xen/include/asm-ia64/vmx_vpd.h @@ -96,7 +96,8 @@ struct arch_vmx_struct { // unsigned long rfi_ipsr; // unsigned long rfi_ifs; // unsigned long in_service[4]; // vLsapic inservice IRQ bits - unsigned long flags; + unsigned long flags; + unsigned long xen_port; #ifdef VTI_DEBUG unsigned long ivt_current; struct ivt_debug ivt_debug[IVT_DEBUG_MAX]; From 5f065ba906cf174459f50c647ff810f866144243 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Wed, 23 Aug 2006 13:21:02 -0600 Subject: [PATCH 29/58] [IA64] Modify xc_ia64_hvm_build for using the new Xen event channels Signed-off-by: Tsunehisa Doi Signed-off-by: Tomonari Horikoshi --- tools/libxc/ia64/xc_ia64_hvm_build.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/tools/libxc/ia64/xc_ia64_hvm_build.c b/tools/libxc/ia64/xc_ia64_hvm_build.c index ededfe6e5d..ce90475007 100644 --- a/tools/libxc/ia64/xc_ia64_hvm_build.c +++ b/tools/libxc/ia64/xc_ia64_hvm_build.c @@ -553,7 +553,6 @@ setup_guest(int xc_handle, uint32_t dom, unsigned long memsize, { unsigned long page_array[2]; shared_iopage_t *sp; - int i; unsigned long dom_memsize = (memsize << 20); DECLARE_DOM0_OP; @@ -605,18 +604,6 @@ setup_guest(int xc_handle, uint32_t dom, unsigned long memsize, goto error_out; memset(sp, 0, PAGE_SIZE); - - for (i = 0; i < vcpus; i++) { - uint32_t vp_eport; - - vp_eport = xc_evtchn_alloc_unbound(xc_handle, dom, 0); - if (vp_eport < 0) { - DPRINTF("Couldn't get unbound port from VMX guest.\n"); - goto error_out; - } - sp->vcpu_iodata[i].vp_eport = vp_eport; - } - munmap(sp, PAGE_SIZE); return 0; From ed46a80ff6feee3f94f73b7c64bd80e678b24ddc Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Wed, 23 Aug 2006 13:26:46 -0600 Subject: [PATCH 30/58] [IA64] Remove extraneous verbose output to clean up Fedora boot. Signed-off-by: Aron Griffis --- xen/arch/ia64/xen/mm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xen/arch/ia64/xen/mm.c b/xen/arch/ia64/xen/mm.c index 0f7a46148e..326e66c8a3 100644 --- a/xen/arch/ia64/xen/mm.c +++ b/xen/arch/ia64/xen/mm.c @@ -949,8 +949,6 @@ efi_mmio(unsigned long physaddr, unsigned long size) return 1; } - DPRINTK("%s:%d physaddr 0x%lx size = 0x%lx\n", - __func__, __LINE__, physaddr, size); return 0; } @@ -971,8 +969,10 @@ assign_domain_mmio_page(struct domain *d, __func__, d, mpaddr, size); } if (!efi_mmio(mpaddr, size)) { +#ifndef NDEBUG DPRINTK("%s:%d domain %p mpaddr 0x%lx size = 0x%lx\n", __func__, __LINE__, d, mpaddr, size); +#endif return -EINVAL; } assign_domain_same_page(d, mpaddr, size, ASSIGN_writable | ASSIGN_nocache); From e8da83b47d509edd4c6760aa8b390e3951bfa05a Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Thu, 24 Aug 2006 11:32:55 -0600 Subject: [PATCH 31/58] [IA64] VTLB optimization: Reuse invalid entry When inserting entry to vtlb or vhpt, reuse invalid entry. Signed-off-by: Isaku Yamahata Signed-off-by: Anthony Xu --- xen/arch/ia64/vmx/vtlb.c | 48 ++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/xen/arch/ia64/vmx/vtlb.c b/xen/arch/ia64/vmx/vtlb.c index bc6fe21d8f..4fb31a0ec2 100644 --- a/xen/arch/ia64/vmx/vtlb.c +++ b/xen/arch/ia64/vmx/vtlb.c @@ -148,13 +148,17 @@ static void vmx_vhpt_insert(thash_cb_t *hcb, u64 pte, u64 itir, u64 ifa) rr.rrval = ia64_get_rr(ifa); head = (thash_data_t *)ia64_thash(ifa); tag = ia64_ttag(ifa); - if( INVALID_VHPT(head) ) { - len = head->len; - head->page_flags = pte; - head->len = len; - head->itir = rr.ps << 2; - head->etag = tag; - return; + cch = head; + while (cch) { + if (INVALID_VHPT(cch)) { + len = cch->len; + cch->page_flags = pte; + cch->len = len; + cch->itir = rr.ps << 2; + cch->etag = tag; + return; + } + cch = cch->next; } if(head->len>=MAX_CCN_DEPTH){ @@ -358,24 +362,20 @@ void vtlb_insert(VCPU *v, u64 pte, u64 itir, u64 va) u64 tag, len; thash_cb_t *hcb = &v->arch.vtlb; vcpu_get_rr(v, va, &vrr.rrval); -#ifdef VTLB_DEBUG - if (vrr.ps != itir_ps(itir)) { -// machine_tlb_insert(hcb->vcpu, entry); - panic_domain(NULL, "not preferred ps with va: 0x%lx vrr.ps=%d ps=%ld\n", - va, vrr.ps, itir_ps(itir)); - return; - } -#endif vrr.ps = itir_ps(itir); VMX(v, psbits[va >> 61]) |= (1UL << vrr.ps); hash_table = vsa_thash(hcb->pta, va, vrr.rrval, &tag); - if( INVALID_TLB(hash_table) ) { - len = hash_table->len; - hash_table->page_flags = pte; - hash_table->len = len; - hash_table->itir=itir; - hash_table->etag=tag; - return; + cch = hash_table; + while (cch) { + if (INVALID_TLB(cch)) { + len = cch->len; + cch->page_flags = pte; + cch->len = len; + cch->itir=itir; + cch->etag=tag; + return; + } + cch = cch->next; } if (hash_table->len>=MAX_CCN_DEPTH){ thash_recycle_cch(hcb, hash_table); @@ -469,10 +469,6 @@ void thash_purge_and_insert(VCPU *v, u64 pte, u64 itir, u64 ifa, int type) ps = itir_ps(itir); vcpu_get_rr(current, ifa, &vrr.rrval); mrr.rrval = ia64_get_rr(ifa); -// if (vrr.ps != itir_ps(itir)) { -// printf("not preferred ps with va: 0x%lx vrr.ps=%d ps=%ld\n", -// ifa, vrr.ps, itir_ps(itir)); -// } if(VMX_DOMAIN(v)){ /* Ensure WB attribute if pte is related to a normal mem page, * which is required by vga acceleration since qemu maps shared From 26cb12a5135d366f777c04cf82ec97db35960200 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Thu, 24 Aug 2006 11:42:24 -0600 Subject: [PATCH 32/58] [IA64] Clean up: change asm constraints and remove _hypercall_imm* Signed-off-by: Tristan Gingold --- .../include/asm-ia64/hypercall.h | 149 ++++-------------- 1 file changed, 31 insertions(+), 118 deletions(-) diff --git a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h index b0daed8ee2..7d354f9f9c 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h @@ -51,7 +51,7 @@ "break 0x1000 ;;\n" \ "mov %0=r8 ;;\n" \ : "=r" (__res) \ - : "i" (__HYPERVISOR_##name) \ + : "J" (__HYPERVISOR_##name) \ : "r2","r8", \ "memory" ); \ (type)__res; \ @@ -66,8 +66,8 @@ "break 0x1000 ;;\n" \ "mov %0=r8 ;;\n" \ : "=r" (__res) \ - : "i" (__HYPERVISOR_##name), \ - "r" ((unsigned long)(a1)) \ + : "J" (__HYPERVISOR_##name), \ + "rI" ((unsigned long)(a1)) \ : "r14","r2","r8", \ "memory" ); \ (type)__res; \ @@ -83,9 +83,9 @@ "break 0x1000 ;;\n" \ "mov %0=r8 ;;\n" \ : "=r" (__res) \ - : "i" (__HYPERVISOR_##name), \ - "r" ((unsigned long)(a1)), \ - "r" ((unsigned long)(a2)) \ + : "J" (__HYPERVISOR_##name), \ + "rI" ((unsigned long)(a1)), \ + "rI" ((unsigned long)(a2)) \ : "r14","r15","r2","r8", \ "memory" ); \ (type)__res; \ @@ -102,10 +102,10 @@ "break 0x1000 ;;\n" \ "mov %0=r8 ;;\n" \ : "=r" (__res) \ - : "i" (__HYPERVISOR_##name), \ - "r" ((unsigned long)(a1)), \ - "r" ((unsigned long)(a2)), \ - "r" ((unsigned long)(a3)) \ + : "J" (__HYPERVISOR_##name), \ + "rI" ((unsigned long)(a1)), \ + "rI" ((unsigned long)(a2)), \ + "rI" ((unsigned long)(a3)) \ : "r14","r15","r16","r2","r8", \ "memory" ); \ (type)__res; \ @@ -123,11 +123,11 @@ "break 0x1000 ;;\n" \ "mov %0=r8 ;;\n" \ : "=r" (__res) \ - : "i" (__HYPERVISOR_##name), \ - "r" ((unsigned long)(a1)), \ - "r" ((unsigned long)(a2)), \ - "r" ((unsigned long)(a3)), \ - "r" ((unsigned long)(a4)) \ + : "J" (__HYPERVISOR_##name), \ + "rI" ((unsigned long)(a1)), \ + "rI" ((unsigned long)(a2)), \ + "rI" ((unsigned long)(a3)), \ + "rI" ((unsigned long)(a4)) \ : "r14","r15","r16","r2","r8", \ "r17","memory" ); \ (type)__res; \ @@ -146,12 +146,12 @@ "break 0x1000 ;;\n" \ "mov %0=r8 ;;\n" \ : "=r" (__res) \ - : "i" (__HYPERVISOR_##name), \ - "r" ((unsigned long)(a1)), \ - "r" ((unsigned long)(a2)), \ - "r" ((unsigned long)(a3)), \ - "r" ((unsigned long)(a4)), \ - "r" ((unsigned long)(a5)) \ + : "J" (__HYPERVISOR_##name), \ + "rI" ((unsigned long)(a1)), \ + "rI" ((unsigned long)(a2)), \ + "rI" ((unsigned long)(a3)), \ + "rI" ((unsigned long)(a4)), \ + "rI" ((unsigned long)(a5)) \ : "r14","r15","r16","r2","r8", \ "r17","r18","memory" ); \ (type)__res; \ @@ -317,97 +317,11 @@ static inline void exit_idle(void) {} #include #include -#define _hypercall_imm1(type, name, imm, a1) \ -({ \ - long __res; \ - __asm__ __volatile__ (";;\n" \ - "mov r14=%2\n" \ - "mov r15=%3\n" \ - "mov r2=%1\n" \ - "break 0x1000 ;;\n" \ - "mov %0=r8 ;;\n" \ - : "=r" (__res) \ - : "i" (__HYPERVISOR_##name), \ - "i" (imm), \ - "r" ((unsigned long)(a1)) \ - : "r14","r15","r2","r8", \ - "memory" ); \ - (type)__res; \ -}) - -#define _hypercall_imm2(type, name, imm, a1, a2) \ -({ \ - long __res; \ - __asm__ __volatile__ (";;\n" \ - "mov r14=%2\n" \ - "mov r15=%3\n" \ - "mov r16=%4\n" \ - "mov r2=%1\n" \ - "break 0x1000 ;;\n" \ - "mov %0=r8 ;;\n" \ - : "=r" (__res) \ - : "i" (__HYPERVISOR_##name), \ - "i" (imm), \ - "r" ((unsigned long)(a1)), \ - "r" ((unsigned long)(a2)) \ - : "r14","r15","r16","r2","r8", \ - "memory" ); \ - (type)__res; \ -}) - -#define _hypercall_imm3(type, name, imm, a1, a2, a3) \ -({ \ - long __res; \ - __asm__ __volatile__ (";;\n" \ - "mov r14=%2\n" \ - "mov r15=%3\n" \ - "mov r16=%4\n" \ - "mov r17=%5\n" \ - "mov r2=%1\n" \ - "break 0x1000 ;;\n" \ - "mov %0=r8 ;;\n" \ - : "=r" (__res) \ - : "i" (__HYPERVISOR_##name), \ - "i" (imm), \ - "r" ((unsigned long)(a1)), \ - "r" ((unsigned long)(a2)), \ - "r" ((unsigned long)(a3)) \ - : "r14","r15","r16","r17", \ - "r2","r8", \ - "memory" ); \ - (type)__res; \ -}) - -#define _hypercall_imm4(type, name, imm, a1, a2, a3, a4) \ -({ \ - long __res; \ - __asm__ __volatile__ (";;\n" \ - "mov r14=%2\n" \ - "mov r15=%3\n" \ - "mov r16=%4\n" \ - "mov r17=%5\n" \ - "mov r18=%6\n" \ - "mov r2=%1\n" \ - "break 0x1000 ;;\n" \ - "mov %0=r8 ;;\n" \ - : "=r" (__res) \ - : "i" (__HYPERVISOR_##name), \ - "i" (imm), \ - "r" ((unsigned long)(a1)), \ - "r" ((unsigned long)(a2)), \ - "r" ((unsigned long)(a3)), \ - "r" ((unsigned long)(a4)) \ - : "r14","r15","r16","r17","r18", \ - "r2","r8", \ - "memory" ); \ - (type)__res; \ -}) - static inline unsigned long __HYPERVISOR_ioremap(unsigned long ioaddr, unsigned long size) { - return _hypercall_imm2(unsigned long, ia64_dom0vp_op, - IA64_DOM0VP_ioremap, ioaddr, size); + return _hypercall3(unsigned long, ia64_dom0vp_op, + IA64_DOM0VP_ioremap, ioaddr, size); } static inline unsigned long @@ -429,8 +343,8 @@ HYPERVISOR_ioremap(unsigned long ioaddr, unsigned long size) static inline unsigned long __HYPERVISOR_phystomach(unsigned long gpfn) { - return _hypercall_imm1(unsigned long, ia64_dom0vp_op, - IA64_DOM0VP_phystomach, gpfn); + return _hypercall2(unsigned long, ia64_dom0vp_op, + IA64_DOM0VP_phystomach, gpfn); } static inline unsigned long @@ -446,8 +360,8 @@ HYPERVISOR_phystomach(unsigned long gpfn) static inline unsigned long __HYPERVISOR_machtophys(unsigned long mfn) { - return _hypercall_imm1(unsigned long, ia64_dom0vp_op, - IA64_DOM0VP_machtophys, mfn); + return _hypercall2(unsigned long, ia64_dom0vp_op, + IA64_DOM0VP_machtophys, mfn); } static inline unsigned long @@ -463,8 +377,8 @@ HYPERVISOR_machtophys(unsigned long mfn) static inline unsigned long __HYPERVISOR_zap_physmap(unsigned long gpfn, unsigned int extent_order) { - return _hypercall_imm2(unsigned long, ia64_dom0vp_op, - IA64_DOM0VP_zap_physmap, gpfn, extent_order); + return _hypercall3(unsigned long, ia64_dom0vp_op, + IA64_DOM0VP_zap_physmap, gpfn, extent_order); } static inline unsigned long @@ -481,9 +395,8 @@ static inline unsigned long __HYPERVISOR_add_physmap(unsigned long gpfn, unsigned long mfn, unsigned long flags, domid_t domid) { - return _hypercall_imm4(unsigned long, ia64_dom0vp_op, - IA64_DOM0VP_add_physmap, gpfn, mfn, flags, - domid); + return _hypercall5(unsigned long, ia64_dom0vp_op, + IA64_DOM0VP_add_physmap, gpfn, mfn, flags, domid); } static inline unsigned long From 098a8c19d8b2177ebe14ac8a1f6f9de93b38f5aa Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Thu, 24 Aug 2006 11:48:35 -0600 Subject: [PATCH 33/58] [IA64] pal_halt_light emulatefor domU Signed-off-by: Atsushi SAKAI --- xen/arch/ia64/xen/domain.c | 10 ++++++++++ xen/arch/ia64/xen/hypercall.c | 7 ++++++- xen/include/asm-ia64/domain.h | 1 + xen/include/asm-ia64/vcpu.h | 17 +++++++++++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index 2130361cc3..6f2a503f96 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -239,6 +239,12 @@ void startup_cpu_idle_loop(void) # error "XMAPPEDREGS_SHIFT doesn't match sizeof(mapped_regs_t)." #endif +void hlt_timer_fn(void *data) +{ + struct vcpu *v = data; + vcpu_unblock(v); +} + struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id) { struct vcpu *v; @@ -298,6 +304,9 @@ struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id) v->arch.breakimm = d->arch.breakimm; v->arch.last_processor = INVALID_PROCESSOR; } + if (!VMX_DOMAIN(v)){ + init_timer(&v->arch.hlt_timer, hlt_timer_fn, v, v->processor); + } return v; } @@ -309,6 +318,7 @@ void relinquish_vcpu_resources(struct vcpu *v) get_order_from_shift(XMAPPEDREGS_SHIFT)); v->arch.privregs = NULL; } + kill_timer(&v->arch.hlt_timer); } void free_vcpu_struct(struct vcpu *v) diff --git a/xen/arch/ia64/xen/hypercall.c b/xen/arch/ia64/xen/hypercall.c index b5321e030c..203d0211c5 100644 --- a/xen/arch/ia64/xen/hypercall.c +++ b/xen/arch/ia64/xen/hypercall.c @@ -235,7 +235,12 @@ fw_hypercall (struct pt_regs *regs) } else { perfc_incrc(pal_halt_light); - do_sched_op_compat(SCHEDOP_yield, 0); + migrate_timer(&v->arch.hlt_timer, + v->processor); + set_timer(&v->arch.hlt_timer, + vcpu_get_next_timer_ns(v)); + do_sched_op_compat(SCHEDOP_block, 0); + stop_timer(&v->arch.hlt_timer); } regs->r8 = 0; regs->r9 = 0; diff --git a/xen/include/asm-ia64/domain.h b/xen/include/asm-ia64/domain.h index fed8c428e0..394b3bc6ad 100644 --- a/xen/include/asm-ia64/domain.h +++ b/xen/include/asm-ia64/domain.h @@ -198,6 +198,7 @@ struct arch_vcpu { unsigned long old_rsc; int mode_flags; fpswa_ret_t fpswa_ret; /* save return values of FPSWA emulation */ + struct timer hlt_timer; struct arch_vmx_struct arch_vmx; /* Virtual Machine Extensions */ #define INVALID_PROCESSOR INT_MAX diff --git a/xen/include/asm-ia64/vcpu.h b/xen/include/asm-ia64/vcpu.h index 87b3801b2f..7bfc76f761 100644 --- a/xen/include/asm-ia64/vcpu.h +++ b/xen/include/asm-ia64/vcpu.h @@ -4,6 +4,7 @@ // TODO: Many (or perhaps most) of these should eventually be // static inline functions +#include #include #include #include @@ -15,6 +16,7 @@ typedef int BOOLEAN; struct vcpu; typedef struct vcpu VCPU; typedef cpu_user_regs_t REGS; +extern u64 cycle_to_ns(u64 cycle); /* Note: PSCB stands for Privilegied State Communication Block. */ #define VCPU(_v,_x) (_v->arch.privregs->_x) @@ -183,6 +185,21 @@ itir_mask(UINT64 itir) return (~((1UL << itir_ps(itir)) - 1)); } +static inline s64 +vcpu_get_next_timer_ns(VCPU *vcpu) +{ + s64 vcpu_get_next_timer_ns; + u64 d = PSCBX(vcpu, domain_itm); + u64 now = ia64_get_itc(); + + if (d > now) + vcpu_get_next_timer_ns = cycle_to_ns(d - now) + NOW(); + else + vcpu_get_next_timer_ns = cycle_to_ns(local_cpu_data->itm_delta) + NOW(); + + return vcpu_get_next_timer_ns; +} + #define verbose(a...) do {if (vcpu_verbose) printf(a);} while(0) //#define vcpu_quick_region_check(_tr_regions,_ifa) 1 From 31a34181c72408640b1ea728f24c6f95b4cfd36f Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Thu, 24 Aug 2006 11:52:23 -0600 Subject: [PATCH 34/58] [IA64] All vcpus can sync interrupts from qemu Previously only vcpu0 can sync interrupt from qemu. Now all vcpus can sync. Signed-off-by: Anthony Xu --- xen/arch/ia64/vmx/vmx_init.c | 3 +++ xen/arch/ia64/vmx/vmx_support.c | 4 +++- xen/include/asm-ia64/domain.h | 2 ++ xen/include/asm-ia64/vmx_vpd.h | 6 ++++++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/xen/arch/ia64/vmx/vmx_init.c b/xen/arch/ia64/vmx/vmx_init.c index bf85b7df0c..df1bc94de0 100644 --- a/xen/arch/ia64/vmx/vmx_init.c +++ b/xen/arch/ia64/vmx/vmx_init.c @@ -445,6 +445,9 @@ void vmx_setup_platform(struct domain *d) memset(&d->shared_info->evtchn_mask[0], 0xff, sizeof(d->shared_info->evtchn_mask)); + /* initiate spinlock for pass virq */ + spin_lock_init(&d->arch.arch_vmx.virq_assist_lock); + /* Initialize the virtual interrupt lines */ vmx_virq_line_init(d); diff --git a/xen/arch/ia64/vmx/vmx_support.c b/xen/arch/ia64/vmx/vmx_support.c index 3f8c4bcf0c..70b9dd7321 100644 --- a/xen/arch/ia64/vmx/vmx_support.c +++ b/xen/arch/ia64/vmx/vmx_support.c @@ -73,8 +73,10 @@ void vmx_intr_assist(struct vcpu *v) { #ifdef V_IOSAPIC_READY /* Confirm virtual interrupt line signals, and set pending bits in vpd */ - if(v->vcpu_id==0) + if (spin_trylock(&v->domain->arch.arch_vmx.virq_assist_lock)) { vmx_virq_line_assist(v); + spin_unlock(&v->domain->arch.arch_vmx.virq_assist_lock); + } #endif return; } diff --git a/xen/include/asm-ia64/domain.h b/xen/include/asm-ia64/domain.h index 394b3bc6ad..0222115242 100644 --- a/xen/include/asm-ia64/domain.h +++ b/xen/include/asm-ia64/domain.h @@ -137,6 +137,8 @@ struct arch_domain { atomic64_t shadow_fault_count; struct last_vcpu last_vcpu[NR_CPUS]; + + struct arch_vmx_domain arch_vmx; /* Virtual Machine Extensions */ }; #define INT_ENABLE_OFFSET(v) \ (sizeof(vcpu_info_t) * (v)->vcpu_id + \ diff --git a/xen/include/asm-ia64/vmx_vpd.h b/xen/include/asm-ia64/vmx_vpd.h index 82363a2876..b534268ebb 100644 --- a/xen/include/asm-ia64/vmx_vpd.h +++ b/xen/include/asm-ia64/vmx_vpd.h @@ -27,6 +27,7 @@ #include #include #include +#include #define VPD_SHIFT 17 /* 128K requirement */ #define VPD_SIZE (1 << VPD_SHIFT) @@ -72,6 +73,11 @@ struct ivt_debug{ }; #define IVT_DEBUG_MAX 128 #endif + +struct arch_vmx_domain { + spinlock_t virq_assist_lock; /* spinlock for pass virq */ +}; + struct arch_vmx_struct { // vpd_t *vpd; vtime_t vtm; From ee98b4c1f612b703b530f1b822c9f0573c400ad1 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Thu, 24 Aug 2006 11:54:23 -0600 Subject: [PATCH 35/58] [IA64] Avoid compile-time warnings. Signed-off-by: Tristan Gingold --- xen/include/asm-ia64/grant_table.h | 2 +- xen/include/asm-ia64/vmx.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/xen/include/asm-ia64/grant_table.h b/xen/include/asm-ia64/grant_table.h index 442e4fa4e1..1d0bded64f 100644 --- a/xen/include/asm-ia64/grant_table.h +++ b/xen/include/asm-ia64/grant_table.h @@ -35,7 +35,7 @@ void guest_physmap_add_page(struct domain *d, unsigned long gpfn, unsigned long gnttab_shared_maddr((d), (t), (i))); \ (IA64_GRANT_TABLE_PADDR >> PAGE_SHIFT) + (i);}) -#define gnttab_mark_dirty(d, f) ((void)0) +#define gnttab_mark_dirty(d, f) ((void)f) static inline void gnttab_clear_flag(unsigned long nr, uint16_t *addr) { diff --git a/xen/include/asm-ia64/vmx.h b/xen/include/asm-ia64/vmx.h index f2e6de5cea..b9d9a67779 100644 --- a/xen/include/asm-ia64/vmx.h +++ b/xen/include/asm-ia64/vmx.h @@ -55,6 +55,7 @@ extern void illegal_op (struct vcpu *vcpu); extern void vmx_relinquish_guest_resources(struct domain *d); extern void vmx_relinquish_vcpu_resources(struct vcpu *v); extern void vmx_die_if_kernel(char *str, struct pt_regs *regs, long err); +extern void vmx_send_assist_req(struct vcpu *v); static inline vcpu_iodata_t *get_vio(struct domain *d, unsigned long cpu) { From 0775ba7ce3e40ed7e4c30dcd3a3f0fd039722631 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Fri, 25 Aug 2006 15:06:18 -0600 Subject: [PATCH 36/58] [IA64] Expand hvm_op hypercall for PV-on-HVM/IPF Introduce HVMOP_setup_shared_info_page - A page allocated on HVM-guest OS is swapped original shared_info page with this hypercall. - In x86 code, original shared_info page is used after pv-on-hvm setup with remapping feature in arch depend HYPERVISOR_memory_op. But, we can't implement same feature for IPF, thus we select to implement with this method. Introduce HVMOP_setup_gnttab_table - Pages allocated on HVM-guest OS is swapped original grant_table page frames with this hypercall. - Same above. Signed-off-by: Tsunehisa Doi Signed-off-by: Tomonari Horikoshi --- xen/arch/ia64/vmx/vmx_hypercall.c | 105 ++++++++++++++++++++++++++++++ xen/include/public/arch-ia64.h | 11 ++++ 2 files changed, 116 insertions(+) diff --git a/xen/arch/ia64/vmx/vmx_hypercall.c b/xen/arch/ia64/vmx/vmx_hypercall.c index bc3c6e7cab..9b566e88d3 100644 --- a/xen/arch/ia64/vmx/vmx_hypercall.c +++ b/xen/arch/ia64/vmx/vmx_hypercall.c @@ -2,6 +2,7 @@ /* * vmx_hyparcall.c: handling hypercall from domain * Copyright (c) 2005, Intel Corporation. + * Copyright (c) 2006, Fujitsu Limited. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -17,6 +18,8 @@ * Place - Suite 330, Boston, MA 02111-1307 USA. * * Xuefei Xu (Anthony Xu) (Anthony.xu@intel.com) + * Tsunehisa Doi (Doi.Tsunehisa@jp.fujitsu.com) + * Tomonari Horikoshi (t.horikoshi@jp.fujitsu.com) */ #include @@ -34,6 +37,89 @@ #include #include #include +#include +#include + +static void +vmx_free_pages(unsigned long pgaddr, int npg) +{ + for (; npg > 0; npg--, pgaddr += PAGE_SIZE) { + /* If original page belongs to xen heap, then relinguish back + * to xen heap. Or else, leave to domain itself to decide. + */ + if (likely(IS_XEN_HEAP_FRAME(virt_to_page(pgaddr)))) { + free_domheap_page(virt_to_page(pgaddr)); + free_xenheap_page((void *)pgaddr); + } + else { + put_page(virt_to_page(pgaddr)); + } + } +} + +static int +vmx_gnttab_setup_table(unsigned long frame_pa, unsigned long nr_frames) +{ + struct domain *d = current->domain; + unsigned long o_grant_shared, pgaddr; + + if ((nr_frames != NR_GRANT_FRAMES) || (frame_pa & (PAGE_SIZE - 1))) { + return -EINVAL; + } + + pgaddr = domain_mpa_to_imva(d, frame_pa); + if (pgaddr == NULL) { + return -EFAULT; + } + + o_grant_shared = (unsigned long)d->grant_table->shared; + d->grant_table->shared = (struct grant_entry *)pgaddr; + + /* Copy existing grant table shared into new page */ + if (o_grant_shared) { + memcpy((void *)d->grant_table->shared, + (void *)o_grant_shared, PAGE_SIZE * nr_frames); + vmx_free_pages(o_grant_shared, nr_frames); + } + else { + memset((void *)d->grant_table->shared, 0, PAGE_SIZE * nr_frames); + } + return 0; +} + +static int +vmx_setup_shared_info_page(unsigned long gpa) +{ + VCPU *vcpu = current; + struct domain *d = vcpu->domain; + unsigned long o_info, pgaddr; + struct vcpu *v; + + if (gpa & (PAGE_SIZE - 1)) { + return -EINVAL; + } + + pgaddr = domain_mpa_to_imva(d, gpa); + if (pgaddr == NULL) { + return -EFAULT; + } + + o_info = (u64)d->shared_info; + d->shared_info = (shared_info_t *)pgaddr; + + /* Copy existing shared info into new page */ + if (o_info) { + memcpy((void*)d->shared_info, (void*)o_info, PAGE_SIZE); + for_each_vcpu(d, v) { + v->vcpu_info = &d->shared_info->vcpu_info[v->vcpu_id]; + } + vmx_free_pages(o_info, 1); + } + else { + memset((void *)d->shared_info, 0, PAGE_SIZE); + } + return 0; +} long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) @@ -78,6 +164,25 @@ do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) break; } + case HVMOP_setup_gnttab_table: + case HVMOP_setup_shared_info_page: + { + struct xen_hvm_setup a; + + if (copy_from_guest(&a, arg, 1)) + return -EFAULT; + + switch (op) { + case HVMOP_setup_gnttab_table: + printk("vmx_gnttab_setup_table: frame_pa=%#lx," + "nr_frame=%ld\n", a.arg1, a.arg2); + return vmx_gnttab_setup_table(a.arg1, a.arg2); + case HVMOP_setup_shared_info_page: + printk("vmx_setup_shared_info_page: gpa=0x%lx\n", a.arg1); + return vmx_setup_shared_info_page(a.arg1); + } + } + default: DPRINTK("Bad HVM op %ld.\n", op); rc = -ENOSYS; diff --git a/xen/include/public/arch-ia64.h b/xen/include/public/arch-ia64.h index 98bda1d241..31c4a0748e 100644 --- a/xen/include/public/arch-ia64.h +++ b/xen/include/public/arch-ia64.h @@ -336,6 +336,17 @@ struct vcpu_guest_context { typedef struct vcpu_guest_context vcpu_guest_context_t; DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t); +// hvm_op expansion +#define HVMOP_setup_gnttab_table 2 +#define HVMOP_setup_shared_info_page 3 + +struct xen_hvm_setup { + unsigned long arg1; + unsigned long arg2; +}; +typedef struct xen_hvm_setup xen_hvm_setup_t; +DEFINE_XEN_GUEST_HANDLE(xen_hvm_setup_t); + // dom0 vp op #define __HYPERVISOR_ia64_dom0vp_op __HYPERVISOR_arch_0 #define IA64_DOM0VP_ioremap 0 // map io space in machine From ca2696587ad3fcef892f16ed2f56684279907704 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Fri, 25 Aug 2006 15:52:31 -0600 Subject: [PATCH 37/58] [IA64] dom_fw.c cleaned up. Only use one page for stubs and tables instead of 2MB. Create struct fw_tables to make code more understandable. Many comments added. Correctly compute sal systab checksum. Signed-off-by: Tristan Gingold --- xen/arch/ia64/xen/dom_fw.c | 608 +++++++++++++++++----------------- xen/include/asm-ia64/dom_fw.h | 39 ++- 2 files changed, 322 insertions(+), 325 deletions(-) diff --git a/xen/arch/ia64/xen/dom_fw.c b/xen/arch/ia64/xen/dom_fw.c index 2a70b66e66..0296794722 100644 --- a/xen/arch/ia64/xen/dom_fw.c +++ b/xen/arch/ia64/xen/dom_fw.c @@ -26,24 +26,25 @@ #include #include -static void dom_fw_init (struct domain *d, struct ia64_boot_param *bp, char *fw_mem, int fw_mem_size, unsigned long maxmem); - -extern struct domain *dom0; +#define ONE_MB (1UL << 20) extern unsigned long running_on_sim; +/* Base of FW tables. */ +static const unsigned long dom_fw_base_mpa = FW_HYPERCALL_END_PADDR; +static unsigned long dom_fw_end_mpa; + /* Note: two domains cannot be created simulteanously! */ -static unsigned long dom_fw_base_mpa = -1; static unsigned long imva_fw_base = -1; #define FW_VENDOR "X\0e\0n\0/\0i\0a\0\066\0\064\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" -#define MAKE_MD(typ, attr, start, end, abs) \ +#define MAKE_MD(typ, attr, start, end) \ do { \ - md = efi_memmap + i++; \ + md = tables->efi_memmap + i++; \ md->type = typ; \ md->pad = 0; \ - md->phys_addr = abs ? start : start_mpaddr + start; \ + md->phys_addr = start; \ md->virt_addr = 0; \ md->num_pages = (end - start) >> EFI_PAGE_SHIFT; \ md->attribute = attr; \ @@ -53,8 +54,8 @@ static unsigned long imva_fw_base = -1; do { \ dom_efi_hypercall_patch(d, FW_HYPERCALL_##call##_PADDR, \ FW_HYPERCALL_##call); \ - tgt = dom_pa((unsigned long) pfn); \ - *pfn++ = FW_HYPERCALL_##call##_PADDR + start_mpaddr; \ + tables->efi_runtime.tgt = dom_pa((unsigned long) pfn); \ + *pfn++ = FW_HYPERCALL_##call##_PADDR; \ *pfn++ = 0; \ } while (0) @@ -63,7 +64,7 @@ static unsigned long imva_fw_base = -1; static unsigned long dom_pa(unsigned long imva) { - if (dom_fw_base_mpa == -1 || imva_fw_base == -1) { + if (imva_fw_base == -1) { printf("dom_pa: uninitialized! (spinning...)\n"); while(1); } @@ -78,12 +79,12 @@ dom_pa(unsigned long imva) // allocate a page for fw // build_physmap_table() which is called by new_thread() // does for domU. -#define ASSIGN_NEW_DOMAIN_PAGE_IF_DOM0(d, mpaddr) \ - do { \ - if ((d) == dom0) { \ - assign_new_domain0_page((d), (mpaddr)); \ - } \ - } while (0) +static inline void +assign_new_domain_page_if_dom0(struct domain *d, unsigned long mpaddr) +{ + if (d == dom0) + assign_new_domain0_page(d, mpaddr); +} /************************************************************************** Hypercall bundle creation @@ -105,8 +106,8 @@ static void build_hypercall_bundle(UINT64 *imva, UINT64 brkimm, UINT64 hypnum, U slot1.inst = 0; slot1.qp = 0; slot1.x6 = 0; slot1.x3 = 0; slot1.major = 0x0; slot1.imm20 = brkimm; slot1.i = brkimm >> 20; - // if ret slot2: br.ret.sptk.many rp - // else slot2: br.cond.sptk.many rp + // if ret slot2: br.ret.sptk.many rp + // else slot2: br.cond.sptk.many rp slot2.inst = 0; slot2.qp = 0; slot2.p = 1; slot2.b2 = 0; slot2.wh = 0; slot2.d = 0; slot2.major = 0x0; if (ret) { @@ -169,14 +170,15 @@ static void dom_fpswa_hypercall_patch(struct domain *d) unsigned long entry_paddr = FW_HYPERCALL_FPSWA_ENTRY_PADDR; unsigned long patch_paddr = FW_HYPERCALL_FPSWA_PATCH_PADDR; - ASSIGN_NEW_DOMAIN_PAGE_IF_DOM0(d, entry_paddr); - ASSIGN_NEW_DOMAIN_PAGE_IF_DOM0(d, patch_paddr); + assign_new_domain_page_if_dom0(d, entry_paddr); + assign_new_domain_page_if_dom0(d, patch_paddr); entry_imva = domain_mpa_to_imva(d, entry_paddr); patch_imva = domain_mpa_to_imva(d, patch_paddr); *entry_imva++ = patch_paddr; *entry_imva = 0; - build_hypercall_bundle(patch_imva, d->arch.breakimm, FW_HYPERCALL_FPSWA, 1); + build_hypercall_bundle(patch_imva, d->arch.breakimm, + FW_HYPERCALL_FPSWA, 1); } // builds a hypercall bundle at domain physical address @@ -184,7 +186,7 @@ static void dom_efi_hypercall_patch(struct domain *d, unsigned long paddr, unsig { unsigned long *imva; - ASSIGN_NEW_DOMAIN_PAGE_IF_DOM0(d, paddr); + assign_new_domain_page_if_dom0(d, paddr); imva = domain_mpa_to_imva(d, paddr); build_hypercall_bundle(imva, d->arch.breakimm, hypercall, 1); } @@ -194,7 +196,7 @@ static void dom_fw_hypercall_patch(struct domain *d, unsigned long paddr, unsign { unsigned long *imva; - ASSIGN_NEW_DOMAIN_PAGE_IF_DOM0(d, paddr); + assign_new_domain_page_if_dom0(d, paddr); imva = domain_mpa_to_imva(d, paddr); build_hypercall_bundle(imva, d->arch.breakimm, hypercall, ret); } @@ -203,36 +205,28 @@ static void dom_fw_pal_hypercall_patch(struct domain *d, unsigned long paddr) { unsigned long *imva; - ASSIGN_NEW_DOMAIN_PAGE_IF_DOM0(d, paddr); + assign_new_domain_page_if_dom0(d, paddr); imva = domain_mpa_to_imva(d, paddr); - build_pal_hypercall_bundles(imva, d->arch.breakimm, FW_HYPERCALL_PAL_CALL); + build_pal_hypercall_bundles(imva, d->arch.breakimm, + FW_HYPERCALL_PAL_CALL); } - -void dom_fw_setup(struct domain *d, unsigned long bp_mpa, unsigned long maxmem) -{ - struct ia64_boot_param *bp; - - dom_fw_base_mpa = 0; - ASSIGN_NEW_DOMAIN_PAGE_IF_DOM0(d, dom_fw_base_mpa); - imva_fw_base = (unsigned long) domain_mpa_to_imva(d, dom_fw_base_mpa); - ASSIGN_NEW_DOMAIN_PAGE_IF_DOM0(d, bp_mpa); - bp = domain_mpa_to_imva(d, bp_mpa); - dom_fw_init(d, bp, (char *) imva_fw_base, PAGE_SIZE, maxmem); -} - - /* the following heavily leveraged from linux/arch/ia64/hp/sim/fw-emu.c */ -#define NFUNCPTRS 20 - static inline void print_md(efi_memory_desc_t *md) { - printk("domain mem: type=%2u, attr=0x%016lx, range=[0x%016lx-0x%016lx) (%luMB)\n", - md->type, md->attribute, md->phys_addr, - md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT), - md->num_pages >> (20 - EFI_PAGE_SHIFT)); + u64 size; + + printk("dom mem: type=%2u, attr=0x%016lx, range=[0x%016lx-0x%016lx) ", + md->type, md->attribute, md->phys_addr, + md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)); + + size = md->num_pages << EFI_PAGE_SHIFT; + if (size > ONE_MB) + printf ("(%luMB)\n", size >> 20); + else + printf ("(%luKB)\n", size >> 10); } static u32 lsapic_nbr; @@ -468,9 +462,6 @@ dom_fw_fake_acpi(struct domain *d, struct fake_acpi_tables *tables) return; } -#define NUM_EFI_SYS_TABLES 6 -#define NUM_MEM_DESCS 64 //large enough - struct dom0_passthrough_arg { struct domain* d; int flags; @@ -530,23 +521,16 @@ static int dom_fw_dom0_lowmem(efi_memory_desc_t *md, void *arg__) { struct dom0_passthrough_arg* arg = (struct dom0_passthrough_arg*)arg__; - u64 end = min(HYPERCALL_START, - md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)); + u64 end = min(ONE_MB, md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)); BUG_ON(md->type != EFI_CONVENTIONAL_MEMORY); - /* avoid hypercall area */ - if (md->phys_addr >= HYPERCALL_START) - return 0; - - /* avoid firmware base area */ - if (md->phys_addr < dom_pa(imva_fw_base)) - end = min(end, dom_pa(imva_fw_base)); - else if (md->phys_addr < dom_pa(imva_fw_base + PAGE_SIZE)) { - if (end < dom_pa(imva_fw_base + PAGE_SIZE)) - return 0; - md->phys_addr = dom_pa(imva_fw_base + PAGE_SIZE); - } + /* Avoid firmware and hypercall area. + We know they are 0-based. */ + if (end < dom_fw_end_mpa || md->phys_addr >= ONE_MB) + return 0; + if (md->phys_addr < dom_fw_end_mpa) + md->phys_addr = dom_fw_end_mpa; arg->md->type = md->type; arg->md->pad = 0; @@ -558,22 +542,6 @@ dom_fw_dom0_lowmem(efi_memory_desc_t *md, void *arg__) (*arg->i)++; arg->md++; - /* if firmware area spliced the md, add the upper part here */ - if (end == dom_pa(imva_fw_base)) { - end = min(HYPERCALL_START, - md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)); - if (end > dom_pa(imva_fw_base + PAGE_SIZE)) { - arg->md->type = md->type; - arg->md->pad = 0; - arg->md->phys_addr = dom_pa(imva_fw_base + PAGE_SIZE); - arg->md->virt_addr = 0; - arg->md->num_pages = (end - arg->md->phys_addr) >> EFI_PAGE_SHIFT; - arg->md->attribute = md->attribute; - - (*arg->i)++; - arg->md++; - } - } return 0; } @@ -596,296 +564,291 @@ efi_mdt_cmp(const void *a, const void *b) return 0; } +#define NFUNCPTRS 16 +#define NUM_EFI_SYS_TABLES 6 +#define NUM_MEM_DESCS 64 //large enough + +struct fw_tables { + efi_system_table_t efi_systab; + efi_runtime_services_t efi_runtime; + efi_config_table_t efi_tables[NUM_EFI_SYS_TABLES]; + + struct ia64_sal_systab sal_systab; + struct ia64_sal_desc_entry_point sal_ed; + struct ia64_sal_desc_ap_wakeup sal_wakeup; + /* End of SAL descriptors. Do not forget to update checkum bound. */ + + fpswa_interface_t fpswa_inf; + efi_memory_desc_t efi_memmap[NUM_MEM_DESCS]; + unsigned long func_ptrs[2*NFUNCPTRS]; + struct xen_sal_data sal_data; + unsigned char fw_vendor[sizeof(FW_VENDOR)]; + + struct fake_acpi_tables acpi_tables; +}; + static void -dom_fw_init (struct domain *d, struct ia64_boot_param *bp, char *fw_mem, int fw_mem_size, unsigned long maxmem) +dom_fw_init(struct domain *d, + struct ia64_boot_param *bp, + struct fw_tables *tables, + unsigned long maxmem) { - efi_system_table_t *efi_systab; - efi_runtime_services_t *efi_runtime; - efi_config_table_t *efi_tables; - struct ia64_sal_systab *sal_systab; - struct ia64_sal_desc_entry_point *sal_ed; - struct ia64_sal_desc_ap_wakeup *sal_wakeup; - fpswa_interface_t *fpswa_inf; - efi_memory_desc_t *efi_memmap, *md; - struct xen_sal_data *sal_data; + efi_memory_desc_t *md; unsigned long *pfn; - unsigned char checksum = 0; - char *cp, *fw_vendor; - int num_mds, j, i = 0; - const unsigned long start_mpaddr = 0; + unsigned char checksum; + char *cp; + int num_mds, i; -/* FIXME: should check size but for now we have a whole MB to play with. - And if stealing code from fw-emu.c, watch out for new fw_vendor on the end! - if (fw_mem_size < sizeof(fw_mem_proto)) { - printf("sys_fw_init: insufficient space for fw_mem\n"); - return 0; - } -*/ - memset(fw_mem, 0, fw_mem_size); - - cp = fw_mem; - efi_systab = (void *) cp; cp += sizeof(*efi_systab); - efi_runtime = (void *) cp; cp += sizeof(*efi_runtime); - efi_tables = (void *) cp; cp += NUM_EFI_SYS_TABLES * sizeof(*efi_tables); - sal_systab = (void *) cp; cp += sizeof(*sal_systab); - sal_ed = (void *) cp; cp += sizeof(*sal_ed); - sal_wakeup = (void *) cp; cp += sizeof(*sal_wakeup); - fpswa_inf = (void *) cp; cp += sizeof(*fpswa_inf); - efi_memmap = (void *) cp; cp += NUM_MEM_DESCS*sizeof(*efi_memmap); - pfn = (void *) cp; cp += NFUNCPTRS * 2 * sizeof(pfn); - sal_data = (void *) cp; cp += sizeof(*sal_data); + memset(tables, 0, sizeof(struct fw_tables)); /* Initialise for EFI_SET_VIRTUAL_ADDRESS_MAP emulation */ - d->arch.efi_runtime = efi_runtime; - d->arch.fpswa_inf = fpswa_inf; - d->arch.sal_data = sal_data; + d->arch.efi_runtime = &tables->efi_runtime; + d->arch.fpswa_inf = &tables->fpswa_inf; + d->arch.sal_data = &tables->sal_data; - memset(efi_systab, 0, sizeof(efi_systab)); - efi_systab->hdr.signature = EFI_SYSTEM_TABLE_SIGNATURE; - efi_systab->hdr.revision = EFI_SYSTEM_TABLE_REVISION; - efi_systab->hdr.headersize = sizeof(efi_systab->hdr); - fw_vendor = cp; - cp += sizeof(FW_VENDOR) + (8-((unsigned long)cp & 7)); // round to 64-bit boundary + /* EFI systab. */ + tables->efi_systab.hdr.signature = EFI_SYSTEM_TABLE_SIGNATURE; + tables->efi_systab.hdr.revision = EFI_SYSTEM_TABLE_REVISION; + tables->efi_systab.hdr.headersize = sizeof(tables->efi_systab.hdr); - memcpy(fw_vendor,FW_VENDOR,sizeof(FW_VENDOR)); - efi_systab->fw_vendor = dom_pa((unsigned long) fw_vendor); - efi_systab->fw_revision = 1; - efi_systab->runtime = (void *) dom_pa((unsigned long) efi_runtime); - efi_systab->nr_tables = NUM_EFI_SYS_TABLES; - efi_systab->tables = dom_pa((unsigned long) efi_tables); + memcpy(tables->fw_vendor,FW_VENDOR,sizeof(FW_VENDOR)); + tables->efi_systab.fw_vendor = + dom_pa((unsigned long)tables->fw_vendor); + tables->efi_systab.fw_revision = 1; + tables->efi_systab.runtime = + (void *)dom_pa((unsigned long)&tables->efi_runtime); + tables->efi_systab.nr_tables = NUM_EFI_SYS_TABLES; + tables->efi_systab.tables = dom_pa((unsigned long)tables->efi_tables); - efi_runtime->hdr.signature = EFI_RUNTIME_SERVICES_SIGNATURE; - efi_runtime->hdr.revision = EFI_RUNTIME_SERVICES_REVISION; - efi_runtime->hdr.headersize = sizeof(efi_runtime->hdr); + /* EFI runtime. */ + tables->efi_runtime.hdr.signature = EFI_RUNTIME_SERVICES_SIGNATURE; + tables->efi_runtime.hdr.revision = EFI_RUNTIME_SERVICES_REVISION; + tables->efi_runtime.hdr.headersize = sizeof(tables->efi_runtime.hdr); - EFI_HYPERCALL_PATCH(efi_runtime->get_time,EFI_GET_TIME); - EFI_HYPERCALL_PATCH(efi_runtime->set_time,EFI_SET_TIME); - EFI_HYPERCALL_PATCH(efi_runtime->get_wakeup_time,EFI_GET_WAKEUP_TIME); - EFI_HYPERCALL_PATCH(efi_runtime->set_wakeup_time,EFI_SET_WAKEUP_TIME); - EFI_HYPERCALL_PATCH(efi_runtime->set_virtual_address_map,EFI_SET_VIRTUAL_ADDRESS_MAP); - EFI_HYPERCALL_PATCH(efi_runtime->get_variable,EFI_GET_VARIABLE); - EFI_HYPERCALL_PATCH(efi_runtime->get_next_variable,EFI_GET_NEXT_VARIABLE); - EFI_HYPERCALL_PATCH(efi_runtime->set_variable,EFI_SET_VARIABLE); - EFI_HYPERCALL_PATCH(efi_runtime->get_next_high_mono_count,EFI_GET_NEXT_HIGH_MONO_COUNT); - EFI_HYPERCALL_PATCH(efi_runtime->reset_system,EFI_RESET_SYSTEM); + pfn = tables->func_ptrs; + EFI_HYPERCALL_PATCH(get_time,EFI_GET_TIME); + EFI_HYPERCALL_PATCH(set_time,EFI_SET_TIME); + EFI_HYPERCALL_PATCH(get_wakeup_time,EFI_GET_WAKEUP_TIME); + EFI_HYPERCALL_PATCH(set_wakeup_time,EFI_SET_WAKEUP_TIME); + EFI_HYPERCALL_PATCH(set_virtual_address_map, + EFI_SET_VIRTUAL_ADDRESS_MAP); + EFI_HYPERCALL_PATCH(get_variable,EFI_GET_VARIABLE); + EFI_HYPERCALL_PATCH(get_next_variable,EFI_GET_NEXT_VARIABLE); + EFI_HYPERCALL_PATCH(set_variable,EFI_SET_VARIABLE); + EFI_HYPERCALL_PATCH(get_next_high_mono_count, + EFI_GET_NEXT_HIGH_MONO_COUNT); + EFI_HYPERCALL_PATCH(reset_system,EFI_RESET_SYSTEM); - efi_tables[0].guid = SAL_SYSTEM_TABLE_GUID; - efi_tables[0].table = dom_pa((unsigned long) sal_systab); + /* System tables. */ + tables->efi_tables[0].guid = SAL_SYSTEM_TABLE_GUID; + tables->efi_tables[0].table = + dom_pa((unsigned long)&tables->sal_systab); for (i = 1; i < NUM_EFI_SYS_TABLES; i++) { - efi_tables[i].guid = NULL_GUID; - efi_tables[i].table = 0; + tables->efi_tables[i].guid = NULL_GUID; + tables->efi_tables[i].table = 0; } + i = 1; if (d == dom0) { printf("Domain0 EFI passthrough:"); - i = 1; if (efi.mps) { - efi_tables[i].guid = MPS_TABLE_GUID; - efi_tables[i].table = __pa(efi.mps); - printf(" MPS=0x%lx",efi_tables[i].table); + tables->efi_tables[i].guid = MPS_TABLE_GUID; + tables->efi_tables[i].table = __pa(efi.mps); + printf(" MPS=0x%lx",tables->efi_tables[i].table); i++; } touch_acpi_table(); if (efi.acpi20) { - efi_tables[i].guid = ACPI_20_TABLE_GUID; - efi_tables[i].table = __pa(efi.acpi20); - printf(" ACPI 2.0=0x%lx",efi_tables[i].table); + tables->efi_tables[i].guid = ACPI_20_TABLE_GUID; + tables->efi_tables[i].table = __pa(efi.acpi20); + printf(" ACPI 2.0=0x%lx",tables->efi_tables[i].table); i++; } if (efi.acpi) { - efi_tables[i].guid = ACPI_TABLE_GUID; - efi_tables[i].table = __pa(efi.acpi); - printf(" ACPI=0x%lx",efi_tables[i].table); + tables->efi_tables[i].guid = ACPI_TABLE_GUID; + tables->efi_tables[i].table = __pa(efi.acpi); + printf(" ACPI=0x%lx",tables->efi_tables[i].table); i++; } if (efi.smbios) { - efi_tables[i].guid = SMBIOS_TABLE_GUID; - efi_tables[i].table = __pa(efi.smbios); - printf(" SMBIOS=0x%lx",efi_tables[i].table); + tables->efi_tables[i].guid = SMBIOS_TABLE_GUID; + tables->efi_tables[i].table = __pa(efi.smbios); + printf(" SMBIOS=0x%lx",tables->efi_tables[i].table); i++; } if (efi.hcdp) { - efi_tables[i].guid = HCDP_TABLE_GUID; - efi_tables[i].table = __pa(efi.hcdp); - printf(" HCDP=0x%lx",efi_tables[i].table); + tables->efi_tables[i].guid = HCDP_TABLE_GUID; + tables->efi_tables[i].table = __pa(efi.hcdp); + printf(" HCDP=0x%lx",tables->efi_tables[i].table); i++; } printf("\n"); } else { printf("DomainU EFI build up:"); - i = 1; - if ((unsigned long)fw_mem + fw_mem_size - (unsigned long)cp >= - sizeof(struct fake_acpi_tables)) { - struct fake_acpi_tables *acpi_tables; + dom_fw_fake_acpi(d, &tables->acpi_tables); - acpi_tables = (void *)cp; - cp += sizeof(struct fake_acpi_tables); - dom_fw_fake_acpi(d, acpi_tables); - - efi_tables[i].guid = ACPI_20_TABLE_GUID; - efi_tables[i].table = dom_pa((unsigned long) acpi_tables); - printf(" ACPI 2.0=0x%lx",efi_tables[i].table); - i++; - } + tables->efi_tables[i].guid = ACPI_20_TABLE_GUID; + tables->efi_tables[i].table = + dom_pa((unsigned long) &tables->acpi_tables); + printf(" ACPI 2.0=0x%lx",tables->efi_tables[i].table); + i++; printf("\n"); } /* fill in the SAL system table: */ - memcpy(sal_systab->signature, "SST_", 4); - sal_systab->size = sizeof(*sal_systab); - sal_systab->sal_rev_minor = 1; - sal_systab->sal_rev_major = 0; - sal_systab->entry_count = 2; + memcpy(tables->sal_systab.signature, "SST_", 4); + tables->sal_systab.size = sizeof(tables->sal_systab); + tables->sal_systab.sal_rev_minor = 1; + tables->sal_systab.sal_rev_major = 0; + tables->sal_systab.entry_count = 2; - strcpy((char *)sal_systab->oem_id, "Xen/ia64"); - strcpy((char *)sal_systab->product_id, "Xen/ia64"); + strcpy((char *)tables->sal_systab.oem_id, "Xen/ia64"); + strcpy((char *)tables->sal_systab.product_id, "Xen/ia64"); /* fill in an entry point: */ - sal_ed->type = SAL_DESC_ENTRY_POINT; - sal_ed->pal_proc = FW_HYPERCALL_PAL_CALL_PADDR + start_mpaddr; - dom_fw_pal_hypercall_patch (d, sal_ed->pal_proc); - sal_ed->sal_proc = FW_HYPERCALL_SAL_CALL_PADDR + start_mpaddr; - dom_fw_hypercall_patch (d, sal_ed->sal_proc, FW_HYPERCALL_SAL_CALL, 1); - sal_ed->gp = 0; // will be ignored + tables->sal_ed.type = SAL_DESC_ENTRY_POINT; + tables->sal_ed.pal_proc = FW_HYPERCALL_PAL_CALL_PADDR; + dom_fw_pal_hypercall_patch(d, tables->sal_ed.pal_proc); + tables->sal_ed.sal_proc = FW_HYPERCALL_SAL_CALL_PADDR; + dom_fw_hypercall_patch(d, tables->sal_ed.sal_proc, + FW_HYPERCALL_SAL_CALL, 1); + tables->sal_ed.gp = 0; /* will be ignored */ /* Fill an AP wakeup descriptor. */ - sal_wakeup->type = SAL_DESC_AP_WAKEUP; - sal_wakeup->mechanism = IA64_SAL_AP_EXTERNAL_INT; - sal_wakeup->vector = XEN_SAL_BOOT_RENDEZ_VEC; + tables->sal_wakeup.type = SAL_DESC_AP_WAKEUP; + tables->sal_wakeup.mechanism = IA64_SAL_AP_EXTERNAL_INT; + tables->sal_wakeup.vector = XEN_SAL_BOOT_RENDEZ_VEC; /* Compute checksum. */ - for (cp = (char *) sal_systab; cp < (char *) efi_memmap; ++cp) + checksum = 0; + for (cp = (char *)&tables->sal_systab; + cp < (char *)&tables->fpswa_inf; + ++cp) checksum += *cp; - sal_systab->checksum = -checksum; + tables->sal_systab.checksum = -checksum; /* SAL return point. */ - d->arch.sal_return_addr = FW_HYPERCALL_SAL_RETURN_PADDR + start_mpaddr; + d->arch.sal_return_addr = FW_HYPERCALL_SAL_RETURN_PADDR; dom_fw_hypercall_patch (d, d->arch.sal_return_addr, FW_HYPERCALL_SAL_RETURN, 0); /* Fill in the FPSWA interface: */ - fpswa_inf->revision = fpswa_interface->revision; + tables->fpswa_inf.revision = fpswa_interface->revision; dom_fpswa_hypercall_patch(d); - fpswa_inf->fpswa = (void *) FW_HYPERCALL_FPSWA_ENTRY_PADDR + start_mpaddr; + tables->fpswa_inf.fpswa = (void *)FW_HYPERCALL_FPSWA_ENTRY_PADDR; i = 0; /* Used by MAKE_MD */ - /* Create dom0/domu md entry for fw_mem area */ - MAKE_MD(EFI_ACPI_RECLAIM_MEMORY, EFI_MEMORY_WB | EFI_MEMORY_RUNTIME, - dom_pa((unsigned long)fw_mem), - dom_pa((unsigned long)fw_mem + fw_mem_size), 1); + /* hypercall patches live here, masquerade as reserved PAL memory */ + MAKE_MD(EFI_PAL_CODE,EFI_MEMORY_WB|EFI_MEMORY_RUNTIME, + FW_HYPERCALL_BASE_PADDR, FW_HYPERCALL_END_PADDR); - if (d == dom0) { - /* hypercall patches live here, masquerade as reserved PAL memory */ - MAKE_MD(EFI_PAL_CODE,EFI_MEMORY_WB|EFI_MEMORY_RUNTIME,HYPERCALL_START,HYPERCALL_END, 0); + /* Create dom0/domu md entry for fw tables area */ + MAKE_MD(EFI_RUNTIME_SERVICES_DATA, EFI_MEMORY_WB | EFI_MEMORY_RUNTIME, + dom_fw_base_mpa, dom_fw_end_mpa); - /* pass through the I/O port space */ - if (!running_on_sim) { - struct dom0_passthrough_arg arg; - arg.md = &efi_memmap[i]; - arg.i = &i; - arg.d = d; - arg.flags = ASSIGN_writable; - //XXX Is this needed? - efi_memmap_walk_type(EFI_RUNTIME_SERVICES_CODE, - dom_fw_dom0_passthrough, &arg); - // for ACPI table. - arg.flags = ASSIGN_readonly; - efi_memmap_walk_type(EFI_RUNTIME_SERVICES_DATA, - dom_fw_dom0_passthrough, &arg); - arg.flags = ASSIGN_writable; - efi_memmap_walk_type(EFI_ACPI_RECLAIM_MEMORY, - dom_fw_dom0_passthrough, &arg); - efi_memmap_walk_type(EFI_ACPI_MEMORY_NVS, - dom_fw_dom0_passthrough, &arg); - efi_memmap_walk_type(EFI_RESERVED_TYPE, - dom_fw_dom0_passthrough, &arg); - efi_memmap_walk_type(EFI_MEMORY_MAPPED_IO, - dom_fw_dom0_passthrough, &arg); - efi_memmap_walk_type(EFI_MEMORY_MAPPED_IO_PORT_SPACE, - dom_fw_dom0_passthrough, &arg); - efi_memmap_walk_type(EFI_CONVENTIONAL_MEMORY, - dom_fw_dom0_lowmem, &arg); - } - else MAKE_MD(EFI_RESERVED_TYPE,0,0,0,0); - } else { - /* hypercall patches live here, masquerade as reserved - PAL memory */ - MAKE_MD(EFI_PAL_CODE, EFI_MEMORY_WB | EFI_MEMORY_RUNTIME, - HYPERCALL_START, HYPERCALL_END, 1); + if (d != dom0 || running_on_sim) { + /* Memory. */ + MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB, + dom_fw_end_mpa, maxmem); + /* Create an entry for IO ports. */ MAKE_MD(EFI_MEMORY_MAPPED_IO_PORT_SPACE, EFI_MEMORY_UC, - IO_PORTS_PADDR, IO_PORTS_PADDR + IO_PORTS_SIZE, 1); - MAKE_MD(EFI_RESERVED_TYPE,0,0,0,0); + IO_PORTS_PADDR, IO_PORTS_PADDR + IO_PORTS_SIZE); + + num_mds = i; } - - // simple - // MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB, - // HYPERCALL_END, maxmem, 0); - // is not good. Check overlap. - sort(efi_memmap, i, sizeof(efi_memory_desc_t), - efi_mdt_cmp, NULL); - - // find gap and fill it with conventional memory - num_mds = i; - for (j = 0; j < num_mds; j++) { - unsigned long end; - unsigned long next_start; - - md = &efi_memmap[j]; - end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT); - - next_start = maxmem; - if (j + 1 < num_mds) { - efi_memory_desc_t* next_md = &efi_memmap[j + 1]; - next_start = next_md->phys_addr; - BUG_ON(end > next_start); - if (end == next_md->phys_addr) - continue; - } - - // clip the range and align to PAGE_SIZE - // Avoid "legacy" low memory addresses and the - // HYPERCALL patch area. - if (end < HYPERCALL_END) - end = HYPERCALL_END; - if (next_start > maxmem) - next_start = maxmem; - end = PAGE_ALIGN(end); - next_start = next_start & PAGE_MASK; - if (end >= next_start) - continue; - - MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB, - end, next_start, 0); - if (next_start >= maxmem) - break; - } - sort(efi_memmap, i, sizeof(efi_memory_desc_t), efi_mdt_cmp, NULL); - - bp->efi_systab = dom_pa((unsigned long) fw_mem); - bp->efi_memmap = dom_pa((unsigned long) efi_memmap); - BUG_ON(i > NUM_MEM_DESCS); - bp->efi_memmap_size = i * sizeof(efi_memory_desc_t); - bp->efi_memdesc_size = sizeof(efi_memory_desc_t); - bp->efi_memdesc_version = EFI_MEMDESC_VERSION; - bp->command_line = 0; - bp->console_info.num_cols = 80; - bp->console_info.num_rows = 25; - bp->console_info.orig_x = 0; - bp->console_info.orig_y = 24; - bp->fpswa = dom_pa((unsigned long) fpswa_inf); - if (d == dom0) { - int j; + else { + /* pass through the I/O port space */ + struct dom0_passthrough_arg arg; u64 addr; + int j; + + /* Fill from real entries. */ + arg.md = &tables->efi_memmap[i]; + arg.i = &i; + arg.d = d; + arg.flags = ASSIGN_writable; + //XXX Is this needed? + efi_memmap_walk_type(EFI_RUNTIME_SERVICES_CODE, + dom_fw_dom0_passthrough, &arg); + // for ACPI table. + arg.flags = ASSIGN_readonly; + efi_memmap_walk_type(EFI_RUNTIME_SERVICES_DATA, + dom_fw_dom0_passthrough, &arg); + arg.flags = ASSIGN_writable; + efi_memmap_walk_type(EFI_ACPI_RECLAIM_MEMORY, + dom_fw_dom0_passthrough, &arg); + efi_memmap_walk_type(EFI_ACPI_MEMORY_NVS, + dom_fw_dom0_passthrough, &arg); + efi_memmap_walk_type(EFI_MEMORY_MAPPED_IO, + dom_fw_dom0_passthrough, &arg); + efi_memmap_walk_type(EFI_MEMORY_MAPPED_IO_PORT_SPACE, + dom_fw_dom0_passthrough, &arg); + efi_memmap_walk_type(EFI_CONVENTIONAL_MEMORY, + dom_fw_dom0_lowmem, &arg); + num_mds = i; + + sort(tables->efi_memmap, num_mds, sizeof(efi_memory_desc_t), + efi_mdt_cmp, NULL); + + // find gaps and fill them with conventional memory + for (j = 0; j < num_mds; j++) { + unsigned long end; + unsigned long next_start; + + md = &tables->efi_memmap[j]; + end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT); + + if (j + 1 < num_mds) { + efi_memory_desc_t* next_md; + next_md = &tables->efi_memmap[j+1]; + next_start = next_md->phys_addr; + + /* Have just been sorted. */ + BUG_ON(end > next_start); + + /* No room for memory! */ + if (end == next_start) + continue; + + if (next_start > maxmem) + next_start = maxmem; + } + else + next_start = maxmem; + + /* Avoid "legacy" low memory addresses and + the HYPERCALL area. */ + if (end < ONE_MB) + end = ONE_MB; + + // clip the range and align to PAGE_SIZE + next_start = next_start & PAGE_MASK; + end = PAGE_ALIGN(end); + + /* No room for memory. */ + if (end >= next_start) + continue; + + MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB, + end, next_start); + + if (next_start >= maxmem) + break; + } + num_mds = i; + BUG_ON(num_mds > NUM_MEM_DESCS); + sort(tables->efi_memmap, num_mds, sizeof(efi_memory_desc_t), + efi_mdt_cmp, NULL); // dom0 doesn't need build_physmap_table() // see arch_set_info_guest() // instead we allocate pages manually. - for (j = 0; j < i; j++) { - md = &efi_memmap[j]; + for (i = 0; i < num_mds; i++) { + md = &tables->efi_memmap[i]; if (md->phys_addr > maxmem) break; @@ -898,18 +861,20 @@ dom_fw_init (struct domain *d, struct ia64_boot_param *bp, char *fw_mem, int fw_ if (end == start) { // md->num_pages = 0 is allowed. - end += PAGE_SIZE; + continue; } if (end > (max_page << PAGE_SHIFT)) end = (max_page << PAGE_SHIFT); - for (addr = start; addr < end; addr += PAGE_SIZE) { + for (addr = start; + addr < end; + addr += PAGE_SIZE) { assign_new_domain0_page(d, addr); } } } // Map low-memory holes & unmapped MMIO for legacy drivers - for (addr = 0; addr < 1*MB; addr += PAGE_SIZE) { + for (addr = 0; addr < ONE_MB; addr += PAGE_SIZE) { if (domain_page_mapped(d, addr)) continue; @@ -917,8 +882,41 @@ dom_fw_init (struct domain *d, struct ia64_boot_param *bp, char *fw_mem, int fw_ assign_domain_mmio_page(d, addr, PAGE_SIZE); } } - for (i = 0 ; i < bp->efi_memmap_size/sizeof(efi_memory_desc_t) ; i++) { - md = efi_memmap + i; - print_md(md); - } + + /* Display memmap. */ + for (i = 0 ; i < num_mds; i++) + print_md(&tables->efi_memmap[i]); + + /* Fill boot_param */ + bp->efi_systab = dom_pa((unsigned long)&tables->efi_systab); + bp->efi_memmap = dom_pa((unsigned long)tables->efi_memmap); + bp->efi_memmap_size = num_mds * sizeof(efi_memory_desc_t); + bp->efi_memdesc_size = sizeof(efi_memory_desc_t); + bp->efi_memdesc_version = EFI_MEMDESC_VERSION; + bp->command_line = 0; + bp->console_info.num_cols = 80; + bp->console_info.num_rows = 25; + bp->console_info.orig_x = 0; + bp->console_info.orig_y = 24; + bp->fpswa = dom_pa((unsigned long) &tables->fpswa_inf); +} + +void dom_fw_setup(struct domain *d, unsigned long bp_mpa, unsigned long maxmem) +{ + struct ia64_boot_param *bp; + + /* Note: 4KB < size < 8KB. */ + BUILD_BUG_ON(sizeof(struct fw_tables) > PAGE_SIZE); + + dom_fw_end_mpa = PAGE_ALIGN(dom_fw_base_mpa + sizeof(struct fw_tables)); + + /* Create page for hypercalls. */ + assign_new_domain_page_if_dom0(d, dom_fw_base_mpa); + imva_fw_base = (unsigned long)domain_mpa_to_imva(d, dom_fw_base_mpa); + + /* Create page for boot_param. */ + assign_new_domain_page_if_dom0(d, bp_mpa); + bp = domain_mpa_to_imva(d, bp_mpa); + + dom_fw_init(d, bp, (struct fw_tables *)imva_fw_base, maxmem); } diff --git a/xen/include/asm-ia64/dom_fw.h b/xen/include/asm-ia64/dom_fw.h index 10d7c2e380..579dfd384a 100644 --- a/xen/include/asm-ia64/dom_fw.h +++ b/xen/include/asm-ia64/dom_fw.h @@ -7,18 +7,17 @@ #include -#ifndef MB -#define MB (1024*1024) -#endif - /* This is used to determined the portion of a domain's metaphysical memory space reserved for the hypercall patch table. */ -//FIXME: experiment with smaller sizes -#define HYPERCALL_START 1UL*MB -#define HYPERCALL_END 2UL*MB - -#define FW_HYPERCALL_BASE_PADDR HYPERCALL_START -#define FW_HYPERCALL_END_PADDR HYPERCALL_END +/* Map: + Index Addr + 0x0000-0x000f 0x0000-0x00ff : unused + 0x0010-0x001f 0x0100-0x01ff : EFI + 0x0080-0x008f 0x0800-0x08ff : PAL/SAL + 0x0090-0x009f 0x0900-0x09ff : FPSWA +*/ +#define FW_HYPERCALL_BASE_PADDR 0x0000UL +#define FW_HYPERCALL_END_PADDR 0X1000UL #define FW_HYPERCALL_PADDR(index) (FW_HYPERCALL_BASE_PADDR + (16UL * index)) /* Hypercalls number have a low part and a high part. @@ -91,16 +90,16 @@ */ /* these are indexes into the runtime services table */ -#define FW_HYPERCALL_EFI_GET_TIME_INDEX 0UL -#define FW_HYPERCALL_EFI_SET_TIME_INDEX 1UL -#define FW_HYPERCALL_EFI_GET_WAKEUP_TIME_INDEX 2UL -#define FW_HYPERCALL_EFI_SET_WAKEUP_TIME_INDEX 3UL -#define FW_HYPERCALL_EFI_SET_VIRTUAL_ADDRESS_MAP_INDEX 4UL -#define FW_HYPERCALL_EFI_GET_VARIABLE_INDEX 5UL -#define FW_HYPERCALL_EFI_GET_NEXT_VARIABLE_INDEX 6UL -#define FW_HYPERCALL_EFI_SET_VARIABLE_INDEX 7UL -#define FW_HYPERCALL_EFI_GET_NEXT_HIGH_MONO_COUNT_INDEX 8UL -#define FW_HYPERCALL_EFI_RESET_SYSTEM_INDEX 9UL +#define FW_HYPERCALL_EFI_GET_TIME_INDEX 0x10UL +#define FW_HYPERCALL_EFI_SET_TIME_INDEX 0x11UL +#define FW_HYPERCALL_EFI_GET_WAKEUP_TIME_INDEX 0x12UL +#define FW_HYPERCALL_EFI_SET_WAKEUP_TIME_INDEX 0x13UL +#define FW_HYPERCALL_EFI_SET_VIRTUAL_ADDRESS_MAP_INDEX 0x14UL +#define FW_HYPERCALL_EFI_GET_VARIABLE_INDEX 0x15UL +#define FW_HYPERCALL_EFI_GET_NEXT_VARIABLE_INDEX 0x16UL +#define FW_HYPERCALL_EFI_SET_VARIABLE_INDEX 0x17UL +#define FW_HYPERCALL_EFI_GET_NEXT_HIGH_MONO_COUNT_INDEX 0x18UL +#define FW_HYPERCALL_EFI_RESET_SYSTEM_INDEX 0x19UL /* these are hypercall numbers */ #define FW_HYPERCALL_EFI_CALL 0x300UL From 94f21d01c45524c9f09972624fb9aafc9d90dd25 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Fri, 25 Aug 2006 16:21:39 -0600 Subject: [PATCH 38/58] [IA64] replace lost EFI_RESERVED_TYPE dom0 passthrough Some systems (HP Superdome in particular) place ACPI tables in reserved memory regions, so we have to pass it through to dom0. Signed-off-by: Alex Williamson --- xen/arch/ia64/xen/dom_fw.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xen/arch/ia64/xen/dom_fw.c b/xen/arch/ia64/xen/dom_fw.c index 0296794722..6e174f46f6 100644 --- a/xen/arch/ia64/xen/dom_fw.c +++ b/xen/arch/ia64/xen/dom_fw.c @@ -783,6 +783,8 @@ dom_fw_init(struct domain *d, dom_fw_dom0_passthrough, &arg); efi_memmap_walk_type(EFI_ACPI_MEMORY_NVS, dom_fw_dom0_passthrough, &arg); + efi_memmap_walk_type(EFI_RESERVED_TYPE, + dom_fw_dom0_passthrough, &arg); efi_memmap_walk_type(EFI_MEMORY_MAPPED_IO, dom_fw_dom0_passthrough, &arg); efi_memmap_walk_type(EFI_MEMORY_MAPPED_IO_PORT_SPACE, From f8d89b0e3a5ac65ec95f9b0b1b867fc30d274fc6 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Sun, 27 Aug 2006 10:25:39 -0600 Subject: [PATCH 39/58] [IA64] Fixes for dom0_ops changes Fix typo and update op names Signed-off-by: Alex Williamson --- xen/arch/ia64/xen/domain.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index 44ece09e05..699bd6bff7 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -615,7 +615,7 @@ domain_set_shared_info_va (unsigned long va) /* Transfer and clear the shadow bitmap in 1kB chunks for L1 cache. */ #define SHADOW_COPY_CHUNK (1024 / sizeof (unsigned long)) -int shadow_mode_control(struct domain *d, xen_domctl_shadow_ops_t *sc) +int shadow_mode_control(struct domain *d, xen_domctl_shadow_op_t *sc) { unsigned int op = sc->op; int rc = 0; @@ -740,10 +740,10 @@ int shadow_mode_control(struct domain *d, xen_domctl_shadow_ops_t *sc) } break; } - case DOM0_SHADOW_CONTROL_OP_GET_ALLOCATION: + case XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION: sc->mb = 0; break; - case DOM0_SHADOW_CONTROL_OP_SET_ALLOCATION: + case XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION: if (sc->mb > 0) { BUG(); rc = -ENOMEM; From 37a5d33b0e50c87ef48d481c454cd83d3785f5d1 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Mon, 28 Aug 2006 13:11:17 -0600 Subject: [PATCH 40/58] [IA64] Modify destroy code for PV-on-HVM on IPF Signed-off-by: Tsunehisa Doi Signed-off-by: Tomonari Horikoshi --- xen/arch/ia64/xen/domain.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index 699bd6bff7..5eca64e9a3 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -400,8 +400,16 @@ fail_nomem: void arch_domain_destroy(struct domain *d) { BUG_ON(d->arch.mm.pgd != NULL); - if (d->shared_info != NULL) - free_xenheap_pages(d->shared_info, get_order_from_shift(XSI_SHIFT)); + if (d->shared_info != NULL) { + /* If this domain is domVTi, the shared_info page may + * be replaced with domheap. Then the shared_info page + * frees in relinquish_mm(). + */ + if (IS_XEN_HEAP_FRAME(virt_to_page(d->shared_info))) { + free_xenheap_pages(d->shared_info, + get_order_from_shift(XSI_SHIFT)); + } + } if (d->arch.shadow_bitmap != NULL) xfree(d->arch.shadow_bitmap); From 8c4b6d49f551c7f647217e2858959b8201bda564 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Mon, 28 Aug 2006 13:12:42 -0600 Subject: [PATCH 41/58] [IA64] Fix comment of vmx_hypercall.c Signed-off-by: Tsunehisa Doi Signed-off-by: Tomonari Horikoshi --- xen/arch/ia64/vmx/vmx_hypercall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xen/arch/ia64/vmx/vmx_hypercall.c b/xen/arch/ia64/vmx/vmx_hypercall.c index 9b566e88d3..7daaf141af 100644 --- a/xen/arch/ia64/vmx/vmx_hypercall.c +++ b/xen/arch/ia64/vmx/vmx_hypercall.c @@ -75,7 +75,7 @@ vmx_gnttab_setup_table(unsigned long frame_pa, unsigned long nr_frames) o_grant_shared = (unsigned long)d->grant_table->shared; d->grant_table->shared = (struct grant_entry *)pgaddr; - /* Copy existing grant table shared into new page */ + /* Copy existing grant table into new page */ if (o_grant_shared) { memcpy((void *)d->grant_table->shared, (void *)o_grant_shared, PAGE_SIZE * nr_frames); From 13a2578be6bfec7299ab8e4155aa388b65c04079 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Mon, 28 Aug 2006 13:14:52 -0600 Subject: [PATCH 42/58] [IA64] Remove warning message in fw_emul.c Signed-off-by: Masaki Kanno --- xen/arch/ia64/xen/fw_emul.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xen/arch/ia64/xen/fw_emul.c b/xen/arch/ia64/xen/fw_emul.c index 5b8c91cabf..cf6effd614 100644 --- a/xen/arch/ia64/xen/fw_emul.c +++ b/xen/arch/ia64/xen/fw_emul.c @@ -426,7 +426,7 @@ efi_emulate_get_variable( unsigned long attr_addr, unsigned long data_size_addr, unsigned long data_addr, IA64FAULT *fault) { - unsigned long name, vendor, attr, data_size, data; + unsigned long name, vendor, attr = 0, data_size, data; struct page_info *name_page = NULL, *vendor_page = NULL, *attr_page = NULL, *data_size_page = NULL, *data_page = NULL; From d70fb73eda107cd8336ad097684c639594615a3b Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Mon, 28 Aug 2006 13:18:36 -0600 Subject: [PATCH 43/58] [IA64] fix VTi hangs In some scenarios, xen_timer_interrupt will not set machine itm, this may make this LP not receive timer interrupt any more. Signed-off-by: Anthony Xu --- xen/arch/ia64/xen/xentime.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xen/arch/ia64/xen/xentime.c b/xen/arch/ia64/xen/xentime.c index b1d32c50ae..0ebce66c29 100644 --- a/xen/arch/ia64/xen/xentime.c +++ b/xen/arch/ia64/xen/xentime.c @@ -109,6 +109,7 @@ void xen_timer_interrupt (int irq, void *dev_id, struct pt_regs *regs) { unsigned long new_itm, old_itc; + int f_setitm = 0; #if 0 #define HEARTBEAT_FREQ 16 // period in seconds @@ -129,11 +130,12 @@ xen_timer_interrupt (int irq, void *dev_id, struct pt_regs *regs) vcpu_pend_timer(current); // ensure another timer interrupt happens even if domain doesn't vcpu_set_next_timer(current); + f_setitm = 1; } new_itm = local_cpu_data->itm_next; - if (!VMX_DOMAIN(current) && !time_after(ia64_get_itc(), new_itm)) + if (f_setitm && !time_after(ia64_get_itc(), new_itm)) return; while (1) { From aa933dc90be7038a4a226b25afced61b7a215c1a Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Mon, 28 Aug 2006 13:30:04 -0600 Subject: [PATCH 44/58] [IA64] fix warnings Signed-off-by: Tristan Gingold --- xen/arch/ia64/vmx/vmx_hypercall.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/xen/arch/ia64/vmx/vmx_hypercall.c b/xen/arch/ia64/vmx/vmx_hypercall.c index 7daaf141af..aae1c4490c 100644 --- a/xen/arch/ia64/vmx/vmx_hypercall.c +++ b/xen/arch/ia64/vmx/vmx_hypercall.c @@ -61,7 +61,8 @@ static int vmx_gnttab_setup_table(unsigned long frame_pa, unsigned long nr_frames) { struct domain *d = current->domain; - unsigned long o_grant_shared, pgaddr; + struct grant_entry *pgaddr; + unsigned long o_grant_shared; if ((nr_frames != NR_GRANT_FRAMES) || (frame_pa & (PAGE_SIZE - 1))) { return -EINVAL; @@ -73,7 +74,7 @@ vmx_gnttab_setup_table(unsigned long frame_pa, unsigned long nr_frames) } o_grant_shared = (unsigned long)d->grant_table->shared; - d->grant_table->shared = (struct grant_entry *)pgaddr; + d->grant_table->shared = pgaddr; /* Copy existing grant table into new page */ if (o_grant_shared) { @@ -92,10 +93,11 @@ vmx_setup_shared_info_page(unsigned long gpa) { VCPU *vcpu = current; struct domain *d = vcpu->domain; - unsigned long o_info, pgaddr; + unsigned long o_info; + shared_info_t *pgaddr; struct vcpu *v; - if (gpa & (PAGE_SIZE - 1)) { + if (gpa & ~PAGE_MASK) { return -EINVAL; } @@ -105,7 +107,7 @@ vmx_setup_shared_info_page(unsigned long gpa) } o_info = (u64)d->shared_info; - d->shared_info = (shared_info_t *)pgaddr; + d->shared_info = pgaddr; /* Copy existing shared info into new page */ if (o_info) { From 0a465c9a2002d5f376dfe1f37dfe61f07e37be9d Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Mon, 28 Aug 2006 13:31:35 -0600 Subject: [PATCH 45/58] [IA64] print command line of xen Signed-off-by: Akio Takebe --- xen/arch/ia64/xen/xensetup.c | 1 + 1 file changed, 1 insertion(+) diff --git a/xen/arch/ia64/xen/xensetup.c b/xen/arch/ia64/xen/xensetup.c index 05e8b8dc57..8c2140972e 100644 --- a/xen/arch/ia64/xen/xensetup.c +++ b/xen/arch/ia64/xen/xensetup.c @@ -287,6 +287,7 @@ void start_kernel(void) ia64_boot_param->initrd_size = 0; } + printk("Xen command line: %s\n", saved_command_line); /* xenheap should be in same TR-covered range with xen image */ xenheap_phys_end = xen_pstart + xenheap_size; printk("xen image pstart: 0x%lx, xenheap pend: 0x%lx\n", From 956ac933c8d41af4fa4bfa177c5a3bb8e5ca533a Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Mon, 28 Aug 2006 14:09:31 -0600 Subject: [PATCH 46/58] [IA64] fix noreboot option fix machine_hlt to support noreboot option. Signed-off-by: Akio Takebe [modified to use existing cpu_halt() function in linux-xen files] Signed-off-by: Alex Williamson --- xen/arch/ia64/linux-xen/process-linux-xen.c | 2 ++ xen/arch/ia64/xen/domain.c | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/xen/arch/ia64/linux-xen/process-linux-xen.c b/xen/arch/ia64/linux-xen/process-linux-xen.c index aaaaaca0fe..5f04985cf9 100644 --- a/xen/arch/ia64/linux-xen/process-linux-xen.c +++ b/xen/arch/ia64/linux-xen/process-linux-xen.c @@ -810,6 +810,7 @@ get_wchan (struct task_struct *p) } while (count++ < 16); return 0; } +#endif // !XEN void cpu_halt (void) @@ -834,6 +835,7 @@ cpu_halt (void) ia64_pal_halt(min_power_state); } +#ifndef XEN void machine_restart (char *restart_cmd) { diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index 5eca64e9a3..0fadeffad0 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -1123,13 +1123,15 @@ void machine_restart(char * __unused) while(1); } +extern void cpu_halt(void); + void machine_halt(void) { console_start_sync(); if (running_on_sim) printf ("machine_halt called. spinning...\n"); else - (*efi.reset_system)(EFI_RESET_SHUTDOWN,0,0,NULL); + cpu_halt(); while(1); } From 842cad9240fc6e40cef95e7a13808a301b3b06b1 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Mon, 28 Aug 2006 16:09:28 -0600 Subject: [PATCH 47/58] [IA64] separate hypercalls, acpi and EFI tables Put hypercalls, acpi and EFI tables on three separate 4KB pages. This was a stopper to use 4KB pages. Comments added and simplifications. Signed-off-by: Tristan Gingold --- xen/arch/ia64/linux-xen/efi.c | 22 - xen/arch/ia64/xen/dom_fw.c | 600 ++++++++++----------- xen/arch/ia64/xen/hypercall.c | 2 +- xen/include/asm-ia64/dom_fw.h | 14 + xen/include/asm-ia64/domain.h | 2 - xen/include/asm-ia64/linux-xen/linux/efi.h | 4 - 6 files changed, 308 insertions(+), 336 deletions(-) diff --git a/xen/arch/ia64/linux-xen/efi.c b/xen/arch/ia64/linux-xen/efi.c index a8d4e070b7..93910059cf 100644 --- a/xen/arch/ia64/linux-xen/efi.c +++ b/xen/arch/ia64/linux-xen/efi.c @@ -292,28 +292,6 @@ efi_memmap_walk_uc (efi_freemem_callback_t callback, void *arg) walk(callback, arg, EFI_MEMORY_UC); } -#ifdef XEN -void -efi_memmap_walk_type(u32 type, efi_walk_type_callback_t callback, void *arg) -{ - void *efi_map_start, *efi_map_end, *p; - efi_memory_desc_t *md; - u64 efi_desc_size; - - efi_map_start = __va(ia64_boot_param->efi_memmap); - efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; - efi_desc_size = ia64_boot_param->efi_memdesc_size; - - for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { - md = p; - if (md->type == type) { - if ((*callback)(md, arg) < 0) - return; - } - } -} -#endif - /* * Look for the PAL_CODE region reported by EFI and maps it using an * ITR to enable safe PAL calls in virtual mode. See IA-64 Processor diff --git a/xen/arch/ia64/xen/dom_fw.c b/xen/arch/ia64/xen/dom_fw.c index 6e174f46f6..97bacd1f2a 100644 --- a/xen/arch/ia64/xen/dom_fw.c +++ b/xen/arch/ia64/xen/dom_fw.c @@ -30,13 +30,6 @@ extern unsigned long running_on_sim; -/* Base of FW tables. */ -static const unsigned long dom_fw_base_mpa = FW_HYPERCALL_END_PADDR; -static unsigned long dom_fw_end_mpa; - -/* Note: two domains cannot be created simulteanously! */ -static unsigned long imva_fw_base = -1; - #define FW_VENDOR "X\0e\0n\0/\0i\0a\0\066\0\064\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" #define MAKE_MD(typ, attr, start, end) \ @@ -53,29 +46,15 @@ static unsigned long imva_fw_base = -1; #define EFI_HYPERCALL_PATCH(tgt, call) \ do { \ dom_efi_hypercall_patch(d, FW_HYPERCALL_##call##_PADDR, \ - FW_HYPERCALL_##call); \ - tables->efi_runtime.tgt = dom_pa((unsigned long) pfn); \ - *pfn++ = FW_HYPERCALL_##call##_PADDR; \ - *pfn++ = 0; \ + FW_HYPERCALL_##call, hypercalls_imva); \ + /* Descriptor address. */ \ + tables->efi_runtime.tgt = \ + FW_FIELD_MPA(func_ptrs) + 8 * pfn; \ + /* Descriptor. */ \ + tables->func_ptrs[pfn++] = FW_HYPERCALL_##call##_PADDR; \ + tables->func_ptrs[pfn++] = 0; \ } while (0) -// return domain (meta)physical address for a given imva -// this function is a call-back from dom_fw_init -static unsigned long -dom_pa(unsigned long imva) -{ - if (imva_fw_base == -1) { - printf("dom_pa: uninitialized! (spinning...)\n"); - while(1); - } - if (imva - imva_fw_base > PAGE_SIZE) { - printf("dom_pa: bad offset! imva=0x%lx, imva_fw_base=0x%lx (spinning...)\n", - imva, imva_fw_base); - while(1); - } - return dom_fw_base_mpa + (imva - imva_fw_base); -} - // allocate a page for fw // build_physmap_table() which is called by new_thread() // does for domU. @@ -90,7 +69,8 @@ assign_new_domain_page_if_dom0(struct domain *d, unsigned long mpaddr) Hypercall bundle creation **************************************************************************/ -static void build_hypercall_bundle(UINT64 *imva, UINT64 brkimm, UINT64 hypnum, UINT64 ret) +static void +build_hypercall_bundle(u64 *imva, u64 brkimm, u64 hypnum, u64 ret) { INST64_A5 slot0; INST64_I19 slot1; @@ -127,7 +107,8 @@ static void build_hypercall_bundle(UINT64 *imva, UINT64 brkimm, UINT64 hypnum, U ia64_fc(imva + 1); } -static void build_pal_hypercall_bundles(UINT64 *imva, UINT64 brkimm, UINT64 hypnum) +static void +build_pal_hypercall_bundles(u64 *imva, u64 brkimm, u64 hypnum) { extern unsigned long pal_call_stub[]; IA64_BUNDLE bundle; @@ -164,55 +145,54 @@ static void build_pal_hypercall_bundles(UINT64 *imva, UINT64 brkimm, UINT64 hypn } // builds a hypercall bundle at domain physical address -static void dom_fpswa_hypercall_patch(struct domain *d) +static void +dom_fpswa_hypercall_patch(struct domain *d, unsigned long imva) { unsigned long *entry_imva, *patch_imva; - unsigned long entry_paddr = FW_HYPERCALL_FPSWA_ENTRY_PADDR; - unsigned long patch_paddr = FW_HYPERCALL_FPSWA_PATCH_PADDR; + const unsigned long entry_paddr = FW_HYPERCALL_FPSWA_ENTRY_PADDR; + const unsigned long patch_paddr = FW_HYPERCALL_FPSWA_PATCH_PADDR; - assign_new_domain_page_if_dom0(d, entry_paddr); - assign_new_domain_page_if_dom0(d, patch_paddr); - entry_imva = domain_mpa_to_imva(d, entry_paddr); - patch_imva = domain_mpa_to_imva(d, patch_paddr); + entry_imva = (unsigned long *)(imva + entry_paddr - + FW_HYPERCALL_BASE_PADDR); + patch_imva = (unsigned long *)(imva + patch_paddr - + FW_HYPERCALL_BASE_PADDR); + /* Descriptor. */ *entry_imva++ = patch_paddr; *entry_imva = 0; + build_hypercall_bundle(patch_imva, d->arch.breakimm, FW_HYPERCALL_FPSWA, 1); } // builds a hypercall bundle at domain physical address -static void dom_efi_hypercall_patch(struct domain *d, unsigned long paddr, unsigned long hypercall) +static void +dom_efi_hypercall_patch(struct domain *d, unsigned long paddr, + unsigned long hypercall, unsigned long imva) { - unsigned long *imva; - - assign_new_domain_page_if_dom0(d, paddr); - imva = domain_mpa_to_imva(d, paddr); - build_hypercall_bundle(imva, d->arch.breakimm, hypercall, 1); + build_hypercall_bundle((u64 *)(imva + paddr - FW_HYPERCALL_BASE_PADDR), + d->arch.breakimm, hypercall, 1); } // builds a hypercall bundle at domain physical address -static void dom_fw_hypercall_patch(struct domain *d, unsigned long paddr, unsigned long hypercall,unsigned long ret) +static void +dom_fw_hypercall_patch(struct domain *d, unsigned long paddr, + unsigned long hypercall,unsigned long ret, + unsigned long imva) { - unsigned long *imva; - - assign_new_domain_page_if_dom0(d, paddr); - imva = domain_mpa_to_imva(d, paddr); - build_hypercall_bundle(imva, d->arch.breakimm, hypercall, ret); + build_hypercall_bundle((u64 *)(imva + paddr - FW_HYPERCALL_BASE_PADDR), + d->arch.breakimm, hypercall, ret); } -static void dom_fw_pal_hypercall_patch(struct domain *d, unsigned long paddr) +static void +dom_fw_pal_hypercall_patch(struct domain *d, unsigned long paddr, + unsigned long imva) { - unsigned long *imva; - - assign_new_domain_page_if_dom0(d, paddr); - imva = domain_mpa_to_imva(d, paddr); - build_pal_hypercall_bundles(imva, d->arch.breakimm, - FW_HYPERCALL_PAL_CALL); + build_pal_hypercall_bundles((u64*)(imva + paddr - + FW_HYPERCALL_BASE_PADDR), + d->arch.breakimm, FW_HYPERCALL_PAL_CALL); } -/* the following heavily leveraged from linux/arch/ia64/hp/sim/fw-emu.c */ - static inline void print_md(efi_memory_desc_t *md) { @@ -311,6 +291,8 @@ struct fake_acpi_tables { u8 pm1a_cnt_blk[1]; u8 pm_tmr_blk[4]; }; +#define ACPI_TABLE_MPA(field) \ + FW_ACPI_BASE_PADDR + offsetof(struct fake_acpi_tables, field); /* Create enough of an ACPI structure to make the guest OS ACPI happy. */ static void @@ -340,8 +322,8 @@ dom_fw_fake_acpi(struct domain *d, struct fake_acpi_tables *tables) xsdt->asl_compiler_revision = (xen_major_version() << 16) | xen_minor_version(); - xsdt->table_offset_entry[0] = dom_pa((unsigned long) fadt); - tables->madt_ptr = dom_pa((unsigned long) madt); + xsdt->table_offset_entry[0] = ACPI_TABLE_MPA(fadt); + tables->madt_ptr = ACPI_TABLE_MPA(madt); xsdt->checksum = generate_acpi_checksum(xsdt, xsdt->length); @@ -359,8 +341,8 @@ dom_fw_fake_acpi(struct domain *d, struct fake_acpi_tables *tables) facs->version = 1; facs->length = sizeof(struct facs_descriptor_rev2); - fadt->xfirmware_ctrl = dom_pa((unsigned long) facs); - fadt->Xdsdt = dom_pa((unsigned long) dsdt); + fadt->xfirmware_ctrl = ACPI_TABLE_MPA(facs); + fadt->Xdsdt = ACPI_TABLE_MPA(dsdt); /* * All of the below FADT entries are filled it to prevent warnings @@ -370,15 +352,15 @@ dom_fw_fake_acpi(struct domain *d, struct fake_acpi_tables *tables) fadt->pm1_evt_len = 4; fadt->xpm1a_evt_blk.address_space_id = ACPI_ADR_SPACE_SYSTEM_MEMORY; fadt->xpm1a_evt_blk.register_bit_width = 8; - fadt->xpm1a_evt_blk.address = dom_pa((unsigned long) &tables->pm1a_evt_blk); + fadt->xpm1a_evt_blk.address = ACPI_TABLE_MPA(pm1a_evt_blk); fadt->pm1_cnt_len = 1; fadt->xpm1a_cnt_blk.address_space_id = ACPI_ADR_SPACE_SYSTEM_MEMORY; fadt->xpm1a_cnt_blk.register_bit_width = 8; - fadt->xpm1a_cnt_blk.address = dom_pa((unsigned long) &tables->pm1a_cnt_blk); + fadt->xpm1a_cnt_blk.address = ACPI_TABLE_MPA(pm1a_cnt_blk); fadt->pm_tm_len = 4; fadt->xpm_tmr_blk.address_space_id = ACPI_ADR_SPACE_SYSTEM_MEMORY; fadt->xpm_tmr_blk.register_bit_width = 8; - fadt->xpm_tmr_blk.address = dom_pa((unsigned long) &tables->pm_tmr_blk); + fadt->xpm_tmr_blk.address = ACPI_TABLE_MPA(pm_tmr_blk); fadt->checksum = generate_acpi_checksum(fadt, fadt->length); @@ -387,7 +369,7 @@ dom_fw_fake_acpi(struct domain *d, struct fake_acpi_tables *tables) strcpy(rsdp->oem_id, "XEN"); rsdp->revision = 2; /* ACPI 2.0 includes XSDT */ rsdp->length = sizeof(struct acpi20_table_rsdp); - rsdp->xsdt_address = dom_pa((unsigned long) xsdt); + rsdp->xsdt_address = ACPI_TABLE_MPA(xsdt); rsdp->checksum = generate_acpi_checksum(rsdp, ACPI_RSDP_CHECKSUM_LENGTH); @@ -462,89 +444,6 @@ dom_fw_fake_acpi(struct domain *d, struct fake_acpi_tables *tables) return; } -struct dom0_passthrough_arg { - struct domain* d; - int flags; - efi_memory_desc_t *md; - int* i; -}; - -static int -dom_fw_dom0_passthrough(efi_memory_desc_t *md, void *arg__) -{ - struct dom0_passthrough_arg* arg = (struct dom0_passthrough_arg*)arg__; - unsigned long paddr; - struct domain* d = arg->d; - u64 start = md->phys_addr; - u64 size = md->num_pages << EFI_PAGE_SHIFT; - - if (md->type == EFI_MEMORY_MAPPED_IO || - md->type == EFI_MEMORY_MAPPED_IO_PORT_SPACE) { - - //XXX some machine has large mmio area whose size is about several TB. - // It requires impractical memory to map such a huge region - // to a domain. - // For now we don't map it, but later we must fix this. - if (md->type == EFI_MEMORY_MAPPED_IO && (size > 0x100000000UL)) - return 0; - - paddr = assign_domain_mmio_page(d, start, size); - } else - paddr = assign_domain_mach_page(d, start, size, arg->flags); - - BUG_ON(md->type != EFI_RUNTIME_SERVICES_CODE && - md->type != EFI_RUNTIME_SERVICES_DATA && - md->type != EFI_ACPI_RECLAIM_MEMORY && - md->type != EFI_ACPI_MEMORY_NVS && - md->type != EFI_RESERVED_TYPE && - md->type != EFI_MEMORY_MAPPED_IO && - md->type != EFI_MEMORY_MAPPED_IO_PORT_SPACE); - - arg->md->type = md->type; - arg->md->pad = 0; - arg->md->phys_addr = paddr; - arg->md->virt_addr = 0; - arg->md->num_pages = md->num_pages; - arg->md->attribute = md->attribute; - - (*arg->i)++; - arg->md++; - return 0; -} - -/* - * Create dom0 MDT entries for conventional memory below 1MB. Without - * this Linux will assume VGA is present because 0xA0000 will always - * be either a hole in the MDT or an I/O region via the passthrough. - */ -static int -dom_fw_dom0_lowmem(efi_memory_desc_t *md, void *arg__) -{ - struct dom0_passthrough_arg* arg = (struct dom0_passthrough_arg*)arg__; - u64 end = min(ONE_MB, md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)); - - BUG_ON(md->type != EFI_CONVENTIONAL_MEMORY); - - /* Avoid firmware and hypercall area. - We know they are 0-based. */ - if (end < dom_fw_end_mpa || md->phys_addr >= ONE_MB) - return 0; - if (md->phys_addr < dom_fw_end_mpa) - md->phys_addr = dom_fw_end_mpa; - - arg->md->type = md->type; - arg->md->pad = 0; - arg->md->phys_addr = md->phys_addr; - arg->md->virt_addr = 0; - arg->md->num_pages = (end - md->phys_addr) >> EFI_PAGE_SHIFT; - arg->md->attribute = md->attribute; - - (*arg->i)++; - arg->md++; - - return 0; -} - static int efi_mdt_cmp(const void *a, const void *b) { @@ -583,18 +482,204 @@ struct fw_tables { unsigned long func_ptrs[2*NFUNCPTRS]; struct xen_sal_data sal_data; unsigned char fw_vendor[sizeof(FW_VENDOR)]; - - struct fake_acpi_tables acpi_tables; }; +#define FW_FIELD_MPA(field) \ + FW_TABLES_BASE_PADDR + offsetof(struct fw_tables, field) + +/* Complete the dom0 memmap. */ +static int +complete_dom0_memmap(struct domain *d, + struct fw_tables *tables, + unsigned long maxmem, + int num_mds) +{ + efi_memory_desc_t *md; + u64 addr; + int j; + void *efi_map_start, *efi_map_end, *p; + u64 efi_desc_size; + int i; + + /* Walk through all MDT entries. + Copy all interesting entries. */ + efi_map_start = __va(ia64_boot_param->efi_memmap); + efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size; + efi_desc_size = ia64_boot_param->efi_memdesc_size; + + for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { + const efi_memory_desc_t *md = p; + efi_memory_desc_t *dom_md = &tables->efi_memmap[num_mds]; + u64 start = md->phys_addr; + u64 size = md->num_pages << EFI_PAGE_SHIFT; + u64 end = start + size; + + switch (md->type) { + case EFI_RUNTIME_SERVICES_CODE: + case EFI_RUNTIME_SERVICES_DATA: + case EFI_ACPI_RECLAIM_MEMORY: + case EFI_ACPI_MEMORY_NVS: + case EFI_RESERVED_TYPE: + /* Map into dom0 - All these are writable. */ + assign_domain_mach_page(d, start, size, + ASSIGN_writable); + /* Fall-through. */ + case EFI_MEMORY_MAPPED_IO: + /* Will be mapped with ioremap. */ + /* Copy descriptor. */ + *dom_md = *md; + dom_md->virt_addr = 0; + num_mds++; + break; + + case EFI_MEMORY_MAPPED_IO_PORT_SPACE: + /* Map into dom0. */ + assign_domain_mmio_page(d, start, size); + /* Copy descriptor. */ + *dom_md = *md; + dom_md->virt_addr = 0; + num_mds++; + break; + + case EFI_CONVENTIONAL_MEMORY: + case EFI_LOADER_CODE: + case EFI_LOADER_DATA: + case EFI_BOOT_SERVICES_CODE: + case EFI_BOOT_SERVICES_DATA: + /* Create dom0 MDT entries for conventional memory + below 1MB. Without this Linux will assume VGA is + present because 0xA0000 will always be either a hole + in the MDT or an I/O region via the passthrough. */ + + end = min(ONE_MB, end); + + /* Avoid firmware and hypercall area. + We know they are 0-based. */ + if (end < FW_END_PADDR || start >= ONE_MB) + break; + if (start < FW_END_PADDR) + start = FW_END_PADDR; + + dom_md->type = EFI_CONVENTIONAL_MEMORY; + dom_md->phys_addr = start; + dom_md->virt_addr = 0; + dom_md->num_pages = (end - start) >> EFI_PAGE_SHIFT; + dom_md->attribute = md->attribute; + num_mds++; + break; + + case EFI_UNUSABLE_MEMORY: + case EFI_PAL_CODE: + /* Discard. */ + break; + + default: + /* Print a warning but continue. */ + printf("complete_dom0_memmap: warning: " + "unhandled MDT entry type %u\n", md->type); + } + } + BUG_ON(num_mds > NUM_MEM_DESCS); + + sort(tables->efi_memmap, num_mds, sizeof(efi_memory_desc_t), + efi_mdt_cmp, NULL); + + /* find gaps and fill them with conventional memory */ + i = num_mds; + for (j = 0; j < num_mds; j++) { + unsigned long end; + unsigned long next_start; + + md = &tables->efi_memmap[j]; + end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT); + + if (j + 1 < num_mds) { + efi_memory_desc_t* next_md; + next_md = &tables->efi_memmap[j + 1]; + next_start = next_md->phys_addr; + + /* Have just been sorted. */ + BUG_ON(end > next_start); + + /* No room for memory! */ + if (end == next_start) + continue; + + if (next_start > maxmem) + next_start = maxmem; + } + else + next_start = maxmem; + + /* Avoid "legacy" low memory addresses + and the HYPERCALL area. */ + if (end < ONE_MB) + end = ONE_MB; + + // clip the range and align to PAGE_SIZE + next_start = next_start & PAGE_MASK; + end = PAGE_ALIGN(end); + + /* No room for memory. */ + if (end >= next_start) + continue; + + MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB, + end, next_start); + + if (next_start >= maxmem) + break; + } + num_mds = i; + BUG_ON(num_mds > NUM_MEM_DESCS); + sort(tables->efi_memmap, num_mds, sizeof(efi_memory_desc_t), + efi_mdt_cmp, NULL); + + // dom0 doesn't need build_physmap_table() + // see arch_set_info_guest() + // instead we allocate pages manually. + for (i = 0; i < num_mds; i++) { + md = &tables->efi_memmap[i]; + if (md->phys_addr > maxmem) + break; + + if (md->type == EFI_LOADER_DATA || + md->type == EFI_PAL_CODE || + md->type == EFI_CONVENTIONAL_MEMORY) { + unsigned long start = md->phys_addr & PAGE_MASK; + unsigned long end = md->phys_addr + + (md->num_pages << EFI_PAGE_SHIFT); + + if (end == start) { + /* md->num_pages = 0 is allowed. */ + continue; + } + if (end > (max_page << PAGE_SHIFT)) + end = (max_page << PAGE_SHIFT); + + for (addr = start; addr < end; addr += PAGE_SIZE) + assign_new_domain0_page(d, addr); + } + } + // Map low-memory holes & unmapped MMIO for legacy drivers + for (addr = 0; addr < ONE_MB; addr += PAGE_SIZE) { + if (domain_page_mapped(d, addr)) + continue; + + if (efi_mmio(addr, PAGE_SIZE)) + assign_domain_mmio_page(d, addr, PAGE_SIZE); + } + return num_mds; +} static void dom_fw_init(struct domain *d, struct ia64_boot_param *bp, struct fw_tables *tables, + unsigned long hypercalls_imva, unsigned long maxmem) { efi_memory_desc_t *md; - unsigned long *pfn; + unsigned long pfn; unsigned char checksum; char *cp; int num_mds, i; @@ -612,20 +697,18 @@ dom_fw_init(struct domain *d, tables->efi_systab.hdr.headersize = sizeof(tables->efi_systab.hdr); memcpy(tables->fw_vendor,FW_VENDOR,sizeof(FW_VENDOR)); - tables->efi_systab.fw_vendor = - dom_pa((unsigned long)tables->fw_vendor); + tables->efi_systab.fw_vendor = FW_FIELD_MPA(fw_vendor); tables->efi_systab.fw_revision = 1; - tables->efi_systab.runtime = - (void *)dom_pa((unsigned long)&tables->efi_runtime); + tables->efi_systab.runtime = (void *)FW_FIELD_MPA(efi_runtime); tables->efi_systab.nr_tables = NUM_EFI_SYS_TABLES; - tables->efi_systab.tables = dom_pa((unsigned long)tables->efi_tables); + tables->efi_systab.tables = FW_FIELD_MPA(efi_tables); /* EFI runtime. */ tables->efi_runtime.hdr.signature = EFI_RUNTIME_SERVICES_SIGNATURE; tables->efi_runtime.hdr.revision = EFI_RUNTIME_SERVICES_REVISION; tables->efi_runtime.hdr.headersize = sizeof(tables->efi_runtime.hdr); - pfn = tables->func_ptrs; + pfn = 0; EFI_HYPERCALL_PATCH(get_time,EFI_GET_TIME); EFI_HYPERCALL_PATCH(set_time,EFI_SET_TIME); EFI_HYPERCALL_PATCH(get_wakeup_time,EFI_GET_WAKEUP_TIME); @@ -641,14 +724,16 @@ dom_fw_init(struct domain *d, /* System tables. */ tables->efi_tables[0].guid = SAL_SYSTEM_TABLE_GUID; - tables->efi_tables[0].table = - dom_pa((unsigned long)&tables->sal_systab); + tables->efi_tables[0].table = FW_FIELD_MPA(sal_systab); for (i = 1; i < NUM_EFI_SYS_TABLES; i++) { tables->efi_tables[i].guid = NULL_GUID; tables->efi_tables[i].table = 0; } i = 1; if (d == dom0) { + /* Write messages to the console. */ + touch_acpi_table(); + printf("Domain0 EFI passthrough:"); if (efi.mps) { tables->efi_tables[i].guid = MPS_TABLE_GUID; @@ -657,8 +742,6 @@ dom_fw_init(struct domain *d, i++; } - touch_acpi_table(); - if (efi.acpi20) { tables->efi_tables[i].guid = ACPI_20_TABLE_GUID; tables->efi_tables[i].table = __pa(efi.acpi20); @@ -687,11 +770,8 @@ dom_fw_init(struct domain *d, } else { printf("DomainU EFI build up:"); - dom_fw_fake_acpi(d, &tables->acpi_tables); - tables->efi_tables[i].guid = ACPI_20_TABLE_GUID; - tables->efi_tables[i].table = - dom_pa((unsigned long) &tables->acpi_tables); + tables->efi_tables[i].table = FW_ACPI_BASE_PADDR; printf(" ACPI 2.0=0x%lx",tables->efi_tables[i].table); i++; printf("\n"); @@ -707,13 +787,15 @@ dom_fw_init(struct domain *d, strcpy((char *)tables->sal_systab.oem_id, "Xen/ia64"); strcpy((char *)tables->sal_systab.product_id, "Xen/ia64"); - /* fill in an entry point: */ + /* PAL entry point: */ tables->sal_ed.type = SAL_DESC_ENTRY_POINT; tables->sal_ed.pal_proc = FW_HYPERCALL_PAL_CALL_PADDR; - dom_fw_pal_hypercall_patch(d, tables->sal_ed.pal_proc); + dom_fw_pal_hypercall_patch(d, tables->sal_ed.pal_proc, + hypercalls_imva); + /* SAL entry point. */ tables->sal_ed.sal_proc = FW_HYPERCALL_SAL_CALL_PADDR; dom_fw_hypercall_patch(d, tables->sal_ed.sal_proc, - FW_HYPERCALL_SAL_CALL, 1); + FW_HYPERCALL_SAL_CALL, 1, hypercalls_imva); tables->sal_ed.gp = 0; /* will be ignored */ /* Fill an AP wakeup descriptor. */ @@ -730,13 +812,12 @@ dom_fw_init(struct domain *d, tables->sal_systab.checksum = -checksum; /* SAL return point. */ - d->arch.sal_return_addr = FW_HYPERCALL_SAL_RETURN_PADDR; - dom_fw_hypercall_patch (d, d->arch.sal_return_addr, - FW_HYPERCALL_SAL_RETURN, 0); + dom_fw_hypercall_patch(d, FW_HYPERCALL_SAL_RETURN_PADDR, + FW_HYPERCALL_SAL_RETURN, 0, hypercalls_imva); /* Fill in the FPSWA interface: */ tables->fpswa_inf.revision = fpswa_interface->revision; - dom_fpswa_hypercall_patch(d); + dom_fpswa_hypercall_patch(d, hypercalls_imva); tables->fpswa_inf.fpswa = (void *)FW_HYPERCALL_FPSWA_ENTRY_PADDR; i = 0; /* Used by MAKE_MD */ @@ -745,14 +826,18 @@ dom_fw_init(struct domain *d, MAKE_MD(EFI_PAL_CODE,EFI_MEMORY_WB|EFI_MEMORY_RUNTIME, FW_HYPERCALL_BASE_PADDR, FW_HYPERCALL_END_PADDR); - /* Create dom0/domu md entry for fw tables area */ + /* Create dom0/domu md entry for fw and cpi tables area. */ + MAKE_MD(EFI_ACPI_MEMORY_NVS, EFI_MEMORY_WB | EFI_MEMORY_RUNTIME, + FW_ACPI_BASE_PADDR, FW_ACPI_END_PADDR); MAKE_MD(EFI_RUNTIME_SERVICES_DATA, EFI_MEMORY_WB | EFI_MEMORY_RUNTIME, - dom_fw_base_mpa, dom_fw_end_mpa); + FW_TABLES_BASE_PADDR, FW_TABLES_END_PADDR); if (d != dom0 || running_on_sim) { + /* DomU (or hp-ski). + Create a continuous memory area. */ /* Memory. */ MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB, - dom_fw_end_mpa, maxmem); + FW_END_PADDR, maxmem); /* Create an entry for IO ports. */ MAKE_MD(EFI_MEMORY_MAPPED_IO_PORT_SPACE, EFI_MEMORY_UC, @@ -761,128 +846,10 @@ dom_fw_init(struct domain *d, num_mds = i; } else { - /* pass through the I/O port space */ - struct dom0_passthrough_arg arg; - u64 addr; - int j; - - /* Fill from real entries. */ - arg.md = &tables->efi_memmap[i]; - arg.i = &i; - arg.d = d; - arg.flags = ASSIGN_writable; - //XXX Is this needed? - efi_memmap_walk_type(EFI_RUNTIME_SERVICES_CODE, - dom_fw_dom0_passthrough, &arg); - // for ACPI table. - arg.flags = ASSIGN_readonly; - efi_memmap_walk_type(EFI_RUNTIME_SERVICES_DATA, - dom_fw_dom0_passthrough, &arg); - arg.flags = ASSIGN_writable; - efi_memmap_walk_type(EFI_ACPI_RECLAIM_MEMORY, - dom_fw_dom0_passthrough, &arg); - efi_memmap_walk_type(EFI_ACPI_MEMORY_NVS, - dom_fw_dom0_passthrough, &arg); - efi_memmap_walk_type(EFI_RESERVED_TYPE, - dom_fw_dom0_passthrough, &arg); - efi_memmap_walk_type(EFI_MEMORY_MAPPED_IO, - dom_fw_dom0_passthrough, &arg); - efi_memmap_walk_type(EFI_MEMORY_MAPPED_IO_PORT_SPACE, - dom_fw_dom0_passthrough, &arg); - efi_memmap_walk_type(EFI_CONVENTIONAL_MEMORY, - dom_fw_dom0_lowmem, &arg); - num_mds = i; - - sort(tables->efi_memmap, num_mds, sizeof(efi_memory_desc_t), - efi_mdt_cmp, NULL); - - // find gaps and fill them with conventional memory - for (j = 0; j < num_mds; j++) { - unsigned long end; - unsigned long next_start; - - md = &tables->efi_memmap[j]; - end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT); - - if (j + 1 < num_mds) { - efi_memory_desc_t* next_md; - next_md = &tables->efi_memmap[j+1]; - next_start = next_md->phys_addr; - - /* Have just been sorted. */ - BUG_ON(end > next_start); - - /* No room for memory! */ - if (end == next_start) - continue; - - if (next_start > maxmem) - next_start = maxmem; - } - else - next_start = maxmem; - - /* Avoid "legacy" low memory addresses and - the HYPERCALL area. */ - if (end < ONE_MB) - end = ONE_MB; - - // clip the range and align to PAGE_SIZE - next_start = next_start & PAGE_MASK; - end = PAGE_ALIGN(end); - - /* No room for memory. */ - if (end >= next_start) - continue; - - MAKE_MD(EFI_CONVENTIONAL_MEMORY, EFI_MEMORY_WB, - end, next_start); - - if (next_start >= maxmem) - break; - } - num_mds = i; - BUG_ON(num_mds > NUM_MEM_DESCS); - sort(tables->efi_memmap, num_mds, sizeof(efi_memory_desc_t), - efi_mdt_cmp, NULL); - - // dom0 doesn't need build_physmap_table() - // see arch_set_info_guest() - // instead we allocate pages manually. - for (i = 0; i < num_mds; i++) { - md = &tables->efi_memmap[i]; - if (md->phys_addr > maxmem) - break; - - if (md->type == EFI_LOADER_DATA || - md->type == EFI_PAL_CODE || - md->type == EFI_CONVENTIONAL_MEMORY) { - unsigned long start = md->phys_addr & PAGE_MASK; - unsigned long end = md->phys_addr + - (md->num_pages << EFI_PAGE_SHIFT); - - if (end == start) { - // md->num_pages = 0 is allowed. - continue; - } - if (end > (max_page << PAGE_SHIFT)) - end = (max_page << PAGE_SHIFT); - - for (addr = start; - addr < end; - addr += PAGE_SIZE) { - assign_new_domain0_page(d, addr); - } - } - } - // Map low-memory holes & unmapped MMIO for legacy drivers - for (addr = 0; addr < ONE_MB; addr += PAGE_SIZE) { - if (domain_page_mapped(d, addr)) - continue; - - if (efi_mmio(addr, PAGE_SIZE)) - assign_domain_mmio_page(d, addr, PAGE_SIZE); - } + /* Dom0. + We must preserve ACPI data from real machine, + as well as IO areas. */ + num_mds = complete_dom0_memmap(d, tables, maxmem, i); } /* Display memmap. */ @@ -890,8 +857,8 @@ dom_fw_init(struct domain *d, print_md(&tables->efi_memmap[i]); /* Fill boot_param */ - bp->efi_systab = dom_pa((unsigned long)&tables->efi_systab); - bp->efi_memmap = dom_pa((unsigned long)tables->efi_memmap); + bp->efi_systab = FW_FIELD_MPA(efi_systab); + bp->efi_memmap = FW_FIELD_MPA(efi_memmap); bp->efi_memmap_size = num_mds * sizeof(efi_memory_desc_t); bp->efi_memdesc_size = sizeof(efi_memory_desc_t); bp->efi_memdesc_version = EFI_MEMDESC_VERSION; @@ -900,25 +867,44 @@ dom_fw_init(struct domain *d, bp->console_info.num_rows = 25; bp->console_info.orig_x = 0; bp->console_info.orig_y = 24; - bp->fpswa = dom_pa((unsigned long) &tables->fpswa_inf); + bp->fpswa = FW_FIELD_MPA(fpswa_inf); } void dom_fw_setup(struct domain *d, unsigned long bp_mpa, unsigned long maxmem) { struct ia64_boot_param *bp; + unsigned long imva_tables_base; + unsigned long imva_hypercall_base; - /* Note: 4KB < size < 8KB. */ - BUILD_BUG_ON(sizeof(struct fw_tables) > PAGE_SIZE); + BUILD_BUG_ON(sizeof(struct fw_tables) > + (FW_TABLES_END_PADDR - FW_TABLES_BASE_PADDR)); - dom_fw_end_mpa = PAGE_ALIGN(dom_fw_base_mpa + sizeof(struct fw_tables)); + BUILD_BUG_ON(sizeof(struct fake_acpi_tables) > + (FW_ACPI_END_PADDR - FW_ACPI_BASE_PADDR)); /* Create page for hypercalls. */ - assign_new_domain_page_if_dom0(d, dom_fw_base_mpa); - imva_fw_base = (unsigned long)domain_mpa_to_imva(d, dom_fw_base_mpa); + assign_new_domain_page_if_dom0(d, FW_HYPERCALL_BASE_PADDR); + imva_hypercall_base = (unsigned long)domain_mpa_to_imva + (d, FW_HYPERCALL_BASE_PADDR); + + /* Create page for acpi tables. */ + if (d != dom0) { + void *imva; + + assign_new_domain_page_if_dom0(d, FW_ACPI_BASE_PADDR); + imva = domain_mpa_to_imva (d, FW_ACPI_BASE_PADDR); + dom_fw_fake_acpi(d, (struct fake_acpi_tables *)imva); + } + + /* Create page for FW tables. */ + assign_new_domain_page_if_dom0(d, FW_TABLES_BASE_PADDR); + imva_tables_base = (unsigned long)domain_mpa_to_imva + (d, FW_TABLES_BASE_PADDR); /* Create page for boot_param. */ assign_new_domain_page_if_dom0(d, bp_mpa); bp = domain_mpa_to_imva(d, bp_mpa); - dom_fw_init(d, bp, (struct fw_tables *)imva_fw_base, maxmem); + dom_fw_init(d, bp, (struct fw_tables *)imva_tables_base, + imva_hypercall_base, maxmem); } diff --git a/xen/arch/ia64/xen/hypercall.c b/xen/arch/ia64/xen/hypercall.c index 4a9ac5b5ec..1f915bb532 100644 --- a/xen/arch/ia64/xen/hypercall.c +++ b/xen/arch/ia64/xen/hypercall.c @@ -172,7 +172,7 @@ fw_hypercall_ipi (struct pt_regs *regs) vcpu_init_regs (targ); vcpu_regs (targ)->cr_iip = d->arch.sal_data->boot_rdv_ip; vcpu_regs (targ)->r1 = d->arch.sal_data->boot_rdv_r1; - vcpu_regs (targ)->b0 = d->arch.sal_return_addr; + vcpu_regs (targ)->b0 = FW_HYPERCALL_SAL_RETURN_PADDR; if (test_and_clear_bit(_VCPUF_down, &targ->vcpu_flags)) { diff --git a/xen/include/asm-ia64/dom_fw.h b/xen/include/asm-ia64/dom_fw.h index 579dfd384a..841ea9e200 100644 --- a/xen/include/asm-ia64/dom_fw.h +++ b/xen/include/asm-ia64/dom_fw.h @@ -7,6 +7,11 @@ #include +/* Portion of guest physical memory space reserved for PAL/SAL/EFI/ACPI + data and code. */ +#define FW_BASE_PADDR 0x0000UL +#define FW_END_PADDR 0x3000UL + /* This is used to determined the portion of a domain's metaphysical memory space reserved for the hypercall patch table. */ /* Map: @@ -20,6 +25,15 @@ #define FW_HYPERCALL_END_PADDR 0X1000UL #define FW_HYPERCALL_PADDR(index) (FW_HYPERCALL_BASE_PADDR + (16UL * index)) +/* Base and end guest physical address of ACPI tables. */ +#define FW_ACPI_BASE_PADDR 0x1000UL +#define FW_ACPI_END_PADDR 0x2000UL + +/* Base and end guest physical address of EFI and SAL (non-ACPI) tables. */ +#define FW_TABLES_BASE_PADDR 0x2000UL +#define FW_TABLES_END_PADDR 0x3000UL + + /* Hypercalls number have a low part and a high part. The high part is the class (xen/pal/sal/efi). */ #define FW_HYPERCALL_NUM_MASK_HIGH ~0xffUL diff --git a/xen/include/asm-ia64/domain.h b/xen/include/asm-ia64/domain.h index a770df9a00..b93351c63c 100644 --- a/xen/include/asm-ia64/domain.h +++ b/xen/include/asm-ia64/domain.h @@ -118,8 +118,6 @@ struct arch_domain { /* Address of SAL emulator data */ struct xen_sal_data *sal_data; - /* SAL return point. */ - unsigned long sal_return_addr; /* Address of efi_runtime_services_t (placed in domain memory) */ void *efi_runtime; diff --git a/xen/include/asm-ia64/linux-xen/linux/efi.h b/xen/include/asm-ia64/linux-xen/linux/efi.h index 6ec3c93990..73781ec165 100644 --- a/xen/include/asm-ia64/linux-xen/linux/efi.h +++ b/xen/include/asm-ia64/linux-xen/linux/efi.h @@ -293,10 +293,6 @@ extern void *efi_get_pal_addr (void); extern void efi_map_pal_code (void); extern void efi_map_memmap(void); extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg); -#ifdef XEN -typedef int (*efi_walk_type_callback_t)(efi_memory_desc_t *md, void *arg); -extern void efi_memmap_walk_type(u32 type, efi_walk_type_callback_t callback, void *arg); -#endif extern void efi_gettimeofday (struct timespec *ts); extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */ extern u64 efi_get_iobase (void); From e012111cf592cd13154e38e061b83ec2975741f2 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Mon, 28 Aug 2006 16:16:07 -0600 Subject: [PATCH 48/58] [IA64] Modify sparse headers for PV-on-HVM/IPF Signed-off-by: Tsunehisa Doi Signed-off-by: Tomonari Horikoshi --- .../include/asm-ia64/hypercall.h | 2 ++ .../include/asm-ia64/hypervisor.h | 36 +++++++++++++++---- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h index 7d354f9f9c..8270a96ce1 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h @@ -315,7 +315,9 @@ static inline void exit_idle(void) {} }) #include +#ifdef CONFIG_XEN #include +#endif /* CONFIG_XEN */ static inline unsigned long __HYPERVISOR_ioremap(unsigned long ioaddr, unsigned long size) diff --git a/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h b/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h index a4fb434f14..f6b750ceeb 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h @@ -33,7 +33,7 @@ #ifndef __HYPERVISOR_H__ #define __HYPERVISOR_H__ -#ifndef CONFIG_XEN +#if !defined(CONFIG_XEN) && !defined(CONFIG_VMX_GUEST) #define is_running_on_xen() (0) #define HYPERVISOR_ioremap(offset, size) (offset) #else @@ -41,7 +41,7 @@ extern int running_on_xen; #define is_running_on_xen() (running_on_xen) #endif -#ifdef CONFIG_XEN +#if defined(CONFIG_XEN) || defined(CONFIG_VMX_GUEST) #include #include #include @@ -59,10 +59,9 @@ extern int running_on_xen; extern shared_info_t *HYPERVISOR_shared_info; extern start_info_t *xen_start_info; -#define is_initial_xendomain() (xen_start_info->flags & SIF_INITDOMAIN) - void force_evtchn_callback(void); +#ifndef CONFIG_VMX_GUEST /* Turn jiffies into Xen system time. XXX Implement me. */ #define jiffies_to_st(j) 0 @@ -145,10 +144,14 @@ int privcmd_mmap(struct file * file, struct vm_area_struct * vma); #define scrub_pages(_p,_n) ((void)0) #endif #define pte_mfn(_x) pte_pfn(_x) -#define __pte_ma(_x) ((pte_t) {(_x)}) #define phys_to_machine_mapping_valid(_x) (1) -#define pfn_pte_ma(_x,_y) __pte_ma(0) +#endif /* !CONFIG_VMX_GUEST */ + +#define __pte_ma(_x) ((pte_t) {(_x)}) /* unmodified use */ +#define pfn_pte_ma(_x,_y) __pte_ma(0) /* unmodified use */ + +#ifndef CONFIG_VMX_GUEST int __xen_create_contiguous_region(unsigned long vstart, unsigned int order, unsigned int address_bits); static inline int xen_create_contiguous_region(unsigned long vstart, @@ -170,6 +173,8 @@ xen_destroy_contiguous_region(unsigned long vstart, unsigned int order) __xen_destroy_contiguous_region(vstart, order); } +#endif /* !CONFIG_VMX_GUEST */ + // for netfront.c, netback.c #define MULTI_UVMFLAGS_INDEX 0 //XXX any value @@ -182,10 +187,27 @@ MULTI_update_va_mapping( mcl->result = 0; } +static inline void +MULTI_grant_table_op(multicall_entry_t *mcl, unsigned int cmd, + void *uop, unsigned int count) +{ + mcl->op = __HYPERVISOR_grant_table_op; + mcl->args[0] = cmd; + mcl->args[1] = (unsigned long)uop; + mcl->args[2] = count; +} + // for debug asmlinkage int xprintk(const char *fmt, ...); #define xprintd(fmt, ...) xprintk("%s:%d " fmt, __func__, __LINE__, \ ##__VA_ARGS__) -#endif /* CONFIG_XEN */ + +#endif /* CONFIG_XEN || CONFIG_VMX_GUEST */ + +#ifdef CONFIG_XEN_PRIVILEGED_GUEST +#define is_initial_xendomain() (xen_start_info->flags & SIF_INITDOMAIN) +#else +#define is_initial_xendomain() 0 +#endif #endif /* __HYPERVISOR_H__ */ From 2dc8f01c020c79da15dfafacf5fc11a16c62ba6a Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Tue, 29 Aug 2006 08:09:28 -0600 Subject: [PATCH 49/58] [IA64] init the hlt timer on a valid cpu and migrate Based on a patch from Anthony Xu, v->processor is not initialized in alloc_vcpu_struct() when we initialize the hlt_timer. Init the timer on the first cpu and migrate it in schedule_tail(). Signed-off-by: Alex Williamson --- xen/arch/ia64/xen/domain.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index 0fadeffad0..719af71ff2 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -122,6 +122,7 @@ void schedule_tail(struct vcpu *prev) shared_info->vcpu_info[current->vcpu_id].evtchn_upcall_mask; __ia64_per_cpu_var(current_psr_ic_addr) = (int *) (current->domain->arch.shared_info_va + XSI_PSR_IC_OFS); + migrate_timer(¤t->arch.hlt_timer, current->processor); } flush_vtlb_for_context_switch(current); } @@ -305,7 +306,8 @@ struct vcpu *alloc_vcpu_struct(struct domain *d, unsigned int vcpu_id) v->arch.last_processor = INVALID_PROCESSOR; } if (!VMX_DOMAIN(v)){ - init_timer(&v->arch.hlt_timer, hlt_timer_fn, v, v->processor); + init_timer(&v->arch.hlt_timer, hlt_timer_fn, v, + first_cpu(cpu_online_map)); } return v; From ca9a3f90912ec56591a07209b350d20194f96284 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Tue, 29 Aug 2006 09:05:46 -0600 Subject: [PATCH 50/58] [IA64] revert xen-ia64-unstable.hg 11271:c232365128cf Delete functions introduced for old PV-on-HVM on IPF. Signed-off-by: Tsunehisa Doi Signed-off-by: Tomonari Horikoshi --- xen/arch/ia64/vmx/vmx_hypercall.c | 107 ------------------------------ xen/include/public/arch-ia64.h | 11 --- 2 files changed, 118 deletions(-) diff --git a/xen/arch/ia64/vmx/vmx_hypercall.c b/xen/arch/ia64/vmx/vmx_hypercall.c index aae1c4490c..bc3c6e7cab 100644 --- a/xen/arch/ia64/vmx/vmx_hypercall.c +++ b/xen/arch/ia64/vmx/vmx_hypercall.c @@ -2,7 +2,6 @@ /* * vmx_hyparcall.c: handling hypercall from domain * Copyright (c) 2005, Intel Corporation. - * Copyright (c) 2006, Fujitsu Limited. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -18,8 +17,6 @@ * Place - Suite 330, Boston, MA 02111-1307 USA. * * Xuefei Xu (Anthony Xu) (Anthony.xu@intel.com) - * Tsunehisa Doi (Doi.Tsunehisa@jp.fujitsu.com) - * Tomonari Horikoshi (t.horikoshi@jp.fujitsu.com) */ #include @@ -37,91 +34,6 @@ #include #include #include -#include -#include - -static void -vmx_free_pages(unsigned long pgaddr, int npg) -{ - for (; npg > 0; npg--, pgaddr += PAGE_SIZE) { - /* If original page belongs to xen heap, then relinguish back - * to xen heap. Or else, leave to domain itself to decide. - */ - if (likely(IS_XEN_HEAP_FRAME(virt_to_page(pgaddr)))) { - free_domheap_page(virt_to_page(pgaddr)); - free_xenheap_page((void *)pgaddr); - } - else { - put_page(virt_to_page(pgaddr)); - } - } -} - -static int -vmx_gnttab_setup_table(unsigned long frame_pa, unsigned long nr_frames) -{ - struct domain *d = current->domain; - struct grant_entry *pgaddr; - unsigned long o_grant_shared; - - if ((nr_frames != NR_GRANT_FRAMES) || (frame_pa & (PAGE_SIZE - 1))) { - return -EINVAL; - } - - pgaddr = domain_mpa_to_imva(d, frame_pa); - if (pgaddr == NULL) { - return -EFAULT; - } - - o_grant_shared = (unsigned long)d->grant_table->shared; - d->grant_table->shared = pgaddr; - - /* Copy existing grant table into new page */ - if (o_grant_shared) { - memcpy((void *)d->grant_table->shared, - (void *)o_grant_shared, PAGE_SIZE * nr_frames); - vmx_free_pages(o_grant_shared, nr_frames); - } - else { - memset((void *)d->grant_table->shared, 0, PAGE_SIZE * nr_frames); - } - return 0; -} - -static int -vmx_setup_shared_info_page(unsigned long gpa) -{ - VCPU *vcpu = current; - struct domain *d = vcpu->domain; - unsigned long o_info; - shared_info_t *pgaddr; - struct vcpu *v; - - if (gpa & ~PAGE_MASK) { - return -EINVAL; - } - - pgaddr = domain_mpa_to_imva(d, gpa); - if (pgaddr == NULL) { - return -EFAULT; - } - - o_info = (u64)d->shared_info; - d->shared_info = pgaddr; - - /* Copy existing shared info into new page */ - if (o_info) { - memcpy((void*)d->shared_info, (void*)o_info, PAGE_SIZE); - for_each_vcpu(d, v) { - v->vcpu_info = &d->shared_info->vcpu_info[v->vcpu_id]; - } - vmx_free_pages(o_info, 1); - } - else { - memset((void *)d->shared_info, 0, PAGE_SIZE); - } - return 0; -} long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) @@ -166,25 +78,6 @@ do_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg) break; } - case HVMOP_setup_gnttab_table: - case HVMOP_setup_shared_info_page: - { - struct xen_hvm_setup a; - - if (copy_from_guest(&a, arg, 1)) - return -EFAULT; - - switch (op) { - case HVMOP_setup_gnttab_table: - printk("vmx_gnttab_setup_table: frame_pa=%#lx," - "nr_frame=%ld\n", a.arg1, a.arg2); - return vmx_gnttab_setup_table(a.arg1, a.arg2); - case HVMOP_setup_shared_info_page: - printk("vmx_setup_shared_info_page: gpa=0x%lx\n", a.arg1); - return vmx_setup_shared_info_page(a.arg1); - } - } - default: DPRINTK("Bad HVM op %ld.\n", op); rc = -ENOSYS; diff --git a/xen/include/public/arch-ia64.h b/xen/include/public/arch-ia64.h index 079e95a043..5ac98469c2 100644 --- a/xen/include/public/arch-ia64.h +++ b/xen/include/public/arch-ia64.h @@ -339,17 +339,6 @@ struct vcpu_guest_context { typedef struct vcpu_guest_context vcpu_guest_context_t; DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t); -// hvm_op expansion -#define HVMOP_setup_gnttab_table 2 -#define HVMOP_setup_shared_info_page 3 - -struct xen_hvm_setup { - unsigned long arg1; - unsigned long arg2; -}; -typedef struct xen_hvm_setup xen_hvm_setup_t; -DEFINE_XEN_GUEST_HANDLE(xen_hvm_setup_t); - // dom0 vp op #define __HYPERVISOR_ia64_dom0vp_op __HYPERVISOR_arch_0 #define IA64_DOM0VP_ioremap 0 // map io space in machine From 2894bb17210ef61bbac080a4a6b7b42222cd2479 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild.aw" Date: Tue, 29 Aug 2006 09:08:29 -0600 Subject: [PATCH 51/58] [IA64] revert xen-ia64-unstable.hg cset 11301:a19dbbe4cff5 revert arch_domain_destory() for old PV-on-HVM on IPF Signed-off-by: Tsunehisa Doi Signed-off-by: Tomonari Horikoshi --- xen/arch/ia64/xen/domain.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index 719af71ff2..2073fd52c7 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -402,16 +402,8 @@ fail_nomem: void arch_domain_destroy(struct domain *d) { BUG_ON(d->arch.mm.pgd != NULL); - if (d->shared_info != NULL) { - /* If this domain is domVTi, the shared_info page may - * be replaced with domheap. Then the shared_info page - * frees in relinquish_mm(). - */ - if (IS_XEN_HEAP_FRAME(virt_to_page(d->shared_info))) { - free_xenheap_pages(d->shared_info, - get_order_from_shift(XSI_SHIFT)); - } - } + if (d->shared_info != NULL) + free_xenheap_pages(d->shared_info, get_order_from_shift(XSI_SHIFT)); if (d->arch.shadow_bitmap != NULL) xfree(d->arch.shadow_bitmap); From 33d0648f734a5ce02d88306a386693a14f048d8a Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 30 Aug 2006 17:52:35 +0100 Subject: [PATCH 52/58] [TOOLS] Fix gdbserver build. Signed-off-by: Travis Betak --- tools/debugger/gdb/gdbbuild | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/debugger/gdb/gdbbuild b/tools/debugger/gdb/gdbbuild index 419adab61d..90cb4df4ea 100755 --- a/tools/debugger/gdb/gdbbuild +++ b/tools/debugger/gdb/gdbbuild @@ -18,7 +18,7 @@ cd gdb-6.2.1-linux-i386-xen if [ "$MAKE" ]; then $MAKE elif which gmake ; then - gmake -j4 + gmake -j4 CFLAGS=-D__XEN_TOOLS__ else - make -j4 + make -j4 CFLAGS=-D__XEN_TOOLS__ fi From c398044d5d5cca531ed0251e2fea45e0f0e3ea1a Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 30 Aug 2006 17:56:49 +0100 Subject: [PATCH 53/58] [LINUX][X86_64] P2M map must be allocated on page aligned boundary. Otherwise save/restore can break. Signed-off-by: Kazuo Moriwaka --- linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c b/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c index d3b22c8735..96da64e242 100644 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c @@ -846,7 +846,7 @@ void __init setup_arch(char **cmdline_p) if (!xen_feature(XENFEAT_auto_translated_physmap)) { /* Make sure we have a large enough P->M table. */ - phys_to_machine_mapping = alloc_bootmem( + phys_to_machine_mapping = alloc_bootmem_pages( end_pfn * sizeof(unsigned long)); memset(phys_to_machine_mapping, ~0, end_pfn * sizeof(unsigned long)); @@ -863,7 +863,7 @@ void __init setup_arch(char **cmdline_p) * list of frames that make up the p2m table. Used by * save/restore. */ - pfn_to_mfn_frame_list_list = alloc_bootmem(PAGE_SIZE); + pfn_to_mfn_frame_list_list = alloc_bootmem_pages(PAGE_SIZE); HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = virt_to_mfn(pfn_to_mfn_frame_list_list); @@ -873,7 +873,7 @@ void __init setup_arch(char **cmdline_p) k++; BUG_ON(k>=fpp); pfn_to_mfn_frame_list[k] = - alloc_bootmem(PAGE_SIZE); + alloc_bootmem_pages(PAGE_SIZE); pfn_to_mfn_frame_list_list[k] = virt_to_mfn(pfn_to_mfn_frame_list[k]); j=0; From 4a8302220710688f434db6947b7d87108ff1a349 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 30 Aug 2006 18:02:32 +0100 Subject: [PATCH 54/58] [XEN] physdev: Check for negative irqs in alloc_irq_vector. Signed-off-by: Herbert Xu --- xen/arch/x86/physdev.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/physdev.c b/xen/arch/x86/physdev.c index caf6f393e4..2d4841a039 100644 --- a/xen/arch/x86/physdev.c +++ b/xen/arch/x86/physdev.c @@ -96,10 +96,11 @@ long do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg) if ( !IS_PRIV(current->domain) ) break; + irq = irq_op.irq; ret = -EINVAL; - if ( (irq = irq_op.irq) >= NR_IRQS ) + if ( (irq < 0) || (irq >= NR_IRQS) ) break; - + irq_op.vector = assign_irq_vector(irq); ret = copy_to_guest(arg, &irq_op, 1) ? -EFAULT : 0; break; From 6eb53eac78ea16b03191ffa7c08763438f87172f Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 30 Aug 2006 18:03:55 +0100 Subject: [PATCH 55/58] [XEN] Reserve hypercall number for kexec operations. Signed-off-by: Keir Fraser --- xen/include/public/xen.h | 1 + 1 file changed, 1 insertion(+) diff --git a/xen/include/public/xen.h b/xen/include/public/xen.h index eb4bfcb6f9..bec06df60b 100644 --- a/xen/include/public/xen.h +++ b/xen/include/public/xen.h @@ -63,6 +63,7 @@ #define __HYPERVISOR_hvm_op 34 #define __HYPERVISOR_sysctl 35 #define __HYPERVISOR_domctl 36 +#define __HYPERVISOR_kexec_op 37 /* Architecture-specific hypercall definitions. */ #define __HYPERVISOR_arch_0 48 From c5332c36210bebae571238f69f9b9e3318722c39 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 30 Aug 2006 18:08:19 +0100 Subject: [PATCH 56/58] Revert powerpc build break after dom0_ops split. Signed-off-by: Hollis Blanchard --- xen/include/public/domctl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index 1739ebf823..ac21cc95af 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -73,7 +73,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_getdomaininfo_t); struct xen_domctl_getmemlist { /* IN variables. */ uint64_t max_pfns; - XEN_GUEST_HANDLE_64(ulong) buffer; + XEN_GUEST_HANDLE_64(xen_pfn_t) buffer; /* OUT variables. */ uint64_t num_pfns; }; From d96c9af4a37e1dcbe8366013ab089a909585d54a Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 30 Aug 2006 18:19:04 +0100 Subject: [PATCH 57/58] [XEN] Add a start_pfn field in xen_domctl_getmemlist. This is used by ia64 because it directly reads the P2M table. Signed-off-by: Tristan Gingold --- tools/libxc/ia64/xc_ia64_stubs.c | 16 +++++----------- xen/arch/ia64/xen/dom0_ops.c | 4 ++-- xen/include/public/domctl.h | 5 ++++- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/tools/libxc/ia64/xc_ia64_stubs.c b/tools/libxc/ia64/xc_ia64_stubs.c index 6b3639ff52..f6376508d3 100644 --- a/tools/libxc/ia64/xc_ia64_stubs.c +++ b/tools/libxc/ia64/xc_ia64_stubs.c @@ -36,7 +36,6 @@ xc_ia64_get_pfn_list(int xc_handle, uint32_t domid, xen_pfn_t *pfn_buf, struct xen_domctl domctl; int num_pfns,ret; unsigned int __start_page, __nr_pages; - unsigned long max_pfns; xen_pfn_t *__pfn_buf; __start_page = start_page; @@ -44,27 +43,22 @@ xc_ia64_get_pfn_list(int xc_handle, uint32_t domid, xen_pfn_t *pfn_buf, __pfn_buf = pfn_buf; while (__nr_pages) { - max_pfns = ((unsigned long)__start_page << 32) | __nr_pages; domctl.cmd = XEN_DOMCTL_getmemlist; - domctl.domain = (domid_t)domid; - domctl.u.getmemlist.max_pfns = max_pfns; + domctl.domain = (domid_t)domid; + domctl.u.getmemlist.max_pfns = __nr_pages; + domctl.u.getmemlist.start_pfn =__start_page; domctl.u.getmemlist.num_pfns = 0; set_xen_guest_handle(domctl.u.getmemlist.buffer, __pfn_buf); - if ((max_pfns != -1UL) - && mlock(__pfn_buf, __nr_pages * sizeof(xen_pfn_t)) != 0) { + if (mlock(__pfn_buf, __nr_pages * sizeof(xen_pfn_t)) != 0) { PERROR("Could not lock pfn list buffer"); return -1; } ret = do_domctl(xc_handle, &domctl); - if (max_pfns != -1UL) - (void)munlock(__pfn_buf, __nr_pages * sizeof(xen_pfn_t)); + (void)munlock(__pfn_buf, __nr_pages * sizeof(xen_pfn_t)); - if (max_pfns == -1UL) - return 0; - num_pfns = domctl.u.getmemlist.num_pfns; __start_page += num_pfns; __nr_pages -= num_pfns; diff --git a/xen/arch/ia64/xen/dom0_ops.c b/xen/arch/ia64/xen/dom0_ops.c index 0ff54d2507..63eb81bb02 100644 --- a/xen/arch/ia64/xen/dom0_ops.c +++ b/xen/arch/ia64/xen/dom0_ops.c @@ -39,8 +39,8 @@ long arch_do_domctl(xen_domctl_t *op, XEN_GUEST_HANDLE(xen_domctl_t) u_domctl) { unsigned long i; struct domain *d = find_domain_by_id(op->domain); - unsigned long start_page = op->u.getmemlist.max_pfns >> 32; - unsigned long nr_pages = op->u.getmemlist.max_pfns & 0xffffffff; + unsigned long start_page = op->u.getmemlist.start_pfn; + unsigned long nr_pages = op->u.getmemlist.max_pfns; unsigned long mfn; if ( d == NULL ) { diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index ac21cc95af..aaeba06662 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -16,7 +16,7 @@ #include "xen.h" -#define XEN_DOMCTL_INTERFACE_VERSION 0x00000001 +#define XEN_DOMCTL_INTERFACE_VERSION 0x00000002 #define uint64_t uint64_aligned_t @@ -72,7 +72,10 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_getdomaininfo_t); #define XEN_DOMCTL_getmemlist 6 struct xen_domctl_getmemlist { /* IN variables. */ + /* Max entries to write to output buffer. */ uint64_t max_pfns; + /* Start index in guest's page list. */ + uint64_t start_pfn; XEN_GUEST_HANDLE_64(xen_pfn_t) buffer; /* OUT variables. */ uint64_t num_pfns; From 02980865d0523e2282f60ed208bff0a5e4627056 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 30 Aug 2006 18:40:40 +0100 Subject: [PATCH 58/58] [NET] front: move register_netdev() + sysfs attribute registering from create_netdev() into the new open_netdev() function. open_netdev is called as very last thing in netdev_probe. This closes at least one initialization race: uninitialized mac address is visible for a short time in /sys/class/net/${if}/address Signed-off-by: Gerd Hoffmann --- .../drivers/xen/netfront/netfront.c | 60 +++++++++++-------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c index f43bf8fe73..136d1ea420 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c @@ -193,6 +193,7 @@ static void netfront_closing(struct xenbus_device *); static void end_access(int, void *); static void netif_disconnect_backend(struct netfront_info *); +static int open_netdev(struct netfront_info *); static void close_netdev(struct netfront_info *); static void netif_free(struct netfront_info *); @@ -263,15 +264,22 @@ static int __devinit netfront_probe(struct xenbus_device *dev, dev->dev.driver_data = info; err = talk_to_backend(dev, info); - if (err) { - xennet_sysfs_delif(info->netdev); - unregister_netdev(netdev); - free_netdev(netdev); - dev->dev.driver_data = NULL; - return err; - } + if (err) + goto fail_backend; + + err = open_netdev(info); + if (err) + goto fail_open; return 0; + + fail_open: + xennet_sysfs_delif(info->netdev); + unregister_netdev(netdev); + fail_backend: + free_netdev(netdev); + dev->dev.driver_data = NULL; + return err; } @@ -1887,27 +1895,9 @@ create_netdev(int handle, int copying_receiver, struct xenbus_device *dev) SET_MODULE_OWNER(netdev); SET_NETDEV_DEV(netdev, &dev->dev); - err = register_netdev(netdev); - if (err) { - printk(KERN_WARNING "%s> register_netdev err=%d\n", - __FUNCTION__, err); - goto exit_free_rx; - } - - err = xennet_sysfs_addif(netdev); - if (err) { - /* This can be non-fatal: it only means no tuning parameters */ - printk(KERN_WARNING "%s> add sysfs failed err=%d\n", - __FUNCTION__, err); - } - np->netdev = netdev; - return netdev; - - exit_free_rx: - gnttab_free_grant_references(np->gref_rx_head); exit_free_tx: gnttab_free_grant_references(np->gref_tx_head); exit: @@ -1967,6 +1957,26 @@ static int __devexit netfront_remove(struct xenbus_device *dev) } +static int open_netdev(struct netfront_info *info) +{ + int err; + + err = register_netdev(info->netdev); + if (err) { + printk(KERN_WARNING "%s: register_netdev err=%d\n", + __FUNCTION__, err); + return err; + } + + err = xennet_sysfs_addif(info->netdev); + if (err) { + /* This can be non-fatal: it only means no tuning parameters */ + printk(KERN_WARNING "%s: add sysfs failed err=%d\n", + __FUNCTION__, err); + } + return 0; +} + static void close_netdev(struct netfront_info *info) { del_timer_sync(&info->rx_refill_timer);