# HG changeset patch
# User awilliam@xxxxxxxxxxx
# Node ID 4e78528e34806bd1de06e8f14638dded2b694a7e
# Parent 6a49e02dc169540992956eb35b7736ee698a2029
[IA64] merge efi_emul.c into fw_emul.c and clean up
Merge efi_emul.c into fw_emul.c
Clean up: replace some goto with return.
Declare translate_mpa_to_imva in mm.h and as void *.
Signed-off-by: Tristan Gingold <tristan.gingold@xxxxxxxx>
---
xen/arch/ia64/xen/efi_emul.c | 189 --------------------------------------
xen/arch/ia64/vmx/vmx_hypercall.c | 1
xen/arch/ia64/xen/Makefile | 1
xen/arch/ia64/xen/dom_fw.c | 13 +-
xen/arch/ia64/xen/fw_emul.c | 178 +++++++++++++++++++++++++++++++++++
xen/arch/ia64/xen/mm.c | 54 ++--------
xen/include/asm-ia64/mm.h | 1
7 files changed, 199 insertions(+), 238 deletions(-)
diff -r 6a49e02dc169 -r 4e78528e3480 xen/arch/ia64/vmx/vmx_hypercall.c
--- a/xen/arch/ia64/vmx/vmx_hypercall.c Tue Jun 06 09:06:19 2006 -0600
+++ b/xen/arch/ia64/vmx/vmx_hypercall.c Tue Jun 06 09:11:25 2006 -0600
@@ -36,7 +36,6 @@
#include <xen/domain.h>
extern long do_sched_op_compat(int cmd, unsigned long arg);
-extern unsigned long domain_mpa_to_imva(struct domain *,unsigned long mpaddr);
void hyper_not_support(void)
{
diff -r 6a49e02dc169 -r 4e78528e3480 xen/arch/ia64/xen/Makefile
--- a/xen/arch/ia64/xen/Makefile Tue Jun 06 09:06:19 2006 -0600
+++ b/xen/arch/ia64/xen/Makefile Tue Jun 06 09:11:25 2006 -0600
@@ -2,7 +2,6 @@ obj-y += dom0_ops.o
obj-y += dom0_ops.o
obj-y += domain.o
obj-y += dom_fw.o
-obj-y += efi_emul.o
obj-y += fw_emul.o
obj-y += hpsimserial.o
obj-y += hypercall.o
diff -r 6a49e02dc169 -r 4e78528e3480 xen/arch/ia64/xen/dom_fw.c
--- a/xen/arch/ia64/xen/dom_fw.c Tue Jun 06 09:06:19 2006 -0600
+++ b/xen/arch/ia64/xen/dom_fw.c Tue Jun 06 09:11:25 2006 -0600
@@ -25,7 +25,6 @@
#include <asm/dom_fw.h>
static struct ia64_boot_param *dom_fw_init(struct domain *, const char
*,int,char *,int);
-extern unsigned long domain_mpa_to_imva(struct domain *,unsigned long mpaddr);
extern struct domain *dom0;
extern unsigned long dom0_start;
@@ -77,8 +76,8 @@ static void dom_fpswa_hypercall_patch(st
#endif
ASSIGN_NEW_DOMAIN_PAGE_IF_DOM0(d, entry_paddr);
ASSIGN_NEW_DOMAIN_PAGE_IF_DOM0(d, patch_paddr);
- entry_imva = (unsigned long *) domain_mpa_to_imva(d, entry_paddr);
- patch_imva = (unsigned long *) domain_mpa_to_imva(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;
@@ -94,7 +93,7 @@ static void dom_efi_hypercall_patch(stru
if (d == dom0) paddr += dom0_start;
#endif
ASSIGN_NEW_DOMAIN_PAGE_IF_DOM0(d, paddr);
- imva = (unsigned long *) domain_mpa_to_imva(d, paddr);
+ imva = domain_mpa_to_imva(d, paddr);
build_hypercall_bundle(imva, d->arch.breakimm, hypercall, 1);
}
@@ -104,7 +103,7 @@ static void dom_fw_hypercall_patch(struc
unsigned long *imva;
ASSIGN_NEW_DOMAIN_PAGE_IF_DOM0(d, paddr);
- imva = (unsigned long *) domain_mpa_to_imva(d, paddr);
+ imva = domain_mpa_to_imva(d, paddr);
build_hypercall_bundle(imva, d->arch.breakimm, hypercall, ret);
}
@@ -113,7 +112,7 @@ static void dom_fw_pal_hypercall_patch(s
unsigned long *imva;
ASSIGN_NEW_DOMAIN_PAGE_IF_DOM0(d, paddr);
- imva = (unsigned long *) domain_mpa_to_imva(d, paddr);
+ imva = domain_mpa_to_imva(d, paddr);
build_pal_hypercall_bundles(imva, d->arch.breakimm,
FW_HYPERCALL_PAL_CALL);
}
@@ -130,7 +129,7 @@ unsigned long dom_fw_setup(struct domain
if (d == dom0) dom_fw_base_mpa += dom0_start;
#endif
ASSIGN_NEW_DOMAIN_PAGE_IF_DOM0(d, dom_fw_base_mpa);
- imva_fw_base = domain_mpa_to_imva(d, dom_fw_base_mpa);
+ imva_fw_base = (unsigned long) domain_mpa_to_imva(d, dom_fw_base_mpa);
bp = dom_fw_init(d, args, arglen, (char *) imva_fw_base, PAGE_SIZE);
return dom_pa((unsigned long) bp);
}
diff -r 6a49e02dc169 -r 4e78528e3480 xen/arch/ia64/xen/fw_emul.c
--- a/xen/arch/ia64/xen/fw_emul.c Tue Jun 06 09:06:19 2006 -0600
+++ b/xen/arch/ia64/xen/fw_emul.c Tue Jun 06 09:11:25 2006 -0600
@@ -1,3 +1,20 @@
+/*
+ * fw_emul.c:
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ *
+ */
#include <xen/config.h>
#include <asm/system.h>
#include <asm/pgalloc.h>
@@ -338,6 +355,167 @@ xen_pal_emulator(unsigned long index, u6
break;
}
return ((struct ia64_pal_retval) {status, r9, r10, r11});
+}
+
+// given a current domain (virtual or metaphysical) address, return the
virtual address
+static unsigned long
+efi_translate_domain_addr(unsigned long domain_addr, IA64FAULT *fault)
+{
+ struct vcpu *v = current;
+ unsigned long mpaddr = domain_addr;
+ *fault = IA64_NO_FAULT;
+
+ if (v->domain->arch.efi_virt_mode) {
+ *fault = vcpu_tpa(v, domain_addr, &mpaddr);
+ if (*fault != IA64_NO_FAULT) return 0;
+ }
+
+ return ((unsigned long) __va(translate_domain_mpaddr(mpaddr)));
+}
+
+static efi_status_t
+efi_emulate_get_time(
+ unsigned long tv_addr, unsigned long tc_addr,
+ IA64FAULT *fault)
+{
+ unsigned long tv = 0, tc = 0;
+ efi_status_t status;
+
+ //printf("efi_get_time(%016lx,%016lx) called\n", tv_addr, tc_addr);
+ tv = efi_translate_domain_addr(tv_addr, fault);
+ if (*fault != IA64_NO_FAULT) return 0;
+ if (tc_addr) {
+ tc = efi_translate_domain_addr(tc_addr, fault);
+ if (*fault != IA64_NO_FAULT) return 0;
+ }
+ //printf("efi_get_time(%016lx,%016lx) translated to xen virtual
address\n", tv, tc);
+ status = (*efi.get_time)((efi_time_t *) tv, (efi_time_cap_t *) tc);
+ //printf("efi_get_time returns %lx\n", status);
+ return status;
+}
+
+static efi_status_t
+efi_emulate_set_virtual_address_map(
+ unsigned long memory_map_size, unsigned long descriptor_size,
+ u32 descriptor_version, efi_memory_desc_t *virtual_map)
+{
+ void *efi_map_start, *efi_map_end, *p;
+ efi_memory_desc_t entry, *md = &entry;
+ u64 efi_desc_size;
+
+ unsigned long *vfn;
+ struct domain *d = current->domain;
+ efi_runtime_services_t *efi_runtime = d->arch.efi_runtime;
+ fpswa_interface_t *fpswa_inf = d->arch.fpswa_inf;
+
+ if (descriptor_version != EFI_MEMDESC_VERSION) {
+ printf ("efi_emulate_set_virtual_address_map: memory descriptor
version unmatched\n");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (descriptor_size != sizeof(efi_memory_desc_t)) {
+ printf ("efi_emulate_set_virtual_address_map: memory descriptor
size unmatched\n");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (d->arch.efi_virt_mode) return EFI_UNSUPPORTED;
+
+ efi_map_start = virtual_map;
+ efi_map_end = efi_map_start + memory_map_size;
+ efi_desc_size = sizeof(efi_memory_desc_t);
+
+ for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
+ if (copy_from_user(&entry, p, sizeof(efi_memory_desc_t))) {
+ printf ("efi_emulate_set_virtual_address_map:
copy_from_user() fault. addr=0x%p\n", p);
+ return EFI_UNSUPPORTED;
+ }
+
+ /* skip over non-PAL_CODE memory descriptors; EFI_RUNTIME is
included in PAL_CODE. */
+ if (md->type != EFI_PAL_CODE)
+ continue;
+
+#define EFI_HYPERCALL_PATCH_TO_VIRT(tgt,call) \
+ do { \
+ vfn = (unsigned long *) domain_mpa_to_imva(d, tgt); \
+ *vfn++ = FW_HYPERCALL_##call##_INDEX * 16UL + md->virt_addr; \
+ *vfn++ = 0; \
+ } while (0)
+
+ EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_time,EFI_GET_TIME);
+ EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->set_time,EFI_SET_TIME);
+
EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_wakeup_time,EFI_GET_WAKEUP_TIME);
+
EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->set_wakeup_time,EFI_SET_WAKEUP_TIME);
+
EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->set_virtual_address_map,EFI_SET_VIRTUAL_ADDRESS_MAP);
+
EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_variable,EFI_GET_VARIABLE);
+
EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_next_variable,EFI_GET_NEXT_VARIABLE);
+
EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->set_variable,EFI_SET_VARIABLE);
+
EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_next_high_mono_count,EFI_GET_NEXT_HIGH_MONO_COUNT);
+
EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->reset_system,EFI_RESET_SYSTEM);
+
+ vfn = (unsigned long *) domain_mpa_to_imva(d, (unsigned long)
fpswa_inf->fpswa);
+ *vfn++ = FW_HYPERCALL_FPSWA_PATCH_INDEX * 16UL + md->virt_addr;
+ *vfn = 0;
+ fpswa_inf->fpswa = (void *) (FW_HYPERCALL_FPSWA_ENTRY_INDEX *
16UL + md->virt_addr);
+ break;
+ }
+
+ /* The virtual address map has been applied. */
+ d->arch.efi_virt_mode = 1;
+
+ return EFI_SUCCESS;
+}
+
+efi_status_t
+efi_emulator (struct pt_regs *regs, IA64FAULT *fault)
+{
+ struct vcpu *v = current;
+ efi_status_t status;
+
+ *fault = IA64_NO_FAULT;
+
+ switch (regs->r2) {
+ case FW_HYPERCALL_EFI_RESET_SYSTEM:
+ printf("efi.reset_system called ");
+ if (current->domain == dom0) {
+ printf("(by dom0)\n ");
+ (*efi.reset_system)(EFI_RESET_WARM,0,0,NULL);
+ } else {
+ printf("\n");
+ domain_shutdown (current->domain, SHUTDOWN_reboot);
+ }
+ status = EFI_UNSUPPORTED;
+ break;
+ case FW_HYPERCALL_EFI_GET_TIME:
+ status = efi_emulate_get_time (
+ vcpu_get_gr(v,32),
+ vcpu_get_gr(v,33),
+ fault);
+ break;
+ case FW_HYPERCALL_EFI_SET_VIRTUAL_ADDRESS_MAP:
+ status = efi_emulate_set_virtual_address_map (
+ vcpu_get_gr(v,32),
+ vcpu_get_gr(v,33),
+ (u32) vcpu_get_gr(v,34),
+ (efi_memory_desc_t *) vcpu_get_gr(v,35));
+ break;
+ case FW_HYPERCALL_EFI_SET_TIME:
+ 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;
+ break;
+ default:
+ printf("unknown ia64 fw hypercall %lx\n", regs->r2);
+ status = EFI_UNSUPPORTED;
+ }
+
+ return status;
}
void
diff -r 6a49e02dc169 -r 4e78528e3480 xen/arch/ia64/xen/mm.c
--- a/xen/arch/ia64/xen/mm.c Tue Jun 06 09:06:19 2006 -0600
+++ b/xen/arch/ia64/xen/mm.c Tue Jun 06 09:11:25 2006 -0600
@@ -296,7 +296,6 @@ u64 translate_domain_pte(u64 pteval, u64
printk("translate_domain_pte: out-of-bounds dom0 mpaddr
0x%lx! itc=%lx...\n",
mpaddr, ia64_get_itc());
*/
- tdpfoo();
}
}
else if ((mpaddr >> PAGE_SHIFT) > d->max_pages) {
@@ -310,7 +309,6 @@ u64 translate_domain_pte(u64 pteval, u64
"vadr=0x%lx,pteval=0x%lx,itir=0x%lx\n",
mpaddr, (unsigned long)d->max_pages<<PAGE_SHIFT,
address, pteval, itir.itir);
- tdpfoo();
}
#endif
pteval2 = lookup_domain_mpa(d,mpaddr);
@@ -345,7 +343,6 @@ unsigned long translate_domain_mpaddr(un
if (mpaddr < dom0_start || mpaddr >= dom0_start + dom0_size) {
printk("translate_domain_mpaddr: out-of-bounds dom0
mpaddr 0x%lx! continuing...\n",
mpaddr);
- tdpfoo();
}
}
#endif
@@ -393,20 +390,17 @@ lookup_noalloc_domain_pte(struct domain*
BUG_ON(mm->pgd == NULL);
pgd = pgd_offset(mm, mpaddr);
if (!pgd_present(*pgd))
- goto not_present;
+ return NULL;
pud = pud_offset(pgd, mpaddr);
if (!pud_present(*pud))
- goto not_present;
+ return NULL;
pmd = pmd_offset(pud, mpaddr);
if (!pmd_present(*pmd))
- goto not_present;
+ return NULL;
return pte_offset_map(pmd, mpaddr);
-
-not_present:
- return NULL;
}
#ifdef CONFIG_XEN_IA64_DOM0_VP
@@ -421,20 +415,17 @@ lookup_noalloc_domain_pte_none(struct do
BUG_ON(mm->pgd == NULL);
pgd = pgd_offset(mm, mpaddr);
if (pgd_none(*pgd))
- goto not_present;
+ return NULL;
pud = pud_offset(pgd, mpaddr);
if (pud_none(*pud))
- goto not_present;
+ return NULL;
pmd = pmd_offset(pud, mpaddr);
if (pmd_none(*pmd))
- goto not_present;
+ return NULL;
return pte_offset_map(pmd, mpaddr);
-
-not_present:
- return NULL;
}
unsigned long
@@ -444,14 +435,12 @@ ____lookup_domain_mpa(struct domain *d,
pte = lookup_noalloc_domain_pte(d, mpaddr);
if (pte == NULL)
- goto not_present;
+ return INVALID_MFN;
if (pte_present(*pte))
return (pte->pte & _PFN_MASK);
else if (VMX_DOMAIN(d->vcpu[0]))
return GPFN_INV_MASK;
-
-not_present:
return INVALID_MFN;
}
@@ -469,13 +458,6 @@ __lookup_domain_mpa(struct domain *d, un
return INVALID_MFN;
}
#endif
-
-void mpafoo(unsigned long mpaddr)
-{
- extern unsigned long privop_trace;
- if (mpaddr == 0x3800)
- privop_trace = 1;
-}
unsigned long lookup_domain_mpa(struct domain *d, unsigned long mpaddr)
{
@@ -487,7 +469,6 @@ unsigned long lookup_domain_mpa(struct d
if (mpaddr < dom0_start || mpaddr >= dom0_start + dom0_size) {
//printk("lookup_domain_mpa: bad dom0 mpaddr 0x%lx!\n",mpaddr);
//printk("lookup_domain_mpa:
start=0x%lx,end=0x%lx!\n",dom0_start,dom0_start+dom0_size);
- mpafoo(mpaddr);
}
pteval = pfn_pte(mpaddr >> PAGE_SHIFT,
__pgprot(__DIRTY_BITS | _PAGE_PL_2 | _PAGE_AR_RWX));
@@ -511,7 +492,6 @@ unsigned long lookup_domain_mpa(struct d
else
printk("%s: bad mpa 0x%lx (=> 0x%lx)\n", __func__,
mpaddr, (unsigned long)d->max_pages << PAGE_SHIFT);
- mpafoo(mpaddr);
//XXX This is a work around until the emulation memory access to a region
// where memory or device are attached is implemented.
@@ -520,7 +500,7 @@ unsigned long lookup_domain_mpa(struct d
// FIXME: ONLY USE FOR DOMAIN PAGE_SIZE == PAGE_SIZE
#if 1
-unsigned long domain_mpa_to_imva(struct domain *d, unsigned long mpaddr)
+void *domain_mpa_to_imva(struct domain *d, unsigned long mpaddr)
{
unsigned long pte = lookup_domain_mpa(d,mpaddr);
unsigned long imva;
@@ -528,14 +508,14 @@ unsigned long domain_mpa_to_imva(struct
pte &= _PAGE_PPN_MASK;
imva = (unsigned long) __va(pte);
imva |= mpaddr & ~PAGE_MASK;
- return(imva);
+ return (void*)imva;
}
#else
-unsigned long domain_mpa_to_imva(struct domain *d, unsigned long mpaddr)
+void *domain_mpa_to_imva(struct domain *d, unsigned long mpaddr)
{
unsigned long imva = __gpa_to_mpa(d, mpaddr);
- return __va(imva);
+ return (void *)__va(imva);
}
#endif
@@ -842,17 +822,13 @@ dom0vp_zap_physmap(struct domain *d, uns
dom0vp_zap_physmap(struct domain *d, unsigned long gpfn,
unsigned int extent_order)
{
- unsigned long ret = 0;
if (extent_order != 0) {
//XXX
- ret = -ENOSYS;
- goto out;
+ return -ENOSYS;
}
zap_domain_page_one(d, gpfn << PAGE_SHIFT, 1);
-
-out:
- return ret;
+ return 0;
}
unsigned long
@@ -875,8 +851,7 @@ dom0vp_add_physmap(struct domain* d, uns
DPRINTK("d 0x%p domid %d "
"pgfn 0x%lx mfn 0x%lx flags 0x%lx domid %d\n",
d, d->domain_id, gpfn, mfn, flags, domid);
- error = -ESRCH;
- goto out0;
+ return -ESRCH;
}
BUG_ON(rd == NULL);
get_knownalive_domain(rd);
@@ -895,7 +870,6 @@ dom0vp_add_physmap(struct domain* d, uns
//don't update p2m table because this page belongs to rd, not d.
out1:
put_domain(rd);
-out0:
return error;
}
diff -r 6a49e02dc169 -r 4e78528e3480 xen/include/asm-ia64/mm.h
--- a/xen/include/asm-ia64/mm.h Tue Jun 06 09:06:19 2006 -0600
+++ b/xen/include/asm-ia64/mm.h Tue Jun 06 09:11:25 2006 -0600
@@ -429,6 +429,7 @@ extern void assign_domain_page(struct do
extern void assign_domain_page(struct domain *d, unsigned long mpaddr,
unsigned long physaddr);
extern void assign_domain_io_page(struct domain *d, unsigned long mpaddr,
unsigned long flags);
extern unsigned long lookup_domain_mpa(struct domain *d, unsigned long mpaddr);
+extern void *domain_mpa_to_imva(struct domain *d, unsigned long mpaddr);
#ifdef CONFIG_XEN_IA64_DOM0_VP
extern unsigned long assign_domain_mmio_page(struct domain *d, unsigned long
mpaddr, unsigned long size);
diff -r 6a49e02dc169 -r 4e78528e3480 xen/arch/ia64/xen/efi_emul.c
--- a/xen/arch/ia64/xen/efi_emul.c Tue Jun 06 09:06:19 2006 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,189 +0,0 @@
-/*
- * efi_emul.c:
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- */
-
-#include <xen/config.h>
-#include <xen/compile.h>
-#include <asm/pgalloc.h>
-#include <asm/vcpu.h>
-#include <asm/dom_fw.h>
-#include <asm/fpswa.h>
-#include <public/sched.h>
-
-extern unsigned long translate_domain_mpaddr(unsigned long);
-extern unsigned long domain_mpa_to_imva(struct domain *,unsigned long mpaddr);
-
-// given a current domain (virtual or metaphysical) address, return the
virtual address
-static unsigned long
-efi_translate_domain_addr(unsigned long domain_addr, IA64FAULT *fault)
-{
- struct vcpu *v = current;
- unsigned long mpaddr = domain_addr;
- *fault = IA64_NO_FAULT;
-
- if (v->domain->arch.efi_virt_mode) {
- *fault = vcpu_tpa(v, domain_addr, &mpaddr);
- if (*fault != IA64_NO_FAULT) return 0;
- }
-
- return ((unsigned long) __va(translate_domain_mpaddr(mpaddr)));
-}
-
-static efi_status_t
-efi_emulate_get_time(
- unsigned long tv_addr, unsigned long tc_addr,
- IA64FAULT *fault)
-{
- unsigned long tv = 0, tc = 0;
- efi_status_t status;
-
- //printf("efi_get_time(%016lx,%016lx) called\n", tv_addr, tc_addr);
- tv = efi_translate_domain_addr(tv_addr, fault);
- if (*fault != IA64_NO_FAULT) return 0;
- if (tc_addr) {
- tc = efi_translate_domain_addr(tc_addr, fault);
- if (*fault != IA64_NO_FAULT) return 0;
- }
- //printf("efi_get_time(%016lx,%016lx) translated to xen virtual
address\n", tv, tc);
- status = (*efi.get_time)((efi_time_t *) tv, (efi_time_cap_t *) tc);
- //printf("efi_get_time returns %lx\n", status);
- return status;
-}
-
-static efi_status_t
-efi_emulate_set_virtual_address_map(
- unsigned long memory_map_size, unsigned long descriptor_size,
- u32 descriptor_version, efi_memory_desc_t *virtual_map)
-{
- void *efi_map_start, *efi_map_end, *p;
- efi_memory_desc_t entry, *md = &entry;
- u64 efi_desc_size;
-
- unsigned long *vfn;
- struct domain *d = current->domain;
- efi_runtime_services_t *efi_runtime = d->arch.efi_runtime;
- fpswa_interface_t *fpswa_inf = d->arch.fpswa_inf;
-
- if (descriptor_version != EFI_MEMDESC_VERSION) {
- printf ("efi_emulate_set_virtual_address_map: memory descriptor
version unmatched\n");
- return EFI_INVALID_PARAMETER;
- }
-
- if (descriptor_size != sizeof(efi_memory_desc_t)) {
- printf ("efi_emulate_set_virtual_address_map: memory descriptor
size unmatched\n");
- return EFI_INVALID_PARAMETER;
- }
-
- if (d->arch.efi_virt_mode) return EFI_UNSUPPORTED;
-
- efi_map_start = virtual_map;
- efi_map_end = efi_map_start + memory_map_size;
- efi_desc_size = sizeof(efi_memory_desc_t);
-
- for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
- if (copy_from_user(&entry, p, sizeof(efi_memory_desc_t))) {
- printf ("efi_emulate_set_virtual_address_map:
copy_from_user() fault. addr=0x%p\n", p);
- return EFI_UNSUPPORTED;
- }
-
- /* skip over non-PAL_CODE memory descriptors; EFI_RUNTIME is
included in PAL_CODE. */
- if (md->type != EFI_PAL_CODE)
- continue;
-
-#define EFI_HYPERCALL_PATCH_TO_VIRT(tgt,call) \
- do { \
- vfn = (unsigned long *) domain_mpa_to_imva(d, tgt); \
- *vfn++ = FW_HYPERCALL_##call##_INDEX * 16UL + md->virt_addr; \
- *vfn++ = 0; \
- } while (0)
-
- EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_time,EFI_GET_TIME);
- EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->set_time,EFI_SET_TIME);
-
EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_wakeup_time,EFI_GET_WAKEUP_TIME);
-
EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->set_wakeup_time,EFI_SET_WAKEUP_TIME);
-
EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->set_virtual_address_map,EFI_SET_VIRTUAL_ADDRESS_MAP);
-
EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_variable,EFI_GET_VARIABLE);
-
EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_next_variable,EFI_GET_NEXT_VARIABLE);
-
EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->set_variable,EFI_SET_VARIABLE);
-
EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->get_next_high_mono_count,EFI_GET_NEXT_HIGH_MONO_COUNT);
-
EFI_HYPERCALL_PATCH_TO_VIRT(efi_runtime->reset_system,EFI_RESET_SYSTEM);
-
- vfn = (unsigned long *) domain_mpa_to_imva(d, (unsigned long)
fpswa_inf->fpswa);
- *vfn++ = FW_HYPERCALL_FPSWA_PATCH_INDEX * 16UL + md->virt_addr;
- *vfn = 0;
- fpswa_inf->fpswa = (void *) (FW_HYPERCALL_FPSWA_ENTRY_INDEX *
16UL + md->virt_addr);
- break;
- }
-
- /* The virtual address map has been applied. */
- d->arch.efi_virt_mode = 1;
-
- return EFI_SUCCESS;
-}
-
-efi_status_t
-efi_emulator (struct pt_regs *regs, IA64FAULT *fault)
-{
- struct vcpu *v = current;
- efi_status_t status;
-
- *fault = IA64_NO_FAULT;
-
- switch (regs->r2) {
- case FW_HYPERCALL_EFI_RESET_SYSTEM:
- printf("efi.reset_system called ");
- if (current->domain == dom0) {
- printf("(by dom0)\n ");
- (*efi.reset_system)(EFI_RESET_WARM,0,0,NULL);
- } else {
- printf("\n");
- domain_shutdown (current->domain, SHUTDOWN_reboot);
- }
- status = EFI_UNSUPPORTED;
- break;
- case FW_HYPERCALL_EFI_GET_TIME:
- status = efi_emulate_get_time (
- vcpu_get_gr(v,32),
- vcpu_get_gr(v,33),
- fault);
- break;
- case FW_HYPERCALL_EFI_SET_VIRTUAL_ADDRESS_MAP:
- status = efi_emulate_set_virtual_address_map (
- vcpu_get_gr(v,32),
- vcpu_get_gr(v,33),
- (u32) vcpu_get_gr(v,34),
- (efi_memory_desc_t *) vcpu_get_gr(v,35));
- break;
- case FW_HYPERCALL_EFI_SET_TIME:
- 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;
- break;
- default:
- printf("unknown ia64 fw hypercall %lx\n", regs->r2);
- status = EFI_UNSUPPORTED;
- }
-
- return status;
-}
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|