ia64/xen-unstable

changeset 3277:da409d40699a

bitkeeper revision 1.1159.183.55 (41bf1757jtBc6PTE_nT4GQFS3VFfXA)

Merge scramble.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xen-2.0-testing.bk
into scramble.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xen-unstable.bk
author kaf24@scramble.cl.cam.ac.uk
date Tue Dec 14 16:39:51 2004 +0000 (2004-12-14)
parents 577e6187b311 12cf2ba64202
children 90394f6cfd34
files .rootkeys xen/arch/x86/boot/x86_64.S xen/arch/x86/domain.c xen/arch/x86/traps.c xen/arch/x86/x86_32/entry.S xen/arch/x86/x86_64/asm-offsets.c xen/arch/x86/x86_64/mm.c xen/arch/x86/x86_64/xen.lds xen/include/asm-x86/asm_defns.h xen/include/asm-x86/irq.h xen/include/asm-x86/multicall.h xen/include/asm-x86/processor.h xen/include/asm-x86/uaccess.h xen/include/asm-x86/x86_32/asm_defns.h xen/include/asm-x86/x86_32/uaccess.h xen/include/asm-x86/x86_64/asm_defns.h xen/include/asm-x86/x86_64/uaccess.h
line diff
     1.1 --- a/.rootkeys	Tue Dec 14 14:47:08 2004 +0000
     1.2 +++ b/.rootkeys	Tue Dec 14 16:39:51 2004 +0000
     1.3 @@ -699,7 +699,9 @@ 3ddb79bcHwuCQDjBICDTSis52hWguw xen/arch/
     1.4  40f92331jfOlE7MfKwpdkEb1CEf23g xen/arch/x86/x86_32/seg_fixup.c
     1.5  3ddb79bc4nTpGQOe6_-MbyZzkhlhFQ xen/arch/x86/x86_32/usercopy.c
     1.6  3ddb79bcOMCu9-5mKpjIh5d0qqBDPg xen/arch/x86/x86_32/xen.lds
     1.7 +41bf1717Ty3hwN3E9swdu8QfnvGqww xen/arch/x86/x86_64/asm-offsets.c
     1.8  40e96d3aLDI-nViMuYneD7VKYlZrVg xen/arch/x86/x86_64/entry.S
     1.9 +41bf1717XhPz_dNT5OKSjgmbFuWBuA xen/arch/x86/x86_64/mm.c
    1.10  40e96d3ahBTZqbTViInnq0lM03vs7A xen/arch/x86/x86_64/usercopy.c
    1.11  40e96d3akN3Hu_J5Bk-WXD8OGscrYQ xen/arch/x86/x86_64/xen.lds
    1.12  3ddb79bdff-gj-jFGKjOejeHLqL8Lg xen/common/Makefile
    1.13 @@ -787,6 +789,7 @@ 40715b2d1yZkqyAt0kgx2xEwsatuuA xen/inclu
    1.14  40715b2dWe0tDhx9LkLXzTQkvD49RA xen/include/asm-x86/acpi.h
    1.15  3ddb79c3l4IiQtf6MS2jIzcd-hJS8g xen/include/asm-x86/apic.h
    1.16  3ddb79c3QJYWr8LLGdonLbWmNb9pQQ xen/include/asm-x86/apicdef.h
    1.17 +41bf17171g_hhz2k4B-fN9LQlODDjQ xen/include/asm-x86/asm_defns.h
    1.18  3ddb79c3OiG9eTsi9Dy3F_OkuRAzKA xen/include/asm-x86/atomic.h
    1.19  3ddb79c3rM-Ote0Xn6Ytg8Y6YqAG-A xen/include/asm-x86/bitops.h
    1.20  3ddb79c3KhTI0F_Iw_hRL9QEyOVK-g xen/include/asm-x86/cache.h
    1.21 @@ -833,6 +836,7 @@ 3ddb79c2ADvRmdexd9y3AYK9_NTx-Q xen/inclu
    1.22  3ddb79c3mbqEM7QQr3zVq7NiBNhouA xen/include/asm-x86/x86_32/regs.h
    1.23  3e7f358aG11EvMI9VJ4_9hD4LUO7rQ xen/include/asm-x86/x86_32/string.h
    1.24  3ddb79c3M2n1ROZH6xk3HbyN4CPDqg xen/include/asm-x86/x86_32/uaccess.h
    1.25 +41bf1717bML6GxpclTWJabiaO5W5vg xen/include/asm-x86/x86_64/asm_defns.h
    1.26  404f1b9ceJeGVaPNIENm2FkK0AgEOQ xen/include/asm-x86/x86_64/current.h
    1.27  404f1b9fl6AQ_a-T1TDK3fuwTPXmHw xen/include/asm-x86/x86_64/desc.h
    1.28  404f1badfXZJZ2sU8sh9PS2EZvd19Q xen/include/asm-x86/x86_64/ldt.h
     2.1 --- a/xen/arch/x86/boot/x86_64.S	Tue Dec 14 14:47:08 2004 +0000
     2.2 +++ b/xen/arch/x86/boot/x86_64.S	Tue Dec 14 16:39:51 2004 +0000
     2.3 @@ -257,29 +257,22 @@ copy_to_user:
     2.4  set_intr_gate:
     2.5  die:
     2.6  machine_to_phys_mapping:
     2.7 -.globl copy_from_user, show_registers, __set_fixmap, do_iopl, check_descriptor
     2.8 +.globl copy_from_user, show_registers, do_iopl
     2.9  copy_from_user: 
    2.10  show_registers: 
    2.11 -__set_fixmap: 
    2.12  do_iopl: 
    2.13 -check_descriptor:
    2.14 -.globl set_gdt, idt_table, copy_user_generic, memcmp, idt_tables, new_thread
    2.15 -set_gdt:
    2.16 +.globl idt_table, copy_user_generic, memcmp, idt_tables, new_thread
    2.17  idt_table:
    2.18  copy_user_generic:
    2.19  memcmp:
    2.20  idt_tables:
    2.21  new_thread:
    2.22 -.globl switch_to, __get_user_1, paging_init, trap_init
    2.23 +.globl switch_to, __get_user_1, __get_user_4, __get_user_8, trap_init
    2.24  switch_to:
    2.25  __get_user_1:
    2.26 -paging_init:
    2.27 -trap_init: 
    2.28 -.globl __get_user_8, zap_low_mappings, set_debugreg,synchronise_pagetables
    2.29 +__get_user_4:
    2.30  __get_user_8:
    2.31 -zap_low_mappings:
    2.32 +trap_init: 
    2.33 +.globl set_debugreg
    2.34  set_debugreg:
    2.35 -synchronise_pagetables:
    2.36 -.globl destroy_gdt
    2.37 -destroy_gdt:    
    2.38          
     3.1 --- a/xen/arch/x86/domain.c	Tue Dec 14 14:47:08 2004 +0000
     3.2 +++ b/xen/arch/x86/domain.c	Tue Dec 14 16:39:51 2004 +0000
     3.3 @@ -427,6 +427,8 @@ long do_iopl(domid_t domain, unsigned in
     3.4      return 0;
     3.5  }
     3.6  
     3.7 +#endif
     3.8 +
     3.9  unsigned long hypercall_create_continuation(
    3.10      unsigned int op, unsigned int nr_args, ...)
    3.11  {
    3.12 @@ -448,11 +450,15 @@ unsigned long hypercall_create_continuat
    3.13      else
    3.14      {
    3.15          ec       = get_execution_context();
    3.16 +#if defined(__i386__)
    3.17          ec->eax  = op;
    3.18          ec->eip -= 2;  /* re-execute 'int 0x82' */
    3.19          
    3.20          for ( i = 0, preg = &ec->ebx; i < nr_args; i++, preg++ )
    3.21              *preg = va_arg(args, unsigned long);
    3.22 +#else
    3.23 +        preg = NULL; /* XXX x86/64 */
    3.24 +#endif
    3.25      }
    3.26  
    3.27      va_end(args);
    3.28 @@ -460,9 +466,6 @@ unsigned long hypercall_create_continuat
    3.29      return op;
    3.30  }
    3.31  
    3.32 -#endif
    3.33 -
    3.34 -
    3.35  static void relinquish_list(struct domain *d, struct list_head *list)
    3.36  {
    3.37      struct list_head *ent;
     4.1 --- a/xen/arch/x86/traps.c	Tue Dec 14 14:47:08 2004 +0000
     4.2 +++ b/xen/arch/x86/traps.c	Tue Dec 14 16:39:51 2004 +0000
     4.3 @@ -981,4 +981,10 @@ unsigned long do_get_debugreg(int reg)
     4.4      return current->thread.debugreg[reg];
     4.5  }
     4.6  
     4.7 +#else
     4.8 +
     4.9 +asmlinkage void fatal_trap(int trapnr, struct xen_regs *regs)
    4.10 +{
    4.11 +}
    4.12 +
    4.13  #endif /* __i386__ */
     5.1 --- a/xen/arch/x86/x86_32/entry.S	Tue Dec 14 14:47:08 2004 +0000
     5.2 +++ b/xen/arch/x86/x86_32/entry.S	Tue Dec 14 16:39:51 2004 +0000
     5.3 @@ -56,7 +56,7 @@
     5.4  #include <xen/config.h>
     5.5  #include <xen/errno.h>
     5.6  #include <xen/softirq.h>
     5.7 -#include <asm/x86_32/asm_defns.h>
     5.8 +#include <asm/asm_defns.h>
     5.9  #include <public/xen.h>
    5.10  
    5.11  #define GET_CURRENT(reg)   \
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/xen/arch/x86/x86_64/asm-offsets.c	Tue Dec 14 16:39:51 2004 +0000
     6.3 @@ -0,0 +1,71 @@
     6.4 +/*
     6.5 + * Generate definitions needed by assembly language modules.
     6.6 + * This code generates raw asm output which is post-processed
     6.7 + * to extract and format the required data.
     6.8 + */
     6.9 +
    6.10 +#include <xen/sched.h>
    6.11 +
    6.12 +#define DEFINE(_sym, _val) \
    6.13 +    __asm__ __volatile__ ( "\n->" #_sym " %0 " #_val : : "i" (_val) )
    6.14 +#define BLANK() \
    6.15 +    __asm__ __volatile__ ( "\n->" : : )
    6.16 +#define OFFSET(_sym, _str, _mem) \
    6.17 +    DEFINE(_sym, offsetof(_str, _mem));
    6.18 +
    6.19 +void __dummy__(void)
    6.20 +{
    6.21 +    OFFSET(XREGS_r15, struct xen_regs, r15);
    6.22 +    OFFSET(XREGS_r14, struct xen_regs, r14);
    6.23 +    OFFSET(XREGS_r13, struct xen_regs, r13);
    6.24 +    OFFSET(XREGS_r12, struct xen_regs, r12);
    6.25 +    OFFSET(XREGS_rbp, struct xen_regs, rbp);
    6.26 +    OFFSET(XREGS_rbx, struct xen_regs, rbx);
    6.27 +    OFFSET(XREGS_r11, struct xen_regs, r11);
    6.28 +    OFFSET(XREGS_r10, struct xen_regs, r10);
    6.29 +    OFFSET(XREGS_r9, struct xen_regs, r9);
    6.30 +    OFFSET(XREGS_r8, struct xen_regs, r8);
    6.31 +    OFFSET(XREGS_rax, struct xen_regs, rax);
    6.32 +    OFFSET(XREGS_rcx, struct xen_regs, rcx);
    6.33 +    OFFSET(XREGS_rdx, struct xen_regs, rdx);
    6.34 +    OFFSET(XREGS_rsi, struct xen_regs, rsi);
    6.35 +    OFFSET(XREGS_rdi, struct xen_regs, rdi);
    6.36 +    OFFSET(XREGS_orig_rax, struct xen_regs, orig_rax);
    6.37 +    OFFSET(XREGS_rip, struct xen_regs, rip);
    6.38 +    OFFSET(XREGS_cs, struct xen_regs, cs);
    6.39 +    OFFSET(XREGS_eflags, struct xen_regs, eflags);
    6.40 +    OFFSET(XREGS_rsp, struct xen_regs, rsp);
    6.41 +    OFFSET(XREGS_ss, struct xen_regs, ss);
    6.42 +    BLANK();
    6.43 +
    6.44 +    OFFSET(DOMAIN_processor, struct domain, processor);
    6.45 +    OFFSET(DOMAIN_shared_info, struct domain, shared_info);
    6.46 +    OFFSET(DOMAIN_event_sel, struct domain, thread.event_selector);
    6.47 +    OFFSET(DOMAIN_event_addr, struct domain, thread.event_address);
    6.48 +    OFFSET(DOMAIN_failsafe_sel, struct domain, thread.failsafe_selector);
    6.49 +    OFFSET(DOMAIN_failsafe_addr, struct domain, thread.failsafe_address);
    6.50 +    OFFSET(DOMAIN_trap_bounce, struct domain, thread.trap_bounce);
    6.51 +    OFFSET(DOMAIN_thread_flags, struct domain, thread.flags);
    6.52 +    BLANK();
    6.53 +
    6.54 +    OFFSET(SHINFO_upcall_pending, shared_info_t, 
    6.55 +           vcpu_data[0].evtchn_upcall_pending);
    6.56 +    OFFSET(SHINFO_upcall_mask, shared_info_t, 
    6.57 +           vcpu_data[0].evtchn_upcall_mask);
    6.58 +    BLANK();
    6.59 +
    6.60 +    OFFSET(TRAPBOUNCE_error_code, struct trap_bounce, error_code);
    6.61 +    OFFSET(TRAPBOUNCE_cr2, struct trap_bounce, cr2);
    6.62 +    OFFSET(TRAPBOUNCE_flags, struct trap_bounce, flags);
    6.63 +    OFFSET(TRAPBOUNCE_cs, struct trap_bounce, cs);
    6.64 +    OFFSET(TRAPBOUNCE_eip, struct trap_bounce, eip);
    6.65 +    BLANK();
    6.66 +
    6.67 +    OFFSET(MULTICALL_op, multicall_entry_t, op);
    6.68 +    OFFSET(MULTICALL_arg0, multicall_entry_t, args[0]);
    6.69 +    OFFSET(MULTICALL_arg1, multicall_entry_t, args[1]);
    6.70 +    OFFSET(MULTICALL_arg2, multicall_entry_t, args[2]);
    6.71 +    OFFSET(MULTICALL_arg3, multicall_entry_t, args[3]);
    6.72 +    OFFSET(MULTICALL_arg4, multicall_entry_t, args[4]);
    6.73 +    OFFSET(MULTICALL_result, multicall_entry_t, args[5]);
    6.74 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/xen/arch/x86/x86_64/mm.c	Tue Dec 14 16:39:51 2004 +0000
     7.3 @@ -0,0 +1,455 @@
     7.4 +/******************************************************************************
     7.5 + * arch/x86/x86_64/mm.c
     7.6 + * 
     7.7 + * Modifications to Linux original are copyright (c) 2004, K A Fraser
     7.8 + * 
     7.9 + * This program is free software; you can redistribute it and/or modify
    7.10 + * it under the terms of the GNU General Public License as published by
    7.11 + * the Free Software Foundation; either version 2 of the License, or
    7.12 + * (at your option) any later version.
    7.13 + * 
    7.14 + * This program is distributed in the hope that it will be useful,
    7.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.17 + * GNU General Public License for more details.
    7.18 + * 
    7.19 + * You should have received a copy of the GNU General Public License
    7.20 + * along with this program; if not, write to the Free Software
    7.21 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    7.22 + */
    7.23 +
    7.24 +#include <xen/config.h>
    7.25 +#include <xen/lib.h>
    7.26 +#include <xen/init.h>
    7.27 +#include <xen/mm.h>
    7.28 +#include <asm/page.h>
    7.29 +#include <asm/flushtlb.h>
    7.30 +#include <asm/fixmap.h>
    7.31 +#include <asm/domain_page.h>
    7.32 +
    7.33 +static inline void set_pte_phys(unsigned long vaddr,
    7.34 +                                l1_pgentry_t entry)
    7.35 +{
    7.36 +    l4_pgentry_t *l4ent;
    7.37 +    l3_pgentry_t *l3ent;
    7.38 +    l2_pgentry_t *l2ent;
    7.39 +    l1_pgentry_t *l1ent;
    7.40 +
    7.41 +    l4ent = &idle_pg_table[l4_table_offset(vaddr)];
    7.42 +    l3ent = l4_pgentry_to_l3(*l4ent) + l3_table_offset(vaddr);
    7.43 +    l2ent = l3_pgentry_to_l2(*l3ent) + l2_table_offset(vaddr);
    7.44 +    l1ent = l2_pgentry_to_l1(*l2ent) + l1_table_offset(vaddr);
    7.45 +    *l1ent = entry;
    7.46 +
    7.47 +    /* It's enough to flush this one mapping. */
    7.48 +    __flush_tlb_one(vaddr);
    7.49 +}
    7.50 +
    7.51 +
    7.52 +void __set_fixmap(enum fixed_addresses idx, 
    7.53 +                  l1_pgentry_t entry)
    7.54 +{
    7.55 +    unsigned long address = fix_to_virt(idx);
    7.56 +
    7.57 +    if ( likely(idx < __end_of_fixed_addresses) )
    7.58 +        set_pte_phys(address, entry);
    7.59 +    else
    7.60 +        printk("Invalid __set_fixmap\n");
    7.61 +}
    7.62 +
    7.63 +
    7.64 +void __init paging_init(void)
    7.65 +{
    7.66 +    void *ioremap_pt;
    7.67 +    int i;
    7.68 +
    7.69 +    /* Create page table for ioremap(). */
    7.70 +    ioremap_pt = (void *)alloc_xenheap_page();
    7.71 +    clear_page(ioremap_pt);
    7.72 +    idle_pg_table[IOREMAP_VIRT_START >> L2_PAGETABLE_SHIFT] = 
    7.73 +        mk_l2_pgentry(__pa(ioremap_pt) | __PAGE_HYPERVISOR);
    7.74 +
    7.75 +    /* Create read-only mapping of MPT for guest-OS use. */
    7.76 +    idle_pg_table[RO_MPT_VIRT_START >> L2_PAGETABLE_SHIFT] =
    7.77 +        mk_l2_pgentry(l2_pgentry_val(
    7.78 +            idle_pg_table[RDWR_MPT_VIRT_START >> L2_PAGETABLE_SHIFT]) & 
    7.79 +                      ~_PAGE_RW);
    7.80 +
    7.81 +    /* Set up mapping cache for domain pages. */
    7.82 +    mapcache = (unsigned long *)alloc_xenheap_page();
    7.83 +    clear_page(mapcache);
    7.84 +    idle_pg_table[MAPCACHE_VIRT_START >> L2_PAGETABLE_SHIFT] =
    7.85 +        mk_l2_pgentry(__pa(mapcache) | __PAGE_HYPERVISOR);
    7.86 +
    7.87 +    /* Set up linear page table mapping. */
    7.88 +    idle_pg_table[LINEAR_PT_VIRT_START >> L2_PAGETABLE_SHIFT] =
    7.89 +        mk_l2_pgentry(__pa(idle_pg_table) | __PAGE_HYPERVISOR);
    7.90 +
    7.91 +}
    7.92 +
    7.93 +void __init zap_low_mappings(void)
    7.94 +{
    7.95 +    idle_pg_table[0] = 0;
    7.96 +}
    7.97 +
    7.98 +
    7.99 +/*
   7.100 + * Allows shooting down of borrowed page-table use on specific CPUs.
   7.101 + * Specifically, we borrow page tables when running the idle domain.
   7.102 + */
   7.103 +static void __synchronise_pagetables(void *mask)
   7.104 +{
   7.105 +    struct domain *d = current;
   7.106 +    if ( ((unsigned long)mask & (1<<d->processor)) && is_idle_task(d) )
   7.107 +        write_ptbase(&d->mm);
   7.108 +}
   7.109 +void synchronise_pagetables(unsigned long cpu_mask)
   7.110 +{
   7.111 +    __synchronise_pagetables((void *)cpu_mask);
   7.112 +    smp_call_function(__synchronise_pagetables, (void *)cpu_mask, 1, 1);
   7.113 +}
   7.114 +
   7.115 +long do_stack_switch(unsigned long ss, unsigned long esp)
   7.116 +{
   7.117 +    int nr = smp_processor_id();
   7.118 +    struct tss_struct *t = &init_tss[nr];
   7.119 +
   7.120 +    /* We need to do this check as we load and use SS on guest's behalf. */
   7.121 +    if ( (ss & 3) == 0 )
   7.122 +        return -EPERM;
   7.123 +
   7.124 +    current->thread.guestos_ss = ss;
   7.125 +    current->thread.guestos_sp = esp;
   7.126 +    t->ss1  = ss;
   7.127 +    t->esp1 = esp;
   7.128 +
   7.129 +    return 0;
   7.130 +}
   7.131 +
   7.132 +
   7.133 +/* Returns TRUE if given descriptor is valid for GDT or LDT. */
   7.134 +int check_descriptor(unsigned long *d)
   7.135 +{
   7.136 +    unsigned long base, limit, a = d[0], b = d[1];
   7.137 +
   7.138 +    /* A not-present descriptor will always fault, so is safe. */
   7.139 +    if ( !(b & _SEGMENT_P) ) 
   7.140 +        goto good;
   7.141 +
   7.142 +    /*
   7.143 +     * We don't allow a DPL of zero. There is no legitimate reason for 
   7.144 +     * specifying DPL==0, and it gets rather dangerous if we also accept call 
   7.145 +     * gates (consider a call gate pointing at another guestos descriptor with 
   7.146 +     * DPL 0 -- this would get the OS ring-0 privileges).
   7.147 +     */
   7.148 +    if ( (b & _SEGMENT_DPL) == 0 )
   7.149 +        goto bad;
   7.150 +
   7.151 +    if ( !(b & _SEGMENT_S) )
   7.152 +    {
   7.153 +        /*
   7.154 +         * System segment:
   7.155 +         *  1. Don't allow interrupt or trap gates as they belong in the IDT.
   7.156 +         *  2. Don't allow TSS descriptors or task gates as we don't
   7.157 +         *     virtualise x86 tasks.
   7.158 +         *  3. Don't allow LDT descriptors because they're unnecessary and
   7.159 +         *     I'm uneasy about allowing an LDT page to contain LDT
   7.160 +         *     descriptors. In any case, Xen automatically creates the
   7.161 +         *     required descriptor when reloading the LDT register.
   7.162 +         *  4. We allow call gates but they must not jump to a private segment.
   7.163 +         */
   7.164 +
   7.165 +        /* Disallow everything but call gates. */
   7.166 +        if ( (b & _SEGMENT_TYPE) != 0xc00 )
   7.167 +            goto bad;
   7.168 +
   7.169 +        /* Can't allow far jump to a Xen-private segment. */
   7.170 +        if ( !VALID_CODESEL(a>>16) )
   7.171 +            goto bad;
   7.172 +
   7.173 +        /* Reserved bits must be zero. */
   7.174 +        if ( (b & 0xe0) != 0 )
   7.175 +            goto bad;
   7.176 +        
   7.177 +        /* No base/limit check is needed for a call gate. */
   7.178 +        goto good;
   7.179 +    }
   7.180 +    
   7.181 +    /* Check that base is at least a page away from Xen-private area. */
   7.182 +    base  = (b&(0xff<<24)) | ((b&0xff)<<16) | (a>>16);
   7.183 +    if ( base >= (PAGE_OFFSET - PAGE_SIZE) )
   7.184 +        goto bad;
   7.185 +
   7.186 +    /* Check and truncate the limit if necessary. */
   7.187 +    limit = (b&0xf0000) | (a&0xffff);
   7.188 +    limit++; /* We add one because limit is inclusive. */
   7.189 +    if ( (b & _SEGMENT_G) )
   7.190 +        limit <<= 12;
   7.191 +
   7.192 +    if ( (b & (_SEGMENT_CODE | _SEGMENT_EC)) == _SEGMENT_EC )
   7.193 +    {
   7.194 +        /*
   7.195 +         * Grows-down limit check. 
   7.196 +         * NB. limit == 0xFFFFF provides no access      (if G=1).
   7.197 +         *     limit == 0x00000 provides 4GB-4kB access (if G=1).
   7.198 +         */
   7.199 +        if ( (base + limit) > base )
   7.200 +        {
   7.201 +            limit = -(base & PAGE_MASK);
   7.202 +            goto truncate;
   7.203 +        }
   7.204 +    }
   7.205 +    else
   7.206 +    {
   7.207 +        /*
   7.208 +         * Grows-up limit check.
   7.209 +         * NB. limit == 0xFFFFF provides 4GB access (if G=1).
   7.210 +         *     limit == 0x00000 provides 4kB access (if G=1).
   7.211 +         */
   7.212 +        if ( ((base + limit) <= base) || 
   7.213 +             ((base + limit) > PAGE_OFFSET) )
   7.214 +        {
   7.215 +            limit = PAGE_OFFSET - base;
   7.216 +        truncate:
   7.217 +            if ( !(b & _SEGMENT_G) )
   7.218 +                goto bad; /* too dangerous; too hard to work out... */
   7.219 +            limit = (limit >> 12) - 1;
   7.220 +            d[0] &= ~0x0ffff; d[0] |= limit & 0x0ffff;
   7.221 +            d[1] &= ~0xf0000; d[1] |= limit & 0xf0000;
   7.222 +        }
   7.223 +    }
   7.224 +
   7.225 + good:
   7.226 +    return 1;
   7.227 + bad:
   7.228 +    return 0;
   7.229 +}
   7.230 +
   7.231 +
   7.232 +void destroy_gdt(struct domain *d)
   7.233 +{
   7.234 +    int i;
   7.235 +    unsigned long pfn;
   7.236 +
   7.237 +    for ( i = 0; i < 16; i++ )
   7.238 +    {
   7.239 +        if ( (pfn = l1_pgentry_to_pagenr(d->mm.perdomain_pt[i])) != 0 )
   7.240 +            put_page_and_type(&frame_table[pfn]);
   7.241 +        d->mm.perdomain_pt[i] = mk_l1_pgentry(0);
   7.242 +    }
   7.243 +}
   7.244 +
   7.245 +
   7.246 +long set_gdt(struct domain *d, 
   7.247 +             unsigned long *frames,
   7.248 +             unsigned int entries)
   7.249 +{
   7.250 +    /* NB. There are 512 8-byte entries per GDT page. */
   7.251 +    int i = 0, nr_pages = (entries + 511) / 512;
   7.252 +    struct desc_struct *vgdt;
   7.253 +    unsigned long pfn;
   7.254 +
   7.255 +    /* Check the first page in the new GDT. */
   7.256 +    if ( (pfn = frames[0]) >= max_page )
   7.257 +        goto fail;
   7.258 +
   7.259 +    /* The first page is special because Xen owns a range of entries in it. */
   7.260 +    if ( !get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) )
   7.261 +    {
   7.262 +        /* GDT checks failed: try zapping the Xen reserved entries. */
   7.263 +        if ( !get_page_and_type(&frame_table[pfn], d, PGT_writable_page) )
   7.264 +            goto fail;
   7.265 +        vgdt = map_domain_mem(pfn << PAGE_SHIFT);
   7.266 +        memset(vgdt + FIRST_RESERVED_GDT_ENTRY, 0,
   7.267 +               NR_RESERVED_GDT_ENTRIES*8);
   7.268 +        unmap_domain_mem(vgdt);
   7.269 +        put_page_and_type(&frame_table[pfn]);
   7.270 +
   7.271 +        /* Okay, we zapped the entries. Now try the GDT checks again. */
   7.272 +        if ( !get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) )
   7.273 +            goto fail;
   7.274 +    }
   7.275 +
   7.276 +    /* Check the remaining pages in the new GDT. */
   7.277 +    for ( i = 1; i < nr_pages; i++ )
   7.278 +        if ( ((pfn = frames[i]) >= max_page) ||
   7.279 +             !get_page_and_type(&frame_table[pfn], d, PGT_gdt_page) )
   7.280 +            goto fail;
   7.281 +
   7.282 +    /* Copy reserved GDT entries to the new GDT. */
   7.283 +    vgdt = map_domain_mem(frames[0] << PAGE_SHIFT);
   7.284 +    memcpy(vgdt + FIRST_RESERVED_GDT_ENTRY, 
   7.285 +           gdt_table + FIRST_RESERVED_GDT_ENTRY, 
   7.286 +           NR_RESERVED_GDT_ENTRIES*8);
   7.287 +    unmap_domain_mem(vgdt);
   7.288 +
   7.289 +    /* Tear down the old GDT. */
   7.290 +    destroy_gdt(d);
   7.291 +
   7.292 +    /* Install the new GDT. */
   7.293 +    for ( i = 0; i < nr_pages; i++ )
   7.294 +        d->mm.perdomain_pt[i] =
   7.295 +            mk_l1_pgentry((frames[i] << PAGE_SHIFT) | __PAGE_HYPERVISOR);
   7.296 +
   7.297 +    SET_GDT_ADDRESS(d, GDT_VIRT_START);
   7.298 +    SET_GDT_ENTRIES(d, entries);
   7.299 +
   7.300 +    return 0;
   7.301 +
   7.302 + fail:
   7.303 +    while ( i-- > 0 )
   7.304 +        put_page_and_type(&frame_table[frames[i]]);
   7.305 +    return -EINVAL;
   7.306 +}
   7.307 +
   7.308 +
   7.309 +long do_set_gdt(unsigned long *frame_list, unsigned int entries)
   7.310 +{
   7.311 +    int nr_pages = (entries + 511) / 512;
   7.312 +    unsigned long frames[16];
   7.313 +    long ret;
   7.314 +
   7.315 +    if ( (entries <= LAST_RESERVED_GDT_ENTRY) || (entries > 8192) ) 
   7.316 +        return -EINVAL;
   7.317 +    
   7.318 +    if ( copy_from_user(frames, frame_list, nr_pages * sizeof(unsigned long)) )
   7.319 +        return -EFAULT;
   7.320 +
   7.321 +    if ( (ret = set_gdt(current, frames, entries)) == 0 )
   7.322 +    {
   7.323 +        local_flush_tlb();
   7.324 +        __asm__ __volatile__ ("lgdt %0" : "=m" (*current->mm.gdt));
   7.325 +    }
   7.326 +
   7.327 +    return ret;
   7.328 +}
   7.329 +
   7.330 +
   7.331 +long do_update_descriptor(
   7.332 +    unsigned long pa, unsigned long word1, unsigned long word2)
   7.333 +{
   7.334 +    unsigned long *gdt_pent, pfn = pa >> PAGE_SHIFT, d[2];
   7.335 +    struct pfn_info *page;
   7.336 +    long ret = -EINVAL;
   7.337 +
   7.338 +    d[0] = word1;
   7.339 +    d[1] = word2;
   7.340 +
   7.341 +    if ( (pa & 7) || (pfn >= max_page) || !check_descriptor(d) )
   7.342 +        return -EINVAL;
   7.343 +
   7.344 +    page = &frame_table[pfn];
   7.345 +    if ( unlikely(!get_page(page, current)) )
   7.346 +        return -EINVAL;
   7.347 +
   7.348 +    /* Check if the given frame is in use in an unsafe context. */
   7.349 +    switch ( page->u.inuse.type_info & PGT_type_mask )
   7.350 +    {
   7.351 +    case PGT_gdt_page:
   7.352 +        /* Disallow updates of Xen-reserved descriptors in the current GDT. */
   7.353 +        if ( (l1_pgentry_to_pagenr(current->mm.perdomain_pt[0]) == pfn) &&
   7.354 +             (((pa&(PAGE_SIZE-1))>>3) >= FIRST_RESERVED_GDT_ENTRY) &&
   7.355 +             (((pa&(PAGE_SIZE-1))>>3) <= LAST_RESERVED_GDT_ENTRY) )
   7.356 +            goto out;
   7.357 +        if ( unlikely(!get_page_type(page, PGT_gdt_page)) )
   7.358 +            goto out;
   7.359 +        break;
   7.360 +    case PGT_ldt_page:
   7.361 +        if ( unlikely(!get_page_type(page, PGT_ldt_page)) )
   7.362 +            goto out;
   7.363 +        break;
   7.364 +    default:
   7.365 +        if ( unlikely(!get_page_type(page, PGT_writable_page)) )
   7.366 +            goto out;
   7.367 +        break;
   7.368 +    }
   7.369 +
   7.370 +    /* All is good so make the update. */
   7.371 +    gdt_pent = map_domain_mem(pa);
   7.372 +    memcpy(gdt_pent, d, 8);
   7.373 +    unmap_domain_mem(gdt_pent);
   7.374 +
   7.375 +    put_page_type(page);
   7.376 +
   7.377 +    ret = 0; /* success */
   7.378 +
   7.379 + out:
   7.380 +    put_page(page);
   7.381 +    return ret;
   7.382 +}
   7.383 +
   7.384 +#ifdef MEMORY_GUARD
   7.385 +
   7.386 +void *memguard_init(void *heap_start)
   7.387 +{
   7.388 +    l1_pgentry_t *l1;
   7.389 +    int i, j;
   7.390 +
   7.391 +    /* Round the allocation pointer up to a page boundary. */
   7.392 +    heap_start = (void *)(((unsigned long)heap_start + (PAGE_SIZE-1)) & 
   7.393 +                          PAGE_MASK);
   7.394 +
   7.395 +    /* Memory guarding is incompatible with super pages. */
   7.396 +    for ( i = 0; i < (xenheap_phys_end >> L2_PAGETABLE_SHIFT); i++ )
   7.397 +    {
   7.398 +        l1 = (l1_pgentry_t *)heap_start;
   7.399 +        heap_start = (void *)((unsigned long)heap_start + PAGE_SIZE);
   7.400 +        for ( j = 0; j < ENTRIES_PER_L1_PAGETABLE; j++ )
   7.401 +            l1[j] = mk_l1_pgentry((i << L2_PAGETABLE_SHIFT) |
   7.402 +                                   (j << L1_PAGETABLE_SHIFT) | 
   7.403 +                                  __PAGE_HYPERVISOR);
   7.404 +        idle_pg_table[i] = idle_pg_table[i + l2_table_offset(PAGE_OFFSET)] =
   7.405 +            mk_l2_pgentry(virt_to_phys(l1) | __PAGE_HYPERVISOR);
   7.406 +    }
   7.407 +
   7.408 +    return heap_start;
   7.409 +}
   7.410 +
   7.411 +static void __memguard_change_range(void *p, unsigned long l, int guard)
   7.412 +{
   7.413 +    l1_pgentry_t *l1;
   7.414 +    l2_pgentry_t *l2;
   7.415 +    unsigned long _p = (unsigned long)p;
   7.416 +    unsigned long _l = (unsigned long)l;
   7.417 +
   7.418 +    /* Ensure we are dealing with a page-aligned whole number of pages. */
   7.419 +    ASSERT((_p&PAGE_MASK) != 0);
   7.420 +    ASSERT((_l&PAGE_MASK) != 0);
   7.421 +    ASSERT((_p&~PAGE_MASK) == 0);
   7.422 +    ASSERT((_l&~PAGE_MASK) == 0);
   7.423 +
   7.424 +    while ( _l != 0 )
   7.425 +    {
   7.426 +        l2  = &idle_pg_table[l2_table_offset(_p)];
   7.427 +        l1  = l2_pgentry_to_l1(*l2) + l1_table_offset(_p);
   7.428 +        if ( guard )
   7.429 +            *l1 = mk_l1_pgentry(l1_pgentry_val(*l1) & ~_PAGE_PRESENT);
   7.430 +        else
   7.431 +            *l1 = mk_l1_pgentry(l1_pgentry_val(*l1) | _PAGE_PRESENT);
   7.432 +        _p += PAGE_SIZE;
   7.433 +        _l -= PAGE_SIZE;
   7.434 +    }
   7.435 +}
   7.436 +
   7.437 +void memguard_guard_range(void *p, unsigned long l)
   7.438 +{
   7.439 +    __memguard_change_range(p, l, 1);
   7.440 +    local_flush_tlb();
   7.441 +}
   7.442 +
   7.443 +void memguard_unguard_range(void *p, unsigned long l)
   7.444 +{
   7.445 +    __memguard_change_range(p, l, 0);
   7.446 +}
   7.447 +
   7.448 +int memguard_is_guarded(void *p)
   7.449 +{
   7.450 +    l1_pgentry_t *l1;
   7.451 +    l2_pgentry_t *l2;
   7.452 +    unsigned long _p = (unsigned long)p;
   7.453 +    l2  = &idle_pg_table[l2_table_offset(_p)];
   7.454 +    l1  = l2_pgentry_to_l1(*l2) + l1_table_offset(_p);
   7.455 +    return !(l1_pgentry_val(*l1) & _PAGE_PRESENT);
   7.456 +}
   7.457 +
   7.458 +#endif
     8.1 --- a/xen/arch/x86/x86_64/xen.lds	Tue Dec 14 14:47:08 2004 +0000
     8.2 +++ b/xen/arch/x86/x86_64/xen.lds	Tue Dec 14 16:39:51 2004 +0000
     8.3 @@ -28,6 +28,11 @@ SECTIONS
     8.4    __ex_table : { *(__ex_table) } :text
     8.5    __stop___ex_table = .;
     8.6  
     8.7 +  . = ALIGN(16);                /* Pre-exception table */
     8.8 +  __start___pre_ex_table = .;
     8.9 +  __pre_ex_table : { *(__pre_ex_table) } :text
    8.10 +  __stop___pre_ex_table = .;
    8.11 +
    8.12    __start___ksymtab = .;	/* Kernel symbol table */
    8.13    __ksymtab : { *(__ksymtab) } :text
    8.14    __stop___ksymtab = .;
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/xen/include/asm-x86/asm_defns.h	Tue Dec 14 16:39:51 2004 +0000
     9.3 @@ -0,0 +1,18 @@
     9.4 +
     9.5 +#ifndef __X86_ASM_DEFNS_H__
     9.6 +#define __X86_ASM_DEFNS_H__
     9.7 +
     9.8 +/* NB. Auto-generated from arch/.../asm-offsets.c */
     9.9 +#include <asm/asm-offsets.h>
    9.10 +#include <asm/processor.h>
    9.11 +
    9.12 +#define __STR(x) #x
    9.13 +#define STR(x) __STR(x)
    9.14 +
    9.15 +#ifdef __x86_64__
    9.16 +#include <asm/x86_64/asm_defns.h>
    9.17 +#else
    9.18 +#include <asm/x86_32/asm_defns.h>
    9.19 +#endif
    9.20 +
    9.21 +#endif /* __X86_ASM_DEFNS_H__ */
    10.1 --- a/xen/include/asm-x86/irq.h	Tue Dec 14 14:47:08 2004 +0000
    10.2 +++ b/xen/include/asm-x86/irq.h	Tue Dec 14 16:39:51 2004 +0000
    10.3 @@ -5,7 +5,7 @@
    10.4  
    10.5  #include <xen/config.h>
    10.6  #include <asm/atomic.h>
    10.7 -#include <asm/x86_32/asm_defns.h>
    10.8 +#include <asm/asm_defns.h>
    10.9  
   10.10  extern void disable_irq(unsigned int);
   10.11  extern void disable_irq_nosync(unsigned int);
    11.1 --- a/xen/include/asm-x86/multicall.h	Tue Dec 14 14:47:08 2004 +0000
    11.2 +++ b/xen/include/asm-x86/multicall.h	Tue Dec 14 16:39:51 2004 +0000
    11.3 @@ -5,7 +5,13 @@
    11.4  #ifndef __ASM_X86_MULTICALL_H__
    11.5  #define __ASM_X86_MULTICALL_H__
    11.6  
    11.7 -#include <asm-x86/x86_32/asm_defns.h>
    11.8 +#include <asm/asm_defns.h>
    11.9 +
   11.10 +#ifdef __x86_64__
   11.11 +
   11.12 +#define do_multicall_call(_call) BUG()
   11.13 +
   11.14 +#else
   11.15  
   11.16  #define do_multicall_call(_call)                       \
   11.17      do {                                               \
   11.18 @@ -23,4 +29,6 @@
   11.19              : : "b" (_call) : "eax", "ecx", "edx" );   \
   11.20      } while ( 0 )
   11.21  
   11.22 +#endif
   11.23 +
   11.24  #endif /* __ASM_X86_MULTICALL_H__ */
    12.1 --- a/xen/include/asm-x86/processor.h	Tue Dec 14 14:47:08 2004 +0000
    12.2 +++ b/xen/include/asm-x86/processor.h	Tue Dec 14 16:39:51 2004 +0000
    12.3 @@ -254,18 +254,18 @@ static inline unsigned int cpuid_edx(uns
    12.4  })
    12.5  
    12.6  #define write_cr0(x) \
    12.7 -	__asm__("mov"__OS" %0,%%cr0": :"r" (x));
    12.8 +	__asm__("mov"__OS" %0,%%cr0": :"r" ((unsigned long)x));
    12.9  
   12.10  #define read_cr4() ({ \
   12.11 -	unsigned int __dummy; \
   12.12 +	unsigned long __dummy; \
   12.13  	__asm__( \
   12.14 -		"movl %%cr4,%0\n\t" \
   12.15 +		"mov"__OS" %%cr4,%0\n\t" \
   12.16  		:"=r" (__dummy)); \
   12.17  	__dummy; \
   12.18  })
   12.19  
   12.20  #define write_cr4(x) \
   12.21 -	__asm__("movl %0,%%cr4": :"r" (x));
   12.22 +	__asm__("mov"__OS" %0,%%cr4": :"r" ((unsigned long)x));
   12.23  
   12.24  /*
   12.25   * Save the cr4 feature set we're using (ie
   12.26 @@ -290,7 +290,7 @@ static inline void clear_in_cr4 (unsigne
   12.27      mmu_cr4_features &= ~mask;
   12.28      __asm__("mov"__OS" %%cr4,%%"__OP"ax\n\t"
   12.29              "and"__OS" %0,%%"__OP"ax\n\t"
   12.30 -            "movl"__OS" %%"__OP"ax,%%cr4\n"
   12.31 +            "mov"__OS" %%"__OP"ax,%%cr4\n"
   12.32              : : "irg" (~mask)
   12.33              :"ax");
   12.34  }
    13.1 --- a/xen/include/asm-x86/uaccess.h	Tue Dec 14 14:47:08 2004 +0000
    13.2 +++ b/xen/include/asm-x86/uaccess.h	Tue Dec 14 16:39:51 2004 +0000
    13.3 @@ -1,6 +1,32 @@
    13.4 +
    13.5 +#ifndef __X86_UACCESS_H__
    13.6 +#define __X86_UACCESS_H__
    13.7  
    13.8  #ifdef __x86_64__
    13.9  #include <asm/x86_64/uaccess.h>
   13.10  #else
   13.11  #include <asm/x86_32/uaccess.h>
   13.12  #endif
   13.13 +
   13.14 +/*
   13.15 + * The exception table consists of pairs of addresses: the first is the
   13.16 + * address of an instruction that is allowed to fault, and the second is
   13.17 + * the address at which the program should continue.  No registers are
   13.18 + * modified, so it is entirely up to the continuation code to figure out
   13.19 + * what to do.
   13.20 + *
   13.21 + * All the routines below use bits of fixup code that are out of line
   13.22 + * with the main instruction path.  This means when everything is well,
   13.23 + * we don't even have to jump over them.  Further, they do not intrude
   13.24 + * on our cache or tlb entries.
   13.25 + */
   13.26 +
   13.27 +struct exception_table_entry
   13.28 +{
   13.29 +	unsigned long insn, fixup;
   13.30 +};
   13.31 +
   13.32 +extern unsigned long search_exception_table(unsigned long);
   13.33 +extern void sort_exception_tables(void);
   13.34 +
   13.35 +#endif /* __X86_UACCESS_H__ */
    14.1 --- a/xen/include/asm-x86/x86_32/asm_defns.h	Tue Dec 14 14:47:08 2004 +0000
    14.2 +++ b/xen/include/asm-x86/x86_32/asm_defns.h	Tue Dec 14 16:39:51 2004 +0000
    14.3 @@ -1,12 +1,5 @@
    14.4 -#ifndef __ASM_DEFNS_H__
    14.5 -#define __ASM_DEFNS_H__
    14.6 -
    14.7 -/* NB. Auto-generated from arch/.../asm-offsets.c */
    14.8 -#include <asm/asm-offsets.h>
    14.9 -#include <asm/processor.h>
   14.10 -
   14.11 -#define __STR(x) #x
   14.12 -#define STR(x) __STR(x)
   14.13 +#ifndef __X86_32_ASM_DEFNS_H__
   14.14 +#define __X86_32_ASM_DEFNS_H__
   14.15  
   14.16  /* Maybe auto-generate the following two cases (quoted vs. unquoted). */
   14.17  #ifndef __ASSEMBLY__
   14.18 @@ -85,4 +78,4 @@
   14.19  
   14.20  #endif
   14.21  
   14.22 -#endif /* __ASM_DEFNS_H__ */
   14.23 +#endif /* __X86_32_ASM_DEFNS_H__ */
    15.1 --- a/xen/include/asm-x86/x86_32/uaccess.h	Tue Dec 14 14:47:08 2004 +0000
    15.2 +++ b/xen/include/asm-x86/x86_32/uaccess.h	Tue Dec 14 16:39:51 2004 +0000
    15.3 @@ -69,27 +69,6 @@ extern struct movsl_mask {
    15.4  #define array_access_ok(type,addr,count,size) \
    15.5      (likely(count < (~0UL/size)) && access_ok(type,addr,count*size))
    15.6  
    15.7 -/*
    15.8 - * The exception table consists of pairs of addresses: the first is the
    15.9 - * address of an instruction that is allowed to fault, and the second is
   15.10 - * the address at which the program should continue.  No registers are
   15.11 - * modified, so it is entirely up to the continuation code to figure out
   15.12 - * what to do.
   15.13 - *
   15.14 - * All the routines below use bits of fixup code that are out of line
   15.15 - * with the main instruction path.  This means when everything is well,
   15.16 - * we don't even have to jump over them.  Further, they do not intrude
   15.17 - * on our cache or tlb entries.
   15.18 - */
   15.19 -
   15.20 -struct exception_table_entry
   15.21 -{
   15.22 -	unsigned long insn, fixup;
   15.23 -};
   15.24 -
   15.25 -extern unsigned long search_exception_table(unsigned long);
   15.26 -extern void sort_exception_tables(void);
   15.27 -
   15.28  /**
   15.29   * get_user: - Get a simple variable from user space.
   15.30   * @x:   Variable to store result.
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/xen/include/asm-x86/x86_64/asm_defns.h	Tue Dec 14 16:39:51 2004 +0000
    16.3 @@ -0,0 +1,6 @@
    16.4 +#ifndef __X86_64_ASM_DEFNS_H__
    16.5 +#define __X86_64_ASM_DEFNS_H__
    16.6 +
    16.7 +#define SAVE_ALL(_r) ""
    16.8 +
    16.9 +#endif /* __X86_64_ASM_DEFNS_H__ */
    17.1 --- a/xen/include/asm-x86/x86_64/uaccess.h	Tue Dec 14 14:47:08 2004 +0000
    17.2 +++ b/xen/include/asm-x86/x86_64/uaccess.h	Tue Dec 14 16:39:51 2004 +0000
    17.3 @@ -35,31 +35,15 @@
    17.4  
    17.5  #define access_ok(type, addr, size) (__range_not_ok(addr,size) == 0)
    17.6  
    17.7 +#define array_access_ok(type,addr,count,size)                    \
    17.8 +    (likely(sizeof(count) <= 4) /* disallow 64-bit counts */ &&  \
    17.9 +     access_ok(type,addr,count*size))
   17.10 +
   17.11  extern inline int verify_area(int type, const void __user * addr, unsigned long size)
   17.12  {
   17.13  	return access_ok(type,addr,size) ? 0 : -EFAULT;
   17.14  }
   17.15  
   17.16 -
   17.17 -/*
   17.18 - * The exception table consists of pairs of addresses: the first is the
   17.19 - * address of an instruction that is allowed to fault, and the second is
   17.20 - * the address at which the program should continue.  No registers are
   17.21 - * modified, so it is entirely up to the continuation code to figure out
   17.22 - * what to do.
   17.23 - *
   17.24 - * All the routines below use bits of fixup code that are out of line
   17.25 - * with the main instruction path.  This means when everything is well,
   17.26 - * we don't even have to jump over them.  Further, they do not intrude
   17.27 - * on our cache or tlb entries.
   17.28 - */
   17.29 -
   17.30 -struct exception_table_entry
   17.31 -{
   17.32 -	unsigned long insn, fixup;
   17.33 -};
   17.34 -
   17.35 -
   17.36  /*
   17.37   * These are the main single-value transfer routines.  They automatically
   17.38   * use the right size if we just have the right pointer type.