From 2f5ff9b8622cc26a2802da069f9a4c15f46bc40f Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Mon, 15 Jan 2007 14:32:25 +0000 Subject: [PATCH 01/22] [XEN] BSF/BSR set ZF not CF. Signed-off-by: Keir Fraser --- xen/arch/x86/x86_emulate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/x86_emulate.c b/xen/arch/x86/x86_emulate.c index de5c35287c..6690a394f0 100644 --- a/xen/arch/x86/x86_emulate.c +++ b/xen/arch/x86/x86_emulate.c @@ -2019,7 +2019,7 @@ x86_emulate( case 0xbc: /* bsf */ { int zf; - asm ( "bsf %2,%0; setc %b1" + asm ( "bsf %2,%0; setz %b1" : "=r" (dst.val), "=q" (zf) : "r" (src.val), "1" (0) ); _regs.eflags &= ~EFLG_ZF; @@ -2029,7 +2029,7 @@ x86_emulate( case 0xbd: /* bsr */ { int zf; - asm ( "bsr %2,%0; setc %b1" + asm ( "bsr %2,%0; setz %b1" : "=r" (dst.val), "=q" (zf) : "r" (src.val), "1" (0) ); _regs.eflags &= ~EFLG_ZF; From 12d473893b0f6f543282b054f82d7e2d4ec660e8 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Mon, 15 Jan 2007 15:43:20 +0000 Subject: [PATCH 02/22] [XEN] Allow stack-address-size to be specified differently from regular address-size in the emulator. Signed-off-by: Keir Fraser --- tools/tests/test_x86_emulator.c | 3 +- xen/arch/x86/mm.c | 3 +- xen/arch/x86/mm/shadow/common.c | 25 +++++++++++---- xen/arch/x86/x86_emulate.c | 53 ++++++++++++++++--------------- xen/include/asm-x86/x86_emulate.h | 7 ++-- 5 files changed, 56 insertions(+), 35 deletions(-) diff --git a/tools/tests/test_x86_emulator.c b/tools/tests/test_x86_emulator.c index 1ebe2bb6dd..2d8d49e43f 100644 --- a/tools/tests/test_x86_emulator.c +++ b/tools/tests/test_x86_emulator.c @@ -118,7 +118,8 @@ int main(int argc, char **argv) #endif ctxt.regs = ®s; - ctxt.address_bytes = 4; + ctxt.addr_size = 32; + ctxt.sp_size = 32; res = mmap((void *)0x100000, MMAP_SZ, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index a4b93f2b70..c095ba41a1 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -3376,7 +3376,8 @@ int ptwr_do_page_fault(struct vcpu *v, unsigned long addr, goto bail; ptwr_ctxt.ctxt.regs = guest_cpu_user_regs(); - ptwr_ctxt.ctxt.address_bytes = IS_COMPAT(d) ? 4 : sizeof(long); + ptwr_ctxt.ctxt.addr_size = ptwr_ctxt.ctxt.sp_size = + IS_COMPAT(d) ? 32 : BITS_PER_LONG; ptwr_ctxt.cr2 = addr; ptwr_ctxt.pte = pte; if ( x86_emulate(&ptwr_ctxt.ctxt, &ptwr_emulate_ops) ) diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c index 8cee158842..ac35c7e5cb 100644 --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -110,7 +110,7 @@ static int hvm_translate_linear_addr( unsigned long limit, addr = offset; uint32_t last_byte; - if ( sh_ctxt->ctxt.address_bytes != 8 ) + if ( sh_ctxt->ctxt.addr_size != 64 ) { /* * COMPATIBILITY MODE: Apply segment checks and add base. @@ -399,7 +399,7 @@ static struct x86_emulate_ops pv_shadow_emulator_ops = { struct x86_emulate_ops *shadow_init_emulation( struct sh_emulate_ctxt *sh_ctxt, struct cpu_user_regs *regs) { - struct segment_register *creg; + struct segment_register *creg, *sreg; struct vcpu *v = current; unsigned long addr; @@ -407,7 +407,7 @@ struct x86_emulate_ops *shadow_init_emulation( if ( !is_hvm_vcpu(v) ) { - sh_ctxt->ctxt.address_bytes = sizeof(long); + sh_ctxt->ctxt.addr_size = sh_ctxt->ctxt.sp_size = BITS_PER_LONG; return &pv_shadow_emulator_ops; } @@ -417,11 +417,24 @@ struct x86_emulate_ops *shadow_init_emulation( /* Work out the emulation mode. */ if ( hvm_long_mode_enabled(v) ) - sh_ctxt->ctxt.address_bytes = creg->attr.fields.l ? 8 : 4; + { + sh_ctxt->ctxt.addr_size = creg->attr.fields.l ? 64 : 32; + if ( (sh_ctxt->ctxt.sp_size = sh_ctxt->ctxt.addr_size) != 64 ) + { + sreg = hvm_get_seg_reg(x86_seg_ss, sh_ctxt); + sh_ctxt->ctxt.sp_size = sreg->attr.fields.db ? 32 : 16; + } + } else if ( regs->eflags & X86_EFLAGS_VM ) - sh_ctxt->ctxt.address_bytes = 2; + { + sh_ctxt->ctxt.addr_size = sh_ctxt->ctxt.sp_size = 16; + } else - sh_ctxt->ctxt.address_bytes = creg->attr.fields.db ? 4 : 2; + { + sreg = hvm_get_seg_reg(x86_seg_ss, sh_ctxt); + sh_ctxt->ctxt.addr_size = creg->attr.fields.db ? 32 : 16; + sh_ctxt->ctxt.sp_size = sreg->attr.fields.db ? 32 : 16; + } /* Attempt to prefetch whole instruction. */ sh_ctxt->insn_buf_bytes = diff --git a/xen/arch/x86/x86_emulate.c b/xen/arch/x86/x86_emulate.c index 6690a394f0..feeccd53de 100644 --- a/xen/arch/x86/x86_emulate.c +++ b/xen/arch/x86/x86_emulate.c @@ -443,10 +443,11 @@ do{ __asm__ __volatile__ ( \ }) #define insn_fetch_type(_type) ((_type)insn_fetch_bytes(sizeof(_type))) -#define _truncate_ea(ea, byte_width) \ -({ unsigned long __ea = (ea); \ - (((byte_width) == sizeof(unsigned long)) ? __ea : \ - (__ea & ((1UL << ((byte_width) << 3)) - 1))); \ +#define _truncate_ea(ea, byte_width) \ +({ unsigned long __ea = (ea); \ + unsigned int _width = (byte_width); \ + ((_width == sizeof(unsigned long)) ? __ea : \ + (__ea & ((1UL << (_width << 3)) - 1))); \ }) #define truncate_ea(ea) _truncate_ea((ea), ad_bytes) @@ -473,17 +474,28 @@ static int even_parity(uint8_t v) #define _register_address_increment(reg, inc, byte_width) \ do { \ int _inc = (inc); /* signed type ensures sign extension to long */ \ - if ( (byte_width) == sizeof(unsigned long) ) \ + unsigned int _width = (byte_width); \ + if ( _width == sizeof(unsigned long) ) \ (reg) += _inc; \ else if ( mode_64bit() ) \ - (reg) = ((reg) + _inc) & ((1UL << ((byte_width) << 3)) - 1); \ + (reg) = ((reg) + _inc) & ((1UL << (_width << 3)) - 1); \ else \ - (reg) = ((reg) & ~((1UL << ((byte_width) << 3)) - 1)) | \ - (((reg) + _inc) & ((1UL << ((byte_width) << 3)) - 1)); \ + (reg) = ((reg) & ~((1UL << (_width << 3)) - 1)) | \ + (((reg) + _inc) & ((1UL << (_width << 3)) - 1)); \ } while (0) #define register_address_increment(reg, inc) \ _register_address_increment((reg), (inc), ad_bytes) +#define sp_pre_dec(dec) ({ \ + _register_address_increment(_regs.esp, -(dec), ctxt->sp_size/8); \ + _truncate_ea(_regs.esp, ctxt->sp_size/8); \ +}) +#define sp_post_inc(inc) ({ \ + unsigned long __esp = _truncate_ea(_regs.esp, ctxt->sp_size/8); \ + _register_address_increment(_regs.esp, (inc), ctxt->sp_size/8); \ + __esp; \ +}) + #define jmp_rel(rel) \ do { \ _regs.eip += (int)(rel); \ @@ -679,7 +691,7 @@ x86_emulate( ea.mem.seg = x86_seg_ds; ea.mem.off = 0; - op_bytes = def_op_bytes = ad_bytes = def_ad_bytes = ctxt->address_bytes; + op_bytes = def_op_bytes = ad_bytes = def_ad_bytes = ctxt->addr_size/8; if ( op_bytes == 8 ) { op_bytes = def_op_bytes = 4; @@ -1194,10 +1206,9 @@ x86_emulate( /* 64-bit mode: POP defaults to a 64-bit operand. */ if ( mode_64bit() && (dst.bytes == 4) ) dst.bytes = 8; - if ( (rc = ops->read(x86_seg_ss, truncate_ea(_regs.esp), + if ( (rc = ops->read(x86_seg_ss, sp_post_inc(dst.bytes), &dst.val, dst.bytes, ctxt)) != 0 ) goto done; - register_address_increment(_regs.esp, dst.bytes); break; case 0xb0 ... 0xb7: /* mov imm8,r8 */ @@ -1488,8 +1499,7 @@ x86_emulate( &dst.val, 8, ctxt)) != 0 ) goto done; } - register_address_increment(_regs.esp, -dst.bytes); - if ( (rc = ops->write(x86_seg_ss, truncate_ea(_regs.esp), + if ( (rc = ops->write(x86_seg_ss, sp_pre_dec(dst.bytes), dst.val, dst.bytes, ctxt)) != 0 ) goto done; dst.type = OP_NONE; @@ -1644,10 +1654,9 @@ x86_emulate( dst.bytes = op_bytes; if ( mode_64bit() && (dst.bytes == 4) ) dst.bytes = 8; - if ( (rc = ops->read(x86_seg_ss, truncate_ea(_regs.esp), + if ( (rc = ops->read(x86_seg_ss, sp_post_inc(dst.bytes), &dst.val, dst.bytes, ctxt)) != 0 ) goto done; - register_address_increment(_regs.esp, dst.bytes); break; case 0x60: /* pusha */ { @@ -1657,11 +1666,9 @@ x86_emulate( _regs.esp, _regs.ebp, _regs.esi, _regs.edi }; generate_exception_if(mode_64bit(), EXC_UD); for ( i = 0; i < 8; i++ ) - if ( (rc = ops->write(x86_seg_ss, - truncate_ea(_regs.esp-(i+1)*op_bytes), + if ( (rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes), regs[i], op_bytes, ctxt)) != 0 ) goto done; - register_address_increment(_regs.esp, -8*op_bytes); break; } @@ -1674,11 +1681,9 @@ x86_emulate( (unsigned long *)&_regs.ecx, (unsigned long *)&_regs.eax }; generate_exception_if(mode_64bit(), EXC_UD); for ( i = 0; i < 8; i++ ) - if ( (rc = ops->read(x86_seg_ss, - truncate_ea(_regs.esp+i*op_bytes), + if ( (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes), regs[i], op_bytes, ctxt)) != 0 ) goto done; - register_address_increment(_regs.esp, 8*op_bytes); break; } @@ -1697,9 +1702,8 @@ x86_emulate( if ( mode_64bit() && (dst.bytes == 4) ) dst.bytes = 8; dst.val = src.val; - register_address_increment(_regs.esp, -dst.bytes); dst.mem.seg = x86_seg_ss; - dst.mem.off = truncate_ea(_regs.esp); + dst.mem.off = sp_pre_dec(dst.bytes); break; case 0x70 ... 0x7f: /* jcc (short) */ { @@ -1813,11 +1817,10 @@ x86_emulate( case 0xc3: /* ret (near) */ { int offset = (b == 0xc2) ? insn_fetch_type(uint16_t) : 0; op_bytes = mode_64bit() ? 8 : op_bytes; - if ( (rc = ops->read(x86_seg_ss, truncate_ea(_regs.esp), + if ( (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes + offset), &dst.val, op_bytes, ctxt)) != 0 ) goto done; _regs.eip = dst.val; - register_address_increment(_regs.esp, op_bytes + offset); break; } diff --git a/xen/include/asm-x86/x86_emulate.h b/xen/include/asm-x86/x86_emulate.h index 153bf14aac..45246b8044 100644 --- a/xen/include/asm-x86/x86_emulate.h +++ b/xen/include/asm-x86/x86_emulate.h @@ -150,8 +150,11 @@ struct x86_emulate_ctxt /* Register state before/after emulation. */ struct cpu_user_regs *regs; - /* Default address size in current execution mode (2, 4, or 8). */ - int address_bytes; + /* Default address size in current execution mode (16, 32, or 64). */ + unsigned int addr_size; + + /* Stack pointer width in bits (16, 32 or 64). */ + unsigned int sp_size; }; /* From 6127793b4cb670dff71bfa89082bdbc8c6db8576 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Mon, 15 Jan 2007 15:58:51 +0000 Subject: [PATCH 03/22] [HVM] Fix calculation of address size in long mode. Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/svm/svm.c | 4 ++-- xen/arch/x86/hvm/vmx/vmx.c | 7 +++---- xen/arch/x86/mm/shadow/common.c | 9 ++------- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index 2a3e6370d6..ba3121618e 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -482,8 +482,8 @@ static int svm_guest_x86_mode(struct vcpu *v) { struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - if ( vmcb->efer & EFER_LMA ) - return (vmcb->cs.attr.fields.l ? 8 : 4); + if ( (vmcb->efer & EFER_LMA) && vmcb->cs.attr.fields.l ) + return 8; if ( svm_realmode(v) ) return 2; diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 74e0776016..a665367c6d 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -491,8 +491,7 @@ static unsigned long vmx_get_segment_base(struct vcpu *v, enum x86_segment seg) ASSERT(v == current); #ifdef __x86_64__ - if ( vmx_long_mode_enabled(v) && - (__vmread(GUEST_CS_AR_BYTES) & (1u<<13)) ) + if ( vmx_long_mode_enabled(v) && (__vmread(GUEST_CS_AR_BYTES) & (1u<<13)) ) long_mode = 1; #endif @@ -667,8 +666,8 @@ static int vmx_guest_x86_mode(struct vcpu *v) cs_ar_bytes = __vmread(GUEST_CS_AR_BYTES); - if ( vmx_long_mode_enabled(v) ) - return ((cs_ar_bytes & (1u<<13)) ? 8 : 4); + if ( vmx_long_mode_enabled(v) && (cs_ar_bytes & (1u<<13)) ) + return 8; if ( vmx_realmode(v) ) return 2; diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c index ac35c7e5cb..115ad74d72 100644 --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -416,14 +416,9 @@ struct x86_emulate_ops *shadow_init_emulation( creg = hvm_get_seg_reg(x86_seg_cs, sh_ctxt); /* Work out the emulation mode. */ - if ( hvm_long_mode_enabled(v) ) + if ( hvm_long_mode_enabled(v) && creg->attr.fields.l ) { - sh_ctxt->ctxt.addr_size = creg->attr.fields.l ? 64 : 32; - if ( (sh_ctxt->ctxt.sp_size = sh_ctxt->ctxt.addr_size) != 64 ) - { - sreg = hvm_get_seg_reg(x86_seg_ss, sh_ctxt); - sh_ctxt->ctxt.sp_size = sreg->attr.fields.db ? 32 : 16; - } + sh_ctxt->ctxt.addr_size = sh_ctxt->ctxt.sp_size = 64; } else if ( regs->eflags & X86_EFLAGS_VM ) { From d50a0b66da607f0076fc4231bd13d121f7de701f Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Mon, 15 Jan 2007 16:04:32 +0000 Subject: [PATCH 04/22] [PYGRUB] Make the boot-choice timeout actually time out. Signed-off-by: Tim Deegan --- tools/pygrub/src/pygrub | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/pygrub/src/pygrub b/tools/pygrub/src/pygrub index 13b05d9a67..a0de67df67 100644 --- a/tools/pygrub/src/pygrub +++ b/tools/pygrub/src/pygrub @@ -405,6 +405,9 @@ class Grub: c = self.screen.getch() if mytime != -1: mytime += 1 + if mytime >= int(timeout): + self.isdone = True + break # handle keypresses if c == ord('c'): From 8d6fcabc22dd8893359a7a95b131acd470e8815d Mon Sep 17 00:00:00 2001 From: Steven Hand Date: Mon, 15 Jan 2007 18:07:32 +0000 Subject: [PATCH 05/22] Comment fix. Signed-off-by: Steven Hand --- tools/libxc/xc_linux_build.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c index 8066d5a047..a92e77a8a6 100644 --- a/tools/libxc/xc_linux_build.c +++ b/tools/libxc/xc_linux_build.c @@ -741,7 +741,7 @@ static int setup_guest(int xc_handle, /* * Enable shadow translate mode. This must happen after * populate physmap because the p2m reservation is based on - * the domains current memory allocation. + * the domain's current memory allocation. */ if ( xc_shadow_control(xc_handle, dom, XEN_DOMCTL_SHADOW_OP_ENABLE_TRANSLATE, From c5d238206dd1aa8f64e10efe12f031766ebf1e90 Mon Sep 17 00:00:00 2001 From: Steven Hand Date: Mon, 15 Jan 2007 18:09:16 +0000 Subject: [PATCH 06/22] Remove bogus sanity check from xc_linux_save. (a guest from another host (or an earlier time) can quite validly have a max_mfn bigger the current max on this host) Signed-off-by: Steven Hand --- tools/libxc/xc_linux_save.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tools/libxc/xc_linux_save.c b/tools/libxc/xc_linux_save.c index 7ca8453848..ef64d1ef50 100644 --- a/tools/libxc/xc_linux_save.c +++ b/tools/libxc/xc_linux_save.c @@ -660,13 +660,6 @@ int xc_linux_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, goto out; } - /* cheesy sanity check */ - if ((info.max_memkb >> (PAGE_SHIFT - 10)) > max_mfn) { - ERROR("Invalid state record -- pfn count out of range: %lu", - (info.max_memkb >> (PAGE_SHIFT - 10))); - goto out; - } - /* Map the shared info frame */ if(!(live_shinfo = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ, shared_info_frame))) { From 236c16423bdc5cdb43f120b8d0c4ee4174cef0cb Mon Sep 17 00:00:00 2001 From: Steven Hand Date: Tue, 16 Jan 2007 10:02:50 +0000 Subject: [PATCH 07/22] Enable lazy (on-demand) allocation of memory to a guest being restored; this means that ballooned down domains only require as much memory as is currently being used (rather than their max) when being restored from save, or when being migrated. Signed-off-by: Steven Hand --- tools/libxc/xc_linux_restore.c | 191 ++++++++++++++++-------- tools/python/xen/xend/XendCheckpoint.py | 8 +- 2 files changed, 137 insertions(+), 62 deletions(-) diff --git a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c index 827c45693e..10e03971ab 100644 --- a/tools/libxc/xc_linux_restore.c +++ b/tools/libxc/xc_linux_restore.c @@ -12,7 +12,7 @@ #include "xg_private.h" #include "xg_save_restore.h" -/* max mfn of the whole machine */ +/* max mfn of the current host machine */ static unsigned long max_mfn; /* virtual starting address of the hypervisor */ @@ -30,6 +30,9 @@ static xen_pfn_t *live_p2m = NULL; /* A table mapping each PFN to its new MFN. */ static xen_pfn_t *p2m = NULL; +/* A table of P2M mappings in the current region */ +static xen_pfn_t *p2m_batch = NULL; + static ssize_t read_exact(int fd, void *buf, size_t count) @@ -57,46 +60,78 @@ read_exact(int fd, void *buf, size_t count) ** This function inverts that operation, replacing the pfn values with ** the (now known) appropriate mfn values. */ -static int uncanonicalize_pagetable(unsigned long type, void *page) +static int uncanonicalize_pagetable(int xc_handle, uint32_t dom, + unsigned long type, void *page) { int i, pte_last; unsigned long pfn; uint64_t pte; + int nr_mfns = 0; pte_last = PAGE_SIZE / ((pt_levels == 2)? 4 : 8); - /* Now iterate through the page table, uncanonicalizing each PTE */ + /* First pass: work out how many (if any) MFNs we need to alloc */ + for(i = 0; i < pte_last; i++) { + + if(pt_levels == 2) + pte = ((uint32_t *)page)[i]; + else + pte = ((uint64_t *)page)[i]; + + /* XXX SMH: below needs fixing for PROT_NONE etc */ + if(!(pte & _PAGE_PRESENT)) + continue; + + pfn = (pte >> PAGE_SHIFT) & 0xffffffff; + + if(pfn >= max_pfn) { + /* This "page table page" is probably not one; bail. */ + ERROR("Frame number in type %lu page table is out of range: " + "i=%d pfn=0x%lx max_pfn=%lu", + type >> 28, i, pfn, max_pfn); + return 0; + } + + if(p2m[pfn] == INVALID_P2M_ENTRY) { + /* Have a 'valid' PFN without a matching MFN - need to alloc */ + p2m_batch[nr_mfns++] = pfn; + } + } + + + /* Alllocate the requistite number of mfns */ + if (nr_mfns && xc_domain_memory_populate_physmap( + xc_handle, dom, nr_mfns, 0, 0, p2m_batch) != 0) { + ERROR("Failed to allocate memory for batch.!\n"); + errno = ENOMEM; + return 0; + } + + /* Second pass: uncanonicalize each present PTE */ + nr_mfns = 0; for(i = 0; i < pte_last; i++) { if(pt_levels == 2) pte = ((uint32_t *)page)[i]; else pte = ((uint64_t *)page)[i]; + + /* XXX SMH: below needs fixing for PROT_NONE etc */ + if(!(pte & _PAGE_PRESENT)) + continue; + + pfn = (pte >> PAGE_SHIFT) & 0xffffffff; + + if(p2m[pfn] == INVALID_P2M_ENTRY) + p2m[pfn] = p2m_batch[nr_mfns++]; - if(pte & _PAGE_PRESENT) { + pte &= 0xffffff0000000fffULL; + pte |= (uint64_t)p2m[pfn] << PAGE_SHIFT; - pfn = (pte >> PAGE_SHIFT) & 0xffffffff; - - if(pfn >= max_pfn) { - /* This "page table page" is probably not one; bail. */ - ERROR("Frame number in type %lu page table is out of range: " - "i=%d pfn=0x%lx max_pfn=%lu", - type >> 28, i, pfn, max_pfn); - return 0; - } - - - pte &= 0xffffff0000000fffULL; - pte |= (uint64_t)p2m[pfn] << PAGE_SHIFT; - - if(pt_levels == 2) - ((uint32_t *)page)[i] = (uint32_t)pte; - else - ((uint64_t *)page)[i] = (uint64_t)pte; - - - - } + if(pt_levels == 2) + ((uint32_t *)page)[i] = (uint32_t)pte; + else + ((uint64_t *)page)[i] = (uint64_t)pte; } return 1; @@ -140,6 +175,7 @@ int xc_linux_restore(int xc_handle, int io_fd, /* A temporary mapping of the guest's start_info page. */ start_info_t *start_info; + /* Our mapping of the current region (batch) */ char *region_base; xc_mmu_t *mmu = NULL; @@ -244,8 +280,10 @@ int xc_linux_restore(int xc_handle, int io_fd, p2m = calloc(max_pfn, sizeof(xen_pfn_t)); pfn_type = calloc(max_pfn, sizeof(unsigned long)); region_mfn = calloc(MAX_BATCH_SIZE, sizeof(xen_pfn_t)); + p2m_batch = calloc(MAX_BATCH_SIZE, sizeof(xen_pfn_t)); - if ((p2m == NULL) || (pfn_type == NULL) || (region_mfn == NULL)) { + if ((p2m == NULL) || (pfn_type == NULL) || + (region_mfn == NULL) || (p2m_batch == NULL)) { ERROR("memory alloc failed"); errno = ENOMEM; goto out; @@ -256,6 +294,11 @@ int xc_linux_restore(int xc_handle, int io_fd, goto out; } + if (lock_pages(p2m_batch, sizeof(xen_pfn_t) * MAX_BATCH_SIZE)) { + ERROR("Could not lock p2m_batch"); + goto out; + } + /* Get the domain's shared-info frame. */ domctl.cmd = XEN_DOMCTL_getdomaininfo; domctl.domain = (domid_t)dom; @@ -270,17 +313,9 @@ int xc_linux_restore(int xc_handle, int io_fd, goto out; } + /* Mark all PFNs as invalid; we allocate on demand */ for ( pfn = 0; pfn < max_pfn; pfn++ ) - p2m[pfn] = pfn; - - if (xc_domain_memory_populate_physmap(xc_handle, dom, max_pfn, - 0, 0, p2m) != 0) { - ERROR("Failed to increase reservation by %lx KB", PFN_TO_KB(max_pfn)); - errno = ENOMEM; - goto out; - } - - DPRINTF("Increased domain reservation by %lx KB\n", PFN_TO_KB(max_pfn)); + p2m[pfn] = INVALID_P2M_ENTRY; if(!(mmu = xc_init_mmu_updates(xc_handle, dom))) { ERROR("Could not initialise for MMU updates"); @@ -298,7 +333,7 @@ int xc_linux_restore(int xc_handle, int io_fd, n = 0; while (1) { - int j; + int j, nr_mfns = 0; this_pc = (n * 100) / max_pfn; if ( (this_pc - prev_pc) >= 5 ) @@ -333,6 +368,33 @@ int xc_linux_restore(int xc_handle, int io_fd, goto out; } + /* First pass for this batch: work out how much memory to alloc */ + nr_mfns = 0; + for ( i = 0; i < j; i++ ) + { + unsigned long pfn, pagetype; + pfn = region_pfn_type[i] & ~XEN_DOMCTL_PFINFO_LTAB_MASK; + pagetype = region_pfn_type[i] & XEN_DOMCTL_PFINFO_LTAB_MASK; + + if ( (pagetype != XEN_DOMCTL_PFINFO_XTAB) && + (p2m[pfn] == INVALID_P2M_ENTRY) ) + { + /* Have a live PFN which hasn't had an MFN allocated */ + p2m_batch[nr_mfns++] = pfn; + } + } + + + /* Now allocate a bunch of mfns for this batch */ + if (nr_mfns && xc_domain_memory_populate_physmap( + xc_handle, dom, nr_mfns, 0, 0, p2m_batch) != 0) { + ERROR("Failed to allocate memory for batch.!\n"); + errno = ENOMEM; + goto out; + } + + /* Second pass for this batch: update p2m[] and region_mfn[] */ + nr_mfns = 0; for ( i = 0; i < j; i++ ) { unsigned long pfn, pagetype; @@ -340,13 +402,23 @@ int xc_linux_restore(int xc_handle, int io_fd, pagetype = region_pfn_type[i] & XEN_DOMCTL_PFINFO_LTAB_MASK; if ( pagetype == XEN_DOMCTL_PFINFO_XTAB) - region_mfn[i] = 0; /* we know map will fail, but don't care */ - else - region_mfn[i] = p2m[pfn]; - } + region_mfn[i] = ~0UL; /* map will fail but we don't care */ + else + { + if (p2m[pfn] == INVALID_P2M_ENTRY) { + /* We just allocated a new mfn above; update p2m */ + p2m[pfn] = p2m_batch[nr_mfns++]; + } + /* setup region_mfn[] for batch map */ + region_mfn[i] = p2m[pfn]; + } + } + + /* Map relevant mfns */ region_base = xc_map_foreign_batch( xc_handle, dom, PROT_WRITE, region_mfn, j); + if ( region_base == NULL ) { ERROR("map batch failed"); @@ -401,7 +473,8 @@ int xc_linux_restore(int xc_handle, int io_fd, pae_extended_cr3 || (pagetype != XEN_DOMCTL_PFINFO_L1TAB)) { - if (!uncanonicalize_pagetable(pagetype, page)) { + if (!uncanonicalize_pagetable(xc_handle, dom, + pagetype, page)) { /* ** Failing to uncanonicalize a page table can be ok ** under live migration since the pages type may have @@ -411,10 +484,8 @@ int xc_linux_restore(int xc_handle, int io_fd, pagetype >> 28, pfn, mfn); nraces++; continue; - } - + } } - } else if ( pagetype != XEN_DOMCTL_PFINFO_NOTAB ) { @@ -486,7 +557,7 @@ int xc_linux_restore(int xc_handle, int io_fd, */ int j, k; - + /* First pass: find all L3TABs current in > 4G mfns and get new mfns */ for ( i = 0; i < max_pfn; i++ ) { @@ -555,7 +626,8 @@ int xc_linux_restore(int xc_handle, int io_fd, } for(k = 0; k < j; k++) { - if(!uncanonicalize_pagetable(XEN_DOMCTL_PFINFO_L1TAB, + if(!uncanonicalize_pagetable(xc_handle, dom, + XEN_DOMCTL_PFINFO_L1TAB, region_base + k*PAGE_SIZE)) { ERROR("failed uncanonicalize pt!"); goto out; @@ -631,7 +703,7 @@ int xc_linux_restore(int xc_handle, int io_fd, { unsigned int count; unsigned long *pfntab; - int rc; + int nr_frees, rc; if (!read_exact(io_fd, &count, sizeof(count))) { ERROR("Error when reading pfn count"); @@ -648,29 +720,30 @@ int xc_linux_restore(int xc_handle, int io_fd, goto out; } + nr_frees = 0; for (i = 0; i < count; i++) { unsigned long pfn = pfntab[i]; - if(pfn > max_pfn) - /* shouldn't happen - continue optimistically */ - continue; - - pfntab[i] = p2m[pfn]; - p2m[pfn] = INVALID_P2M_ENTRY; // not in pseudo-physical map + if(p2m[pfn] != INVALID_P2M_ENTRY) { + /* pfn is not in physmap now, but was at some point during + the save/migration process - need to free it */ + pfntab[nr_frees++] = p2m[pfn]; + p2m[pfn] = INVALID_P2M_ENTRY; // not in pseudo-physical map + } } - if (count > 0) { + if (nr_frees > 0) { struct xen_memory_reservation reservation = { - .nr_extents = count, + .nr_extents = nr_frees, .extent_order = 0, .domid = dom }; set_xen_guest_handle(reservation.extent_start, pfntab); if ((rc = xc_memory_op(xc_handle, XENMEM_decrease_reservation, - &reservation)) != count) { + &reservation)) != nr_frees) { ERROR("Could not decrease reservation : %d", rc); goto out; } else @@ -791,6 +864,6 @@ int xc_linux_restore(int xc_handle, int io_fd, free(pfn_type); DPRINTF("Restore exit with rc=%d\n", rc); - + return rc; } diff --git a/tools/python/xen/xend/XendCheckpoint.py b/tools/python/xen/xend/XendCheckpoint.py index 85a59e5d22..106e20fb3d 100644 --- a/tools/python/xen/xend/XendCheckpoint.py +++ b/tools/python/xen/xend/XendCheckpoint.py @@ -147,18 +147,20 @@ def restore(xd, fd, dominfo = None, paused = False): assert store_port assert console_port + nr_pfns = (dominfo.getMemoryTarget() + 3) / 4 + try: l = read_exact(fd, sizeof_unsigned_long, "not a valid guest state file: pfn count read") - nr_pfns = unpack("L", l)[0] # native sizeof long - if nr_pfns > 16*1024*1024: # XXX + max_pfn = unpack("L", l)[0] # native sizeof long + if max_pfn > 16*1024*1024: # XXX raise XendError( "not a valid guest state file: pfn count out of range") balloon.free(xc.pages_to_kib(nr_pfns)) cmd = map(str, [xen.util.auxbin.pathTo(XC_RESTORE), - fd, dominfo.getDomid(), nr_pfns, + fd, dominfo.getDomid(), max_pfn, store_port, console_port]) log.debug("[xc_restore]: %s", string.join(cmd)) From a086d29d0e360e83eafed55959c3e4e2a1340a38 Mon Sep 17 00:00:00 2001 From: George Dunlap Date: Tue, 16 Jan 2007 14:04:12 -0500 Subject: [PATCH 08/22] [XEN] Fix early-unshadow detection for 3- or 4-level guest pagetables. Early-unshadow will unshadow whenever 2 zero values are written to the same page; for PAE, one PTE takes 2 writes. Only check for the early unshadow when writing the low half of the PTE. --- xen/arch/x86/mm/shadow/multi.c | 4 ++-- xen/arch/x86/mm/shadow/private.h | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c index e040e60e71..0546cb1a66 100644 --- a/xen/arch/x86/mm/shadow/multi.c +++ b/xen/arch/x86/mm/shadow/multi.c @@ -3944,7 +3944,7 @@ sh_x86_emulate_write(struct vcpu *v, unsigned long vaddr, void *src, if ( !skip ) sh_validate_guest_pt_write(v, mfn, addr, bytes); /* If we are writing zeros to this page, might want to unshadow */ - if ( likely(bytes >= 4) && (*(u32 *)addr == 0) ) + if ( likely(bytes >= 4) && (*(u32 *)addr == 0) && is_lo_pte(vaddr) ) check_for_early_unshadow(v, mfn); sh_unmap_domain_page(addr); @@ -3996,7 +3996,7 @@ sh_x86_emulate_cmpxchg(struct vcpu *v, unsigned long vaddr, vaddr, prev, old, new, *(unsigned long *)addr, bytes); /* If we are writing zeros to this page, might want to unshadow */ - if ( likely(bytes >= 4) && (*(u32 *)addr == 0) ) + if ( likely(bytes >= 4) && (*(u32 *)addr == 0) && is_lo_pte(vaddr) ) check_for_early_unshadow(v, mfn); sh_unmap_domain_page(addr); diff --git a/xen/arch/x86/mm/shadow/private.h b/xen/arch/x86/mm/shadow/private.h index 913fa43770..21d78eb2de 100644 --- a/xen/arch/x86/mm/shadow/private.h +++ b/xen/arch/x86/mm/shadow/private.h @@ -427,6 +427,11 @@ extern int sh_remove_write_access(struct vcpu *v, mfn_t readonly_mfn, #undef mfn_valid #define mfn_valid(_mfn) (mfn_x(_mfn) < max_page) +#if GUEST_PAGING_LEVELS >= 3 +# define is_lo_pte(_vaddr) (((_vaddr)&0x4)==0) +#else +# define is_lo_pte(_vaddr) (1) +#endif static inline int sh_mfn_is_a_page_table(mfn_t gmfn) From 96002a7e9b93c9363136534fd1821c5743b323fa Mon Sep 17 00:00:00 2001 From: "john.levon@sun.com" Date: Tue, 16 Jan 2007 10:54:20 -0800 Subject: [PATCH 09/22] Remove useless fsip_fs_free(). Delegate freeing of private data to its plugin users. Miscellaneous tidy. Signed-off-by: John Levon --- tools/libfsimage/common/fsimage.c | 2 +- tools/libfsimage/common/fsimage_grub.c | 2 ++ tools/libfsimage/common/fsimage_plugin.c | 8 -------- tools/libfsimage/common/fsimage_plugin.h | 5 ++--- tools/libfsimage/common/mapfile-GNU | 3 +-- tools/libfsimage/common/mapfile-SunOS | 3 +-- tools/libfsimage/ext2fs-lib/ext2fs-lib.c | 2 ++ 7 files changed, 9 insertions(+), 16 deletions(-) diff --git a/tools/libfsimage/common/fsimage.c b/tools/libfsimage/common/fsimage.c index a326fd7644..08262f81ce 100644 --- a/tools/libfsimage/common/fsimage.c +++ b/tools/libfsimage/common/fsimage.c @@ -74,7 +74,7 @@ void fsi_close_fsimage(fsi_t *fsi) pthread_mutex_lock(&fsi_lock); fsi->f_plugin->fp_ops->fpo_umount(fsi); (void) close(fsi->f_fd); - fsip_fs_free(fsi); + free(fsi); pthread_mutex_unlock(&fsi_lock); } diff --git a/tools/libfsimage/common/fsimage_grub.c b/tools/libfsimage/common/fsimage_grub.c index 252445f58e..99481064a9 100644 --- a/tools/libfsimage/common/fsimage_grub.c +++ b/tools/libfsimage/common/fsimage_grub.c @@ -193,6 +193,7 @@ fsig_mount(fsi_t *fsi, const char *path) static int fsig_umount(fsi_t *fsi) { + free(fsi->f_data); return (0); } @@ -250,6 +251,7 @@ fsig_read(fsi_file_t *ffi, void *buf, size_t nbytes) static int fsig_close(fsi_file_t *ffi) { + free(ffi->ff_data); fsip_file_free(ffi); return (0); } diff --git a/tools/libfsimage/common/fsimage_plugin.c b/tools/libfsimage/common/fsimage_plugin.c index 71099ba2ff..f961648164 100644 --- a/tools/libfsimage/common/fsimage_plugin.c +++ b/tools/libfsimage/common/fsimage_plugin.c @@ -40,13 +40,6 @@ fsip_fs_set_data(fsi_t *fsi, void *data) fsi->f_data = data; } -void -fsip_fs_free(fsi_t *fsi) -{ - free(fsi->f_data); - free(fsi); -} - fsi_file_t * fsip_file_alloc(fsi_t *fsi, void *data) { @@ -64,7 +57,6 @@ fsip_file_alloc(fsi_t *fsi, void *data) void fsip_file_free(fsi_file_t *ffi) { - free(ffi->ff_data); free(ffi); } diff --git a/tools/libfsimage/common/fsimage_plugin.h b/tools/libfsimage/common/fsimage_plugin.h index 4592e08be7..f1c83fab95 100644 --- a/tools/libfsimage/common/fsimage_plugin.h +++ b/tools/libfsimage/common/fsimage_plugin.h @@ -50,11 +50,10 @@ typedef fsi_plugin_ops_t * (*fsi_plugin_init_t)(int, fsi_plugin_t *, const char **); void fsip_fs_set_data(fsi_t *, void *); -void fsip_fs_free(fsi_t *); fsi_file_t *fsip_file_alloc(fsi_t *, void *); void fsip_file_free(fsi_file_t *); -fsi_t * fsip_fs(fsi_file_t *ffi); -uint64_t fsip_fs_offset(fsi_t *fsi); +fsi_t *fsip_fs(fsi_file_t *); +uint64_t fsip_fs_offset(fsi_t *); void *fsip_fs_data(fsi_t *); void *fsip_file_data(fsi_file_t *); diff --git a/tools/libfsimage/common/mapfile-GNU b/tools/libfsimage/common/mapfile-GNU index f15060cba4..4bffdeafb0 100644 --- a/tools/libfsimage/common/mapfile-GNU +++ b/tools/libfsimage/common/mapfile-GNU @@ -1,5 +1,5 @@ VERSION { - libfsimage.so.1.1 { + libfsimage.so.1.0 { global: fsi_open_fsimage; fsi_close_fsimage; @@ -10,7 +10,6 @@ VERSION { fsi_pread_file; fsip_fs_set_data; - fsip_fs_free; fsip_file_alloc; fsip_file_free; fsip_fs; diff --git a/tools/libfsimage/common/mapfile-SunOS b/tools/libfsimage/common/mapfile-SunOS index 1ea38bed04..63f17e1832 100644 --- a/tools/libfsimage/common/mapfile-SunOS +++ b/tools/libfsimage/common/mapfile-SunOS @@ -1,4 +1,4 @@ -libfsimage.so.1.1 { +libfsimage.so.1.0 { global: fsi_open_fsimage; fsi_close_fsimage; @@ -9,7 +9,6 @@ libfsimage.so.1.1 { fsi_pread_file; fsip_fs_set_data; - fsip_fs_free; fsip_file_alloc; fsip_file_free; fsip_fs; diff --git a/tools/libfsimage/ext2fs-lib/ext2fs-lib.c b/tools/libfsimage/ext2fs-lib/ext2fs-lib.c index b6f60ce65f..aa8e7a63f4 100644 --- a/tools/libfsimage/ext2fs-lib/ext2fs-lib.c +++ b/tools/libfsimage/ext2fs-lib/ext2fs-lib.c @@ -58,9 +58,11 @@ ext2lib_umount(fsi_t *fsi) { ext2_filsys *fs = fsip_fs_data(fsi); if (ext2fs_close(*fs) != 0) { + free(fs); errno = EINVAL; return (-1); } + free(fs); return (0); } From d74f5aa06311f5bb5ee39d0fbd32707336cf61d0 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Wed, 17 Jan 2007 10:33:13 +0000 Subject: [PATCH 10/22] [LIBFSIMAGE] Fix makefile to track version number change Signed-off-by: Tim Deegan --- tools/libfsimage/common/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/libfsimage/common/Makefile b/tools/libfsimage/common/Makefile index 6efce44f02..9a62e9bbb5 100644 --- a/tools/libfsimage/common/Makefile +++ b/tools/libfsimage/common/Makefile @@ -1,7 +1,7 @@ XEN_ROOT = ../../.. include $(XEN_ROOT)/tools/Rules.mk -MAJOR = 1.0 +MAJOR = 1.1 MINOR = 0 CFLAGS += -Werror -Wp,-MD,.$(@F).d From 201c511f5a11b2317070146dd5f83f1832fc45f5 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 17 Jan 2007 12:11:02 +0000 Subject: [PATCH 11/22] [XEN] Include byteorder functions from Linux. Signed-off-by: Keir Fraser --- xen/include/asm-powerpc/byteorder.h | 80 ++++++++++ xen/include/asm-x86/byteorder.h | 36 +++++ xen/include/xen/byteorder/big_endian.h | 106 +++++++++++++ xen/include/xen/byteorder/generic.h | 68 ++++++++ xen/include/xen/byteorder/little_endian.h | 106 +++++++++++++ xen/include/xen/byteorder/swab.h | 185 ++++++++++++++++++++++ xen/include/xen/config.h | 2 + xen/include/xen/types.h | 7 + 8 files changed, 590 insertions(+) create mode 100644 xen/include/asm-powerpc/byteorder.h create mode 100644 xen/include/asm-x86/byteorder.h create mode 100644 xen/include/xen/byteorder/big_endian.h create mode 100644 xen/include/xen/byteorder/generic.h create mode 100644 xen/include/xen/byteorder/little_endian.h create mode 100644 xen/include/xen/byteorder/swab.h diff --git a/xen/include/asm-powerpc/byteorder.h b/xen/include/asm-powerpc/byteorder.h new file mode 100644 index 0000000000..94bbea2929 --- /dev/null +++ b/xen/include/asm-powerpc/byteorder.h @@ -0,0 +1,80 @@ +#ifndef _ASM_POWERPC_BYTEORDER_H +#define _ASM_POWERPC_BYTEORDER_H + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include + +static inline __u16 ld_le16(const volatile __u16 *addr) +{ + __u16 val; + + asm volatile ("lhbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr)); + return val; +} + +static inline void st_le16(volatile __u16 *addr, const __u16 val) +{ + asm volatile ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr)); +} + +static inline __u32 ld_le32(const volatile __u32 *addr) +{ + __u32 val; + + asm volatile ("lwbrx %0,0,%1" : "=r" (val) : "r" (addr), "m" (*addr)); + return val; +} + +static inline void st_le32(volatile __u32 *addr, const __u32 val) +{ + asm volatile ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr)); +} + +static inline __attribute_const__ __u16 ___arch__swab16(__u16 value) +{ + __u16 result; + + asm("rlwimi %0,%1,8,16,23" + : "=r" (result) + : "r" (value), "0" (value >> 8)); + return result; +} + +static inline __attribute_const__ __u32 ___arch__swab32(__u32 value) +{ + __u32 result; + + asm("rlwimi %0,%1,24,16,23\n\t" + "rlwimi %0,%1,8,8,15\n\t" + "rlwimi %0,%1,24,0,7" + : "=r" (result) + : "r" (value), "0" (value >> 24)); + return result; +} + +#define __arch__swab16(x) ___arch__swab16(x) +#define __arch__swab32(x) ___arch__swab32(x) + +/* The same, but returns converted value from the location pointer by addr. */ +#define __arch__swab16p(addr) ld_le16(addr) +#define __arch__swab32p(addr) ld_le32(addr) + +/* The same, but do the conversion in situ, ie. put the value back to addr. */ +#define __arch__swab16s(addr) st_le16(addr,*addr) +#define __arch__swab32s(addr) st_le32(addr,*addr) + +#define __BYTEORDER_HAS_U64__ +#ifndef __powerpc64__ +#define __SWAB_64_THRU_32__ +#endif /* __powerpc64__ */ + +#include + +#endif /* _ASM_POWERPC_BYTEORDER_H */ diff --git a/xen/include/asm-x86/byteorder.h b/xen/include/asm-x86/byteorder.h new file mode 100644 index 0000000000..eb52ae2f11 --- /dev/null +++ b/xen/include/asm-x86/byteorder.h @@ -0,0 +1,36 @@ +#ifndef __ASM_X86_BYTEORDER_H__ +#define __ASM_X86_BYTEORDER_H__ + +#include +#include + +static inline __attribute_const__ __u32 ___arch__swab32(__u32 x) +{ + asm("bswap %0" : "=r" (x) : "0" (x)); + return x; +} + +static inline __attribute_const__ __u64 ___arch__swab64(__u64 val) +{ + union { + struct { __u32 a,b; } s; + __u64 u; + } v; + v.u = val; + asm("bswapl %0 ; bswapl %1 ; xchgl %0,%1" + : "=r" (v.s.a), "=r" (v.s.b) + : "0" (v.s.a), "1" (v.s.b)); + return v.u; +} + +/* Do not define swab16. Gcc is smart enough to recognize "C" version and + convert it into rotation or exhange. */ + +#define __arch__swab64(x) ___arch__swab64(x) +#define __arch__swab32(x) ___arch__swab32(x) + +#define __BYTEORDER_HAS_U64__ + +#include + +#endif /* __ASM_X86_BYTEORDER_H__ */ diff --git a/xen/include/xen/byteorder/big_endian.h b/xen/include/xen/byteorder/big_endian.h new file mode 100644 index 0000000000..8a815534e4 --- /dev/null +++ b/xen/include/xen/byteorder/big_endian.h @@ -0,0 +1,106 @@ +#ifndef __XEN_BYTEORDER_BIG_ENDIAN_H__ +#define __XEN_BYTEORDER_BIG_ENDIAN_H__ + +#ifndef __BIG_ENDIAN +#define __BIG_ENDIAN 4321 +#endif +#ifndef __BIG_ENDIAN_BITFIELD +#define __BIG_ENDIAN_BITFIELD +#endif + +#include +#include + +#define __constant_htonl(x) ((__force __be32)(__u32)(x)) +#define __constant_ntohl(x) ((__force __u32)(__be32)(x)) +#define __constant_htons(x) ((__force __be16)(__u16)(x)) +#define __constant_ntohs(x) ((__force __u16)(__be16)(x)) +#define __constant_cpu_to_le64(x) ((__force __le64)___constant_swab64((x))) +#define __constant_le64_to_cpu(x) ___constant_swab64((__force __u64)(__le64)(x)) +#define __constant_cpu_to_le32(x) ((__force __le32)___constant_swab32((x))) +#define __constant_le32_to_cpu(x) ___constant_swab32((__force __u32)(__le32)(x)) +#define __constant_cpu_to_le16(x) ((__force __le16)___constant_swab16((x))) +#define __constant_le16_to_cpu(x) ___constant_swab16((__force __u16)(__le16)(x)) +#define __constant_cpu_to_be64(x) ((__force __be64)(__u64)(x)) +#define __constant_be64_to_cpu(x) ((__force __u64)(__be64)(x)) +#define __constant_cpu_to_be32(x) ((__force __be32)(__u32)(x)) +#define __constant_be32_to_cpu(x) ((__force __u32)(__be32)(x)) +#define __constant_cpu_to_be16(x) ((__force __be16)(__u16)(x)) +#define __constant_be16_to_cpu(x) ((__force __u16)(__be16)(x)) +#define __cpu_to_le64(x) ((__force __le64)__swab64((x))) +#define __le64_to_cpu(x) __swab64((__force __u64)(__le64)(x)) +#define __cpu_to_le32(x) ((__force __le32)__swab32((x))) +#define __le32_to_cpu(x) __swab32((__force __u32)(__le32)(x)) +#define __cpu_to_le16(x) ((__force __le16)__swab16((x))) +#define __le16_to_cpu(x) __swab16((__force __u16)(__le16)(x)) +#define __cpu_to_be64(x) ((__force __be64)(__u64)(x)) +#define __be64_to_cpu(x) ((__force __u64)(__be64)(x)) +#define __cpu_to_be32(x) ((__force __be32)(__u32)(x)) +#define __be32_to_cpu(x) ((__force __u32)(__be32)(x)) +#define __cpu_to_be16(x) ((__force __be16)(__u16)(x)) +#define __be16_to_cpu(x) ((__force __u16)(__be16)(x)) + +static inline __le64 __cpu_to_le64p(const __u64 *p) +{ + return (__force __le64)__swab64p(p); +} +static inline __u64 __le64_to_cpup(const __le64 *p) +{ + return __swab64p((__u64 *)p); +} +static inline __le32 __cpu_to_le32p(const __u32 *p) +{ + return (__force __le32)__swab32p(p); +} +static inline __u32 __le32_to_cpup(const __le32 *p) +{ + return __swab32p((__u32 *)p); +} +static inline __le16 __cpu_to_le16p(const __u16 *p) +{ + return (__force __le16)__swab16p(p); +} +static inline __u16 __le16_to_cpup(const __le16 *p) +{ + return __swab16p((__u16 *)p); +} +static inline __be64 __cpu_to_be64p(const __u64 *p) +{ + return (__force __be64)*p; +} +static inline __u64 __be64_to_cpup(const __be64 *p) +{ + return (__force __u64)*p; +} +static inline __be32 __cpu_to_be32p(const __u32 *p) +{ + return (__force __be32)*p; +} +static inline __u32 __be32_to_cpup(const __be32 *p) +{ + return (__force __u32)*p; +} +static inline __be16 __cpu_to_be16p(const __u16 *p) +{ + return (__force __be16)*p; +} +static inline __u16 __be16_to_cpup(const __be16 *p) +{ + return (__force __u16)*p; +} +#define __cpu_to_le64s(x) __swab64s((x)) +#define __le64_to_cpus(x) __swab64s((x)) +#define __cpu_to_le32s(x) __swab32s((x)) +#define __le32_to_cpus(x) __swab32s((x)) +#define __cpu_to_le16s(x) __swab16s((x)) +#define __le16_to_cpus(x) __swab16s((x)) +#define __cpu_to_be64s(x) do {} while (0) +#define __be64_to_cpus(x) do {} while (0) +#define __cpu_to_be32s(x) do {} while (0) +#define __be32_to_cpus(x) do {} while (0) +#define __cpu_to_be16s(x) do {} while (0) +#define __be16_to_cpus(x) do {} while (0) + +#include + +#endif /* __XEN_BYTEORDER_BIG_ENDIAN_H__ */ diff --git a/xen/include/xen/byteorder/generic.h b/xen/include/xen/byteorder/generic.h new file mode 100644 index 0000000000..8a0006b755 --- /dev/null +++ b/xen/include/xen/byteorder/generic.h @@ -0,0 +1,68 @@ +#ifndef __XEN_BYTEORDER_GENERIC_H__ +#define __XEN_BYTEORDER_GENERIC_H__ + +/* + * Generic Byte-reordering support + * + * The "... p" macros, like le64_to_cpup, can be used with pointers + * to unaligned data, but there will be a performance penalty on + * some architectures. Use get_unaligned for unaligned data. + * + * The following macros are to be defined by : + * + * Conversion of XX-bit integers (16- 32- or 64-) + * between native CPU format and little/big endian format + * 64-bit stuff only defined for proper architectures + * cpu_to_[bl]eXX(__uXX x) + * [bl]eXX_to_cpu(__uXX x) + * + * The same, but takes a pointer to the value to convert + * cpu_to_[bl]eXXp(__uXX x) + * [bl]eXX_to_cpup(__uXX x) + * + * The same, but change in situ + * cpu_to_[bl]eXXs(__uXX x) + * [bl]eXX_to_cpus(__uXX x) + * + * See asm-foo/byteorder.h for examples of how to provide + * architecture-optimized versions + */ + +#define cpu_to_le64 __cpu_to_le64 +#define le64_to_cpu __le64_to_cpu +#define cpu_to_le32 __cpu_to_le32 +#define le32_to_cpu __le32_to_cpu +#define cpu_to_le16 __cpu_to_le16 +#define le16_to_cpu __le16_to_cpu +#define cpu_to_be64 __cpu_to_be64 +#define be64_to_cpu __be64_to_cpu +#define cpu_to_be32 __cpu_to_be32 +#define be32_to_cpu __be32_to_cpu +#define cpu_to_be16 __cpu_to_be16 +#define be16_to_cpu __be16_to_cpu +#define cpu_to_le64p __cpu_to_le64p +#define le64_to_cpup __le64_to_cpup +#define cpu_to_le32p __cpu_to_le32p +#define le32_to_cpup __le32_to_cpup +#define cpu_to_le16p __cpu_to_le16p +#define le16_to_cpup __le16_to_cpup +#define cpu_to_be64p __cpu_to_be64p +#define be64_to_cpup __be64_to_cpup +#define cpu_to_be32p __cpu_to_be32p +#define be32_to_cpup __be32_to_cpup +#define cpu_to_be16p __cpu_to_be16p +#define be16_to_cpup __be16_to_cpup +#define cpu_to_le64s __cpu_to_le64s +#define le64_to_cpus __le64_to_cpus +#define cpu_to_le32s __cpu_to_le32s +#define le32_to_cpus __le32_to_cpus +#define cpu_to_le16s __cpu_to_le16s +#define le16_to_cpus __le16_to_cpus +#define cpu_to_be64s __cpu_to_be64s +#define be64_to_cpus __be64_to_cpus +#define cpu_to_be32s __cpu_to_be32s +#define be32_to_cpus __be32_to_cpus +#define cpu_to_be16s __cpu_to_be16s +#define be16_to_cpus __be16_to_cpus + +#endif /* __XEN_BYTEORDER_GENERIC_H__ */ diff --git a/xen/include/xen/byteorder/little_endian.h b/xen/include/xen/byteorder/little_endian.h new file mode 100644 index 0000000000..24ac42701e --- /dev/null +++ b/xen/include/xen/byteorder/little_endian.h @@ -0,0 +1,106 @@ +#ifndef __XEN_BYTEORDER_LITTLE_ENDIAN_H__ +#define __XEN_BYTEORDER_LITTLE_ENDIAN_H__ + +#ifndef __LITTLE_ENDIAN +#define __LITTLE_ENDIAN 1234 +#endif +#ifndef __LITTLE_ENDIAN_BITFIELD +#define __LITTLE_ENDIAN_BITFIELD +#endif + +#include +#include + +#define __constant_htonl(x) ((__force __be32)___constant_swab32((x))) +#define __constant_ntohl(x) ___constant_swab32((__force __be32)(x)) +#define __constant_htons(x) ((__force __be16)___constant_swab16((x))) +#define __constant_ntohs(x) ___constant_swab16((__force __be16)(x)) +#define __constant_cpu_to_le64(x) ((__force __le64)(__u64)(x)) +#define __constant_le64_to_cpu(x) ((__force __u64)(__le64)(x)) +#define __constant_cpu_to_le32(x) ((__force __le32)(__u32)(x)) +#define __constant_le32_to_cpu(x) ((__force __u32)(__le32)(x)) +#define __constant_cpu_to_le16(x) ((__force __le16)(__u16)(x)) +#define __constant_le16_to_cpu(x) ((__force __u16)(__le16)(x)) +#define __constant_cpu_to_be64(x) ((__force __be64)___constant_swab64((x))) +#define __constant_be64_to_cpu(x) ___constant_swab64((__force __u64)(__be64)(x)) +#define __constant_cpu_to_be32(x) ((__force __be32)___constant_swab32((x))) +#define __constant_be32_to_cpu(x) ___constant_swab32((__force __u32)(__be32)(x)) +#define __constant_cpu_to_be16(x) ((__force __be16)___constant_swab16((x))) +#define __constant_be16_to_cpu(x) ___constant_swab16((__force __u16)(__be16)(x)) +#define __cpu_to_le64(x) ((__force __le64)(__u64)(x)) +#define __le64_to_cpu(x) ((__force __u64)(__le64)(x)) +#define __cpu_to_le32(x) ((__force __le32)(__u32)(x)) +#define __le32_to_cpu(x) ((__force __u32)(__le32)(x)) +#define __cpu_to_le16(x) ((__force __le16)(__u16)(x)) +#define __le16_to_cpu(x) ((__force __u16)(__le16)(x)) +#define __cpu_to_be64(x) ((__force __be64)__swab64((x))) +#define __be64_to_cpu(x) __swab64((__force __u64)(__be64)(x)) +#define __cpu_to_be32(x) ((__force __be32)__swab32((x))) +#define __be32_to_cpu(x) __swab32((__force __u32)(__be32)(x)) +#define __cpu_to_be16(x) ((__force __be16)__swab16((x))) +#define __be16_to_cpu(x) __swab16((__force __u16)(__be16)(x)) + +static inline __le64 __cpu_to_le64p(const __u64 *p) +{ + return (__force __le64)*p; +} +static inline __u64 __le64_to_cpup(const __le64 *p) +{ + return (__force __u64)*p; +} +static inline __le32 __cpu_to_le32p(const __u32 *p) +{ + return (__force __le32)*p; +} +static inline __u32 __le32_to_cpup(const __le32 *p) +{ + return (__force __u32)*p; +} +static inline __le16 __cpu_to_le16p(const __u16 *p) +{ + return (__force __le16)*p; +} +static inline __u16 __le16_to_cpup(const __le16 *p) +{ + return (__force __u16)*p; +} +static inline __be64 __cpu_to_be64p(const __u64 *p) +{ + return (__force __be64)__swab64p(p); +} +static inline __u64 __be64_to_cpup(const __be64 *p) +{ + return __swab64p((__u64 *)p); +} +static inline __be32 __cpu_to_be32p(const __u32 *p) +{ + return (__force __be32)__swab32p(p); +} +static inline __u32 __be32_to_cpup(const __be32 *p) +{ + return __swab32p((__u32 *)p); +} +static inline __be16 __cpu_to_be16p(const __u16 *p) +{ + return (__force __be16)__swab16p(p); +} +static inline __u16 __be16_to_cpup(const __be16 *p) +{ + return __swab16p((__u16 *)p); +} +#define __cpu_to_le64s(x) do {} while (0) +#define __le64_to_cpus(x) do {} while (0) +#define __cpu_to_le32s(x) do {} while (0) +#define __le32_to_cpus(x) do {} while (0) +#define __cpu_to_le16s(x) do {} while (0) +#define __le16_to_cpus(x) do {} while (0) +#define __cpu_to_be64s(x) __swab64s((x)) +#define __be64_to_cpus(x) __swab64s((x)) +#define __cpu_to_be32s(x) __swab32s((x)) +#define __be32_to_cpus(x) __swab32s((x)) +#define __cpu_to_be16s(x) __swab16s((x)) +#define __be16_to_cpus(x) __swab16s((x)) + +#include + +#endif /* __XEN_BYTEORDER_LITTLE_ENDIAN_H__ */ diff --git a/xen/include/xen/byteorder/swab.h b/xen/include/xen/byteorder/swab.h new file mode 100644 index 0000000000..0193ff83e7 --- /dev/null +++ b/xen/include/xen/byteorder/swab.h @@ -0,0 +1,185 @@ +#ifndef __XEN_BYTEORDER_SWAB_H__ +#define __XEN_BYTEORDER_SWAB_H__ + +/* + * Byte-swapping, independently from CPU endianness + * swabXX[ps]?(foo) + * + * Francois-Rene Rideau 19971205 + * separated swab functions from cpu_to_XX, + * to clean up support for bizarre-endian architectures. + */ + +#include + +/* casts are necessary for constants, because we never know how for sure + * how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way. + */ +#define ___swab16(x) \ +({ \ + __u16 __x = (x); \ + ((__u16)( \ + (((__u16)(__x) & (__u16)0x00ffU) << 8) | \ + (((__u16)(__x) & (__u16)0xff00U) >> 8) )); \ +}) + +#define ___swab32(x) \ +({ \ + __u32 __x = (x); \ + ((__u32)( \ + (((__u32)(__x) & (__u32)0x000000ffUL) << 24) | \ + (((__u32)(__x) & (__u32)0x0000ff00UL) << 8) | \ + (((__u32)(__x) & (__u32)0x00ff0000UL) >> 8) | \ + (((__u32)(__x) & (__u32)0xff000000UL) >> 24) )); \ +}) + +#define ___swab64(x) \ +({ \ + __u64 __x = (x); \ + ((__u64)( \ + (__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | \ + (__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | \ + (__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | \ + (__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) << 8) | \ + (__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >> 8) | \ + (__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | \ + (__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | \ + (__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); \ +}) + +#define ___constant_swab16(x) \ + ((__u16)( \ + (((__u16)(x) & (__u16)0x00ffU) << 8) | \ + (((__u16)(x) & (__u16)0xff00U) >> 8) )) +#define ___constant_swab32(x) \ + ((__u32)( \ + (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \ + (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \ + (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \ + (((__u32)(x) & (__u32)0xff000000UL) >> 24) )) +#define ___constant_swab64(x) \ + ((__u64)( \ + (__u64)(((__u64)(x) & (__u64)0x00000000000000ffULL) << 56) | \ + (__u64)(((__u64)(x) & (__u64)0x000000000000ff00ULL) << 40) | \ + (__u64)(((__u64)(x) & (__u64)0x0000000000ff0000ULL) << 24) | \ + (__u64)(((__u64)(x) & (__u64)0x00000000ff000000ULL) << 8) | \ + (__u64)(((__u64)(x) & (__u64)0x000000ff00000000ULL) >> 8) | \ + (__u64)(((__u64)(x) & (__u64)0x0000ff0000000000ULL) >> 24) | \ + (__u64)(((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) | \ + (__u64)(((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56) )) + +/* + * provide defaults when no architecture-specific optimization is detected + */ +#ifndef __arch__swab16 +# define __arch__swab16(x) ({ __u16 __tmp = (x) ; ___swab16(__tmp); }) +#endif +#ifndef __arch__swab32 +# define __arch__swab32(x) ({ __u32 __tmp = (x) ; ___swab32(__tmp); }) +#endif +#ifndef __arch__swab64 +# define __arch__swab64(x) ({ __u64 __tmp = (x) ; ___swab64(__tmp); }) +#endif + +#ifndef __arch__swab16p +# define __arch__swab16p(x) __arch__swab16(*(x)) +#endif +#ifndef __arch__swab32p +# define __arch__swab32p(x) __arch__swab32(*(x)) +#endif +#ifndef __arch__swab64p +# define __arch__swab64p(x) __arch__swab64(*(x)) +#endif + +#ifndef __arch__swab16s +# define __arch__swab16s(x) do { *(x) = __arch__swab16p((x)); } while (0) +#endif +#ifndef __arch__swab32s +# define __arch__swab32s(x) do { *(x) = __arch__swab32p((x)); } while (0) +#endif +#ifndef __arch__swab64s +# define __arch__swab64s(x) do { *(x) = __arch__swab64p((x)); } while (0) +#endif + + +/* + * Allow constant folding + */ +#if defined(__GNUC__) && defined(__OPTIMIZE__) +# define __swab16(x) \ +(__builtin_constant_p((__u16)(x)) ? \ + ___swab16((x)) : \ + __fswab16((x))) +# define __swab32(x) \ +(__builtin_constant_p((__u32)(x)) ? \ + ___swab32((x)) : \ + __fswab32((x))) +# define __swab64(x) \ +(__builtin_constant_p((__u64)(x)) ? \ + ___swab64((x)) : \ + __fswab64((x))) +#else +# define __swab16(x) __fswab16(x) +# define __swab32(x) __fswab32(x) +# define __swab64(x) __fswab64(x) +#endif /* OPTIMIZE */ + + +static inline __attribute_const__ __u16 __fswab16(__u16 x) +{ + return __arch__swab16(x); +} +static inline __u16 __swab16p(const __u16 *x) +{ + return __arch__swab16p(x); +} +static inline void __swab16s(__u16 *addr) +{ + __arch__swab16s(addr); +} + +static inline __attribute_const__ __u32 __fswab32(__u32 x) +{ + return __arch__swab32(x); +} +static inline __u32 __swab32p(const __u32 *x) +{ + return __arch__swab32p(x); +} +static inline void __swab32s(__u32 *addr) +{ + __arch__swab32s(addr); +} + +#ifdef __BYTEORDER_HAS_U64__ +static inline __attribute_const__ __u64 __fswab64(__u64 x) +{ +# ifdef __SWAB_64_THRU_32__ + __u32 h = x >> 32; + __u32 l = x & ((1ULL<<32)-1); + return (((__u64)__swab32(l)) << 32) | ((__u64)(__swab32(h))); +# else + return __arch__swab64(x); +# endif +} +static inline __u64 __swab64p(const __u64 *x) +{ + return __arch__swab64p(x); +} +static inline void __swab64s(__u64 *addr) +{ + __arch__swab64s(addr); +} +#endif /* __BYTEORDER_HAS_U64__ */ + +#define swab16 __swab16 +#define swab32 __swab32 +#define swab64 __swab64 +#define swab16p __swab16p +#define swab32p __swab32p +#define swab64p __swab64p +#define swab16s __swab16s +#define swab32s __swab32s +#define swab64s __swab64s + +#endif /* __XEN_BYTEORDER_SWAB_H__ */ diff --git a/xen/include/xen/config.h b/xen/include/xen/config.h index 068a550078..02e292b6d7 100644 --- a/xen/include/xen/config.h +++ b/xen/include/xen/config.h @@ -63,6 +63,8 @@ /* Linux 'checker' project. */ #define __iomem #define __user +#define __force +#define __bitwise #ifndef __ASSEMBLY__ diff --git a/xen/include/xen/types.h b/xen/include/xen/types.h index 8bafc73156..fd89c98427 100644 --- a/xen/include/xen/types.h +++ b/xen/include/xen/types.h @@ -51,4 +51,11 @@ typedef __s64 int64_t; struct domain; struct vcpu; +typedef __u16 __le16; +typedef __u16 __be16; +typedef __u32 __le32; +typedef __u32 __be32; +typedef __u64 __le64; +typedef __u64 __be64; + #endif /* __TYPES_H__ */ From 671248b38b3bdd997b949a43ae1ceb2d412ea6e3 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 17 Jan 2007 14:03:12 +0000 Subject: [PATCH 12/22] Document vfb configuration. Signed-off-by: Markus Armbruster --- docs/man/xmdomain.cfg.pod.5 | 49 +++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/docs/man/xmdomain.cfg.pod.5 b/docs/man/xmdomain.cfg.pod.5 index 03faf68caf..6fe1da79f7 100644 --- a/docs/man/xmdomain.cfg.pod.5 +++ b/docs/man/xmdomain.cfg.pod.5 @@ -135,6 +135,55 @@ one will be randomly chosen by xen with the 00:16:3e vendor id prefix. =back +=item B + +A virtual frame buffer stanza in the form: + + vfb = [ "stanza" ] + +The stanza specifies a set of I options separated by +commas, in the form: "name1=value1, name2=value2, ..." + +B + +=over 4 + +=item I + +There are currently two valid options: I starts a VNC server that +lets you connect an external VNC viewer, and I starts an internal +viewer. + +=item I + +The VNC display number to use, defaults to the domain ID. The +VNC server listens on port 5900 + display number. + +=item I + +The listening address for the VNC server, default 127.0.0.1. + +=item I + +If non-zero, the VNC server listens on the first unused port above +5900. + +=item I + +Overrides the XenD configured default password. + +=item I + +Display to use for the internal viewer, defaults to environment +variable I. + +=item I + +Authority file to use for the internal viewer, defaults to environment +variable I. + +=back + =back =head1 ADDITIONAL OPTIONS From 7aad705cb521269e47d687bf381dea8713197961 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 17 Jan 2007 14:37:45 +0000 Subject: [PATCH 13/22] [XEN] Fix PAE writable-pte fixup to only trigger on writes to upper half the the PAE PTE. Signed-off-by: Jan Beulich --- xen/arch/x86/mm.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index c095ba41a1..406941516d 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -3236,15 +3236,14 @@ static int ptwr_emulated_update( if ( unlikely(!get_page_from_l1e(gl1e_to_ml1e(d, nl1e), d)) ) { if ( (CONFIG_PAGING_LEVELS == 3 || IS_COMPAT(d)) && - (bytes == 4) && - !do_cmpxchg && + (bytes == 4) && (addr & 4) && !do_cmpxchg && (l1e_get_flags(nl1e) & _PAGE_PRESENT) ) { /* - * If this is a half-write to a PAE PTE then we assume that the - * guest has simply got the two writes the wrong way round. We - * zap the PRESENT bit on the assumption the bottom half will be - * written immediately after we return to the guest. + * If this is an upper-half write to a PAE PTE then we assume that + * the guest has simply got the two writes the wrong way round. We + * zap the PRESENT bit on the assumption that the bottom half will + * be written immediately after we return to the guest. */ MEM_LOG("ptwr_emulate: fixing up invalid PAE PTE %"PRIpte, l1e_get_intpte(nl1e)); @@ -3375,7 +3374,7 @@ int ptwr_do_page_fault(struct vcpu *v, unsigned long addr, (page_get_owner(page) != d) ) goto bail; - ptwr_ctxt.ctxt.regs = guest_cpu_user_regs(); + ptwr_ctxt.ctxt.regs = regs; ptwr_ctxt.ctxt.addr_size = ptwr_ctxt.ctxt.sp_size = IS_COMPAT(d) ? 32 : BITS_PER_LONG; ptwr_ctxt.cr2 = addr; From f8871496b97e9cd485de048d4ce1d987425081c5 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 17 Jan 2007 14:45:00 +0000 Subject: [PATCH 14/22] linux/i386: enhance dump_fault_path() in the highpte case As long as the pte page isn't really located in highmem, there is no reason to not access it, in order to print the complete page table hierarchy. A functionally similar patch will go to lkml for native Linux. Signed-off-by: Jan Beulich --- linux-2.6-xen-sparse/arch/i386/mm/fault-xen.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/i386/mm/fault-xen.c b/linux-2.6-xen-sparse/arch/i386/mm/fault-xen.c index cd40fabc08..7e52b47b04 100644 --- a/linux-2.6-xen-sparse/arch/i386/mm/fault-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/mm/fault-xen.c @@ -232,9 +232,12 @@ static void dump_fault_path(unsigned long address) p += (address >> 21) * 2; printk(KERN_ALERT "%08lx -> *pme = %08lx:%08lx\n", page, p[1], p[0]); -#ifndef CONFIG_HIGHPTE + mfn = (p[0] >> PAGE_SHIFT) | (p[1] << 20); +#ifdef CONFIG_HIGHPTE + if (mfn_to_pfn(mfn) >= highstart_pfn) + return; +#endif if (p[0] & 1) { - mfn = (p[0] >> PAGE_SHIFT) | (p[1] << 20); page = mfn_to_pfn(mfn) << PAGE_SHIFT; p = (unsigned long *) __va(page); address &= 0x001fffff; @@ -242,7 +245,6 @@ static void dump_fault_path(unsigned long address) printk(KERN_ALERT "%08lx -> *pte = %08lx:%08lx\n", page, p[1], p[0]); } -#endif } } #else @@ -254,13 +256,16 @@ static void dump_fault_path(unsigned long address) page = ((unsigned long *) __va(page))[address >> 22]; printk(KERN_ALERT "*pde = ma %08lx pa %08lx\n", page, machine_to_phys(page)); +#ifdef CONFIG_HIGHPTE /* * We must not directly access the pte in the highpte - * case, the page table might be allocated in highmem. + * case if the page table is located in highmem. * And lets rather not kmap-atomic the pte, just in case * it's allocated already. */ -#ifndef CONFIG_HIGHPTE + if ((page >> PAGE_SHIFT) >= highstart_pfn) + return; +#endif if (page & 1) { page &= PAGE_MASK; address &= 0x003ff000; @@ -269,7 +274,6 @@ static void dump_fault_path(unsigned long address) printk(KERN_ALERT "*pte = ma %08lx pa %08lx\n", page, machine_to_phys(page)); } -#endif } #endif From edf5361fb26ba21e57b3de94ce4448f2ce3eb2e5 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 17 Jan 2007 14:54:06 +0000 Subject: [PATCH 15/22] Add scheduler name to 'xm info' output. Signed-off-by: Masaki Kanno --- docs/man/xm.pod.1 | 3 ++- tools/python/xen/xend/XendNode.py | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/docs/man/xm.pod.1 b/docs/man/xm.pod.1 index b0ba7f8fb2..3cd8b80ac6 100644 --- a/docs/man/xm.pod.1 +++ b/docs/man/xm.pod.1 @@ -451,6 +451,7 @@ make the man page more readable): xen_minor : 0 xen_extra : -devel xen_caps : xen-3.0-x86_32 + xen_scheduler : credit xen_pagesize : 4096 platform_params : virt_start=0xfc000000 xen_changeset : Mon Nov 14 18:13:38 2005 +0100 @@ -460,7 +461,7 @@ make the man page more readable): cc_compile_by : sdague cc_compile_domain : (none) cc_compile_date : Mon Nov 14 14:16:48 EST 2005 - xend_config_format : 2 + xend_config_format : 3 B diff --git a/tools/python/xen/xend/XendNode.py b/tools/python/xen/xend/XendNode.py index 117ca3d25d..932c05d207 100644 --- a/tools/python/xen/xend/XendNode.py +++ b/tools/python/xen/xend/XendNode.py @@ -365,14 +365,24 @@ class XendNode: return [[k, info[k]] for k in ITEM_ORDER] + def xenschedinfo(self): + sched_id = self.xc.sched_id_get() + if sched_id == xen.lowlevel.xc.XEN_SCHEDULER_SEDF: + return 'sedf' + elif sched_id == xen.lowlevel.xc.XEN_SCHEDULER_CREDIT: + return 'credit' + else: + return 'unknown' def xeninfo(self): info = self.xc.xeninfo() + info['xen_scheduler'] = self.xenschedinfo() ITEM_ORDER = ['xen_major', 'xen_minor', 'xen_extra', 'xen_caps', + 'xen_scheduler', 'xen_pagesize', 'platform_params', 'xen_changeset', From 727e8b415489e59cb1f0fe19e64063afda2255f4 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 17 Jan 2007 14:54:59 +0000 Subject: [PATCH 16/22] [XEND] Fix warning about 'cpus' option on domain creation. Signed-off-by: Masaki Kanno --- tools/python/xen/xend/XendConfig.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index b264b79f32..fd9afb0b3a 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -126,6 +126,7 @@ XENAPI_CFG_TYPES = { 'memory_dynamic_min': int, 'memory_dynamic_max': int, 'memory_actual': int, + 'cpus': list, 'vcpus_policy': str, 'vcpus_params': str, 'vcpus_number': int, From 1468aea9005c69cdb769010d8e1456955b967498 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 17 Jan 2007 14:57:59 +0000 Subject: [PATCH 17/22] Microcode does not need to have the default size of 2000+48 bytes. A corresponding patch has gone into Linux 2.6.19; this is the port to Xen. Signed-off-by: Kurt Garloff Reference: Patch to linux kernel from Sep 27 2006 > # User Shaohua Li > # Node ID 45898b908138b5d93c2cc7353f061ce54af145dc > # Parent f962eab7b82c9bf1a6da69571046e764f5128395 > [PATCH] x86 microcode: don't check the size > > IA32 manual says if micorcode update's size is 0, then the size is > default size (2048 bytes). But this doesn't suggest all microcode > update's size should be above 2048 bytes to me. We actually had a > microcode update whose size is 1024 bytes. The patch just removed > the check. > > Signed-off-by: Shaohua Li > Cc: Tigran Aivazian > Signed-off-by: Andrew Morton > Signed-off-by: Linus Torvalds > > committer: Linus Torvalds 1159370778 -0700 --- xen/arch/x86/microcode.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/xen/arch/x86/microcode.c b/xen/arch/x86/microcode.c index 3dcac7d124..89138c9a79 100644 --- a/xen/arch/x86/microcode.c +++ b/xen/arch/x86/microcode.c @@ -249,14 +249,14 @@ static int find_matching_ucodes (void) } total_size = get_totalsize(&mc_header); - if ((cursor + total_size > user_buffer_size) || (total_size < DEFAULT_UCODE_TOTALSIZE)) { + if (cursor + total_size > user_buffer_size) { printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); error = -EINVAL; goto out; } data_size = get_datasize(&mc_header); - if ((data_size + MC_HEADER_SIZE > total_size) || (data_size < DEFAULT_UCODE_DATASIZE)) { + if (data_size + MC_HEADER_SIZE > total_size) { printk(KERN_ERR "microcode: error! Bad data in microcode data file\n"); error = -EINVAL; goto out; @@ -459,11 +459,6 @@ int microcode_update(XEN_GUEST_HANDLE(void) buf, unsigned long len) { int ret; - if (len < DEFAULT_UCODE_TOTALSIZE) { - printk(KERN_ERR "microcode: not enough data\n"); - return -EINVAL; - } - if (len != (typeof(user_buffer_size))len) { printk(KERN_ERR "microcode: too much data\n"); return -E2BIG; From bba72b94d7ef7a00d278c12e9aed5caae0a62016 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 17 Jan 2007 14:58:53 +0000 Subject: [PATCH 18/22] linux: Allow microcode updates of smaller than default size. Signed-off-by: Kurt Garloff --- linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c index 926ba175c3..756c13e586 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/microcode-xen.c @@ -85,7 +85,7 @@ static ssize_t microcode_write (struct file *file, const char __user *buf, size_ { ssize_t ret; - if (len < DEFAULT_UCODE_TOTALSIZE) { + if (len < MC_HEADER_SIZE) { printk(KERN_ERR "microcode: not enough data\n"); return -EINVAL; } From 4ff20a30344f24c7a246e6ceb3b631c9876c6a51 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 17 Jan 2007 15:03:27 +0000 Subject: [PATCH 19/22] [HVM] i8254: Fix bogus use of current The function pit_load_count incorrectly references current for determining whether the channel number is zero. This breaks when starting a new guest because current points to dom0. The fix is to explicitly pass the address for verification. Signed-off-by: Herbert Xu --- xen/arch/x86/hvm/i8254.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/xen/arch/x86/hvm/i8254.c b/xen/arch/x86/hvm/i8254.c index a81ae57722..1ab512d2ee 100644 --- a/xen/arch/x86/hvm/i8254.c +++ b/xen/arch/x86/hvm/i8254.c @@ -182,11 +182,9 @@ void pit_time_fired(struct vcpu *v, void *priv) s->count_load_time = hvm_get_guest_time(v); } -static inline void pit_load_count(PITChannelState *s, int val) +static inline void pit_load_count(PITChannelState *s, int channel, int val) { u32 period; - PITChannelState *ch0 = - ¤t->domain->arch.hvm_domain.pl_time.vpit.channels[0]; if (val == 0) val = 0x10000; @@ -194,7 +192,7 @@ static inline void pit_load_count(PITChannelState *s, int val) s->count = val; period = DIV_ROUND((val * 1000000000ULL), PIT_FREQ); - if (s != ch0) + if (channel != 0) return; #ifdef DEBUG_PIT @@ -282,17 +280,17 @@ static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val) switch(s->write_state) { default: case RW_STATE_LSB: - pit_load_count(s, val); + pit_load_count(s, addr, val); break; case RW_STATE_MSB: - pit_load_count(s, val << 8); + pit_load_count(s, addr, val << 8); break; case RW_STATE_WORD0: s->write_latch = val; s->write_state = RW_STATE_WORD1; break; case RW_STATE_WORD1: - pit_load_count(s, s->write_latch | (val << 8)); + pit_load_count(s, addr, s->write_latch | (val << 8)); s->write_state = RW_STATE_WORD0; break; } @@ -369,7 +367,7 @@ static void pit_reset(void *opaque) destroy_periodic_time(&s->pt); s->mode = 0xff; /* the init mode */ s->gate = (i != 2); - pit_load_count(s, 0); + pit_load_count(s, i, 0); } } From f515c2cf95c5a6bc88a67a7e6319637b7c6e378b Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 17 Jan 2007 15:09:50 +0000 Subject: [PATCH 20/22] [MINIOS] New make structure to support different architectures. Signed-off-by: Dietmar Hahn --- extras/mini-os/Makefile | 170 ++++++++---------- extras/mini-os/arch/x86/Makefile | 29 +++ extras/mini-os/arch/x86/arch.mk | 28 +++ .../mini-os/{ => arch/x86}/minios-x86_32.lds | 0 .../mini-os/{ => arch/x86}/minios-x86_64.lds | 0 extras/mini-os/{ => arch/x86}/x86_32.S | 0 extras/mini-os/{ => arch/x86}/x86_64.S | 0 extras/mini-os/minios.mk | 62 +++++++ 8 files changed, 195 insertions(+), 94 deletions(-) create mode 100644 extras/mini-os/arch/x86/Makefile create mode 100644 extras/mini-os/arch/x86/arch.mk rename extras/mini-os/{ => arch/x86}/minios-x86_32.lds (100%) rename extras/mini-os/{ => arch/x86}/minios-x86_64.lds (100%) rename extras/mini-os/{ => arch/x86}/x86_32.S (100%) rename extras/mini-os/{ => arch/x86}/x86_64.S (100%) create mode 100644 extras/mini-os/minios.mk diff --git a/extras/mini-os/Makefile b/extras/mini-os/Makefile index 0fa1baccd5..ad4ff8d910 100644 --- a/extras/mini-os/Makefile +++ b/extras/mini-os/Makefile @@ -1,112 +1,88 @@ -debug ?= y +# Common Makefile for mini-os. +# +# Every architecture directory below mini-os/arch has to have a +# Makefile and a arch.mk. +# + pae ?= n XEN_ROOT = ../.. include $(XEN_ROOT)/Config.mk -# Set TARGET_ARCH -override TARGET_ARCH := $(XEN_TARGET_ARCH) - XEN_INTERFACE_VERSION := 0x00030204 +export XEN_INTERFACE_VERSION -# NB. '-Wcast-qual' is nasty, so I omitted it. -CFLAGS := -fno-builtin -Wall -Werror -Wredundant-decls -Wno-format -CFLAGS += -Wstrict-prototypes -Wnested-externs -Wpointer-arith -Winline -CFLAGS += -D__XEN_INTERFACE_VERSION__=$(XEN_INTERFACE_VERSION) +# Set TARGET_ARCH +override TARGET_ARCH := $(XEN_TARGET_ARCH) -ASFLAGS = -D__ASSEMBLY__ +# Set mini-os root path, used in mini-os.mk. +MINI-OS_ROOT=$(PWD) +export MINI-OS_ROOT -LDLIBS = -L. -lminios -LDFLAGS_FINAL := -N -T minios-$(TARGET_ARCH).lds -LDFLAGS := +# Try to find out the architecture family TARGET_ARCH_FAM. +# First check whether x86_... is contained (for x86_32, x86_32y, x86_64). +# If not x86 then use $(TARGET_ARCH) -> for ia64, ... +ifeq ($(findstring x86_,$(TARGET_ARCH)),x86_) +TARGET_ARCH_FAM = x86 +else +TARGET_ARCH_FAM = $(TARGET_ARCH) +endif + +# The architecture family directory below mini-os. +TARGET_ARCH_DIR := arch/$(TARGET_ARCH_FAM) + +# Export these variables for possible use in architecture dependent makefiles. +export TARGET_ARCH +export TARGET_ARCH_DIR +export TARGET_ARCH_FAM + +# This is used for architecture specific links. +# This can be overwritten from arch specific rules. +ARCH_LINKS = + +# For possible special header directories. +# This can be overwritten from arch specific rules. +EXTRA_INC = + +# Special build dependencies. +# Build all after touching this/these file(s) (see minios.mk) +SPEC_DEPENDS = minios.mk + +# Include the architecture family's special makerules. +# This must be before include minios.mk! +include $(TARGET_ARCH_DIR)/arch.mk + +# Include common mini-os makerules. +include minios.mk + +# Define some default flags for linking. +LDLIBS := +LDFLAGS := +LDARCHLIB := -L$(TARGET_ARCH_DIR) -l$(ARCH_LIB_NAME) +LDFLAGS_FINAL := -N -T $(TARGET_ARCH_DIR)/minios-$(TARGET_ARCH).lds # Prefix for global API names. All other symbols are localised before # linking with EXTRA_OBJS. GLOBAL_PREFIX := xenos_ EXTRA_OBJS = -# For possible special source directories. -EXTRA_SRC = -# For possible special header directories. -EXTRA_INC = - -# Standard name for architecture specific subdirectories. -TARGET_ARCH_DIR = $(TARGET_ARCH) -# This is used for architecture specific links. -ARCH_LINKS = - -ifeq ($(TARGET_ARCH),x86_32) -CFLAGS += -m32 -march=i686 -LDFLAGS += -m elf_i386 -TARGET_ARCH_DIR = x86 -EXTRA_INC += $(TARGET_ARCH_DIR)/$(TARGET_ARCH) -EXTRA_SRC += arch/$(EXTRA_INC) -endif - -ifeq ($(TARGET_ARCH)$(pae),x86_32y) -CFLAGS += -DCONFIG_X86_PAE=1 -ASFLAGS += -DCONFIG_X86_PAE=1 -TARGET_ARCH_DIR = x86 -EXTRA_INC += $(TARGET_ARCH_DIR)/$(TARGET_ARCH) -EXTRA_SRC += arch/$(EXTRA_INC) -endif - -ifeq ($(TARGET_ARCH),x86_64) -CFLAGS += -m64 -mno-red-zone -fpic -fno-reorder-blocks -CFLAGS += -fno-asynchronous-unwind-tables -LDFLAGS += -m elf_x86_64 -TARGET_ARCH_DIR = x86 -EXTRA_INC += $(TARGET_ARCH_DIR)/$(TARGET_ARCH) -EXTRA_SRC += arch/$(EXTRA_INC) -endif - -ifeq ($(TARGET_ARCH),ia64) -CFLAGS += -mfixed-range=f2-f5,f12-f15,f32-f127 -mconstant-gp -ASFLAGS += -x assembler-with-cpp -Wall -ASFLAGS += -mfixed-range=f2-f5,f12-f15,f32-f127 -fomit-frame-pointer -ASFLAGS += -fno-builtin -fno-common -fno-strict-aliasing -mconstant-gp -ARCH_LINKS = IA64_LINKS # Special link on ia64 needed -define arch_links -[ -e include/ia64/asm-xsi-offsets.h ] || ln -sf ../../../../xen/include/asm-ia64/asm-xsi-offsets.h include/ia64/asm-xsi-offsets.h -endef -endif - -ifeq ($(debug),y) -CFLAGS += -g -else -CFLAGS += -O3 -endif - -# Add the special header directories to the include paths. -extra_incl := $(foreach dir,$(EXTRA_INC),-Iinclude/$(dir)) -override CPPFLAGS := -Iinclude $(CPPFLAGS) -Iinclude/$(TARGET_ARCH_DIR) $(extra_incl) - TARGET := mini-os -HEAD := $(TARGET_ARCH).o +# Subdirectories common to mini-os +SUBDIRS := lib xenbus console + +# The common mini-os objects to build. OBJS := $(patsubst %.c,%.o,$(wildcard *.c)) OBJS += $(patsubst %.c,%.o,$(wildcard lib/*.c)) OBJS += $(patsubst %.c,%.o,$(wildcard xenbus/*.c)) OBJS += $(patsubst %.c,%.o,$(wildcard console/*.c)) -OBJS += $(patsubst %.S,%.o,$(wildcard arch/$(TARGET_ARCH_DIR)/*.S)) -OBJS += $(patsubst %.c,%.o,$(wildcard arch/$(TARGET_ARCH_DIR)/*.c)) -# For special wanted source directories. -extra_objs := $(foreach dir,$(EXTRA_SRC),$(patsubst %.c,%.o,$(wildcard $(dir)/*.c))) -OBJS += $(extra_objs) -extra_objs := $(foreach dir,$(EXTRA_SRC),$(patsubst %.S,%.o,$(wildcard $(dir)/*.S))) -OBJS += $(extra_objs) -HDRS := $(wildcard include/*.h) -HDRS += $(wildcard include/xen/*.h) -HDRS += $(wildcard include/$(TARGET_ARCH_DIR)/*.h) -# For special wanted header directories. -extra_heads := $(foreach dir,$(EXTRA_INC),$(wildcard $(dir)/*.h)) -HDRS += $(extra_heads) .PHONY: default default: $(TARGET) -# Create special architecture specific links. +# Create special architecture specific links. The function arch_links +# has to be defined in arch.mk (see include above). ifneq ($(ARCH_LINKS),) $(ARCH_LINKS): $(arch_links) @@ -116,24 +92,29 @@ endif links: $(ARCH_LINKS) [ -e include/xen ] || ln -sf ../../../xen/include/public include/xen -$(TARGET): links $(OBJS) $(HEAD) - $(LD) -r $(LDFLAGS) $(HEAD) $(OBJS) -o $@.o +.PHONY: arch_lib +arch_lib: + $(MAKE) --directory=$(TARGET_ARCH_DIR) || exit 1; + +$(TARGET): links $(OBJS) arch_lib + $(LD) -r $(LDFLAGS) $(HEAD_OBJ) $(OBJS) $(LDARCHLIB) -o $@.o $(OBJCOPY) -w -G $(GLOBAL_PREFIX)* -G _start $@.o $@.o $(LD) $(LDFLAGS) $(LDFLAGS_FINAL) $@.o $(EXTRA_OBJS) -o $@ gzip -f -9 -c $@ >$@.gz -.PHONY: clean -clean: - find . -type f -name '*.o' | xargs rm -f - rm -f *.o *~ core $(TARGET) $(TARGET).gz +.PHONY: clean arch_clean + +arch_clean: + $(MAKE) --directory=$(TARGET_ARCH_DIR) clean || exit 1; + +clean: arch_clean + for dir in $(SUBDIRS); do \ + rm -f $$dir/*.o; \ + done + rm -f *.o *~ core $(TARGET).elf $(TARGET).raw $(TARGET) $(TARGET).gz find . -type l | xargs rm -f rm -f tags TAGS -%.o: %.c $(HDRS) Makefile - $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ - -%.o: %.S $(HDRS) Makefile - $(CC) $(ASFLAGS) $(CPPFLAGS) -c $< -o $@ define all_sources ( find . -follow -name SCCS -prune -o -name '*.[chS]' -print ) @@ -147,3 +128,4 @@ cscope: .PHONY: tags tags: $(all_sources) | xargs ctags + diff --git a/extras/mini-os/arch/x86/Makefile b/extras/mini-os/arch/x86/Makefile new file mode 100644 index 0000000000..45cfe19136 --- /dev/null +++ b/extras/mini-os/arch/x86/Makefile @@ -0,0 +1,29 @@ +# +# x86 architecture specific makefiles. +# It's is used for x86_32, x86_32y and x86_64 +# + +# Rebuild all after touching this/these extra file(s) (see mini-os.mk) +SPEC_DEP = arch.mk + +# include arch.mk has to be before mini-os.mk! +include arch.mk +include ../../minios.mk + +# Sources here are all *.c *.S without $(TARGET_ARCH).S +# This is handled in $(HEAD_ARCH_OBJ) +ARCH_SRCS := $(wildcard *.c) + +# The objects built from the sources. +ARCH_OBJS := $(patsubst %.c,%.o,$(ARCH_SRCS)) + +all: $(ARCH_LIB) + +# $(HEAD_ARCH_OBJ) is only build here, needed on linking +# in ../../Makefile. +$(ARCH_LIB): $(ARCH_OBJS) $(HEAD_ARCH_OBJ) + $(AR) rv $(ARCH_LIB) $(ARCH_OBJS) + +clean: + rm -f $(ARCH_LIB) $(ARCH_OBJS) + diff --git a/extras/mini-os/arch/x86/arch.mk b/extras/mini-os/arch/x86/arch.mk new file mode 100644 index 0000000000..5d0ee4add7 --- /dev/null +++ b/extras/mini-os/arch/x86/arch.mk @@ -0,0 +1,28 @@ +# +# Architecture special makerules for x86 family +# (including x86_32, x86_32y and x86_64). +# + +ifeq ($(TARGET_ARCH),x86_32) +ARCH_CFLAGS := -m32 -march=i686 +ARCH_LDFLAGS := -m elf_i386 +EXTRA_INC += $(TARGET_ARCH_FAM)/$(TARGET_ARCH) +EXTRA_SRC += arch/$(EXTRA_INC) +endif + +ifeq ($(TARGET_ARCH)$(pae),x86_32y) +ARCH_CFLAGS := -DCONFIG_X86_PAE=1 +ARCH_ASFLAGS := -DCONFIG_X86_PAE=1 +EXTRA_INC += $(TARGET_ARCH_FAM)/$(TARGET_ARCH) +EXTRA_SRC += arch/$(EXTRA_INC) +endif + +ifeq ($(TARGET_ARCH),x86_64) +ARCH_CFLAGS := -m64 -mno-red-zone -fpic -fno-reorder-blocks +ARCH_CFLAGS := -fno-asynchronous-unwind-tables +ARCH_LDFLAGS := -m elf_x86_64 +EXTRA_INC += $(TARGET_ARCH_FAM)/$(TARGET_ARCH) +EXTRA_SRC += arch/$(EXTRA_INC) +endif + + diff --git a/extras/mini-os/minios-x86_32.lds b/extras/mini-os/arch/x86/minios-x86_32.lds similarity index 100% rename from extras/mini-os/minios-x86_32.lds rename to extras/mini-os/arch/x86/minios-x86_32.lds diff --git a/extras/mini-os/minios-x86_64.lds b/extras/mini-os/arch/x86/minios-x86_64.lds similarity index 100% rename from extras/mini-os/minios-x86_64.lds rename to extras/mini-os/arch/x86/minios-x86_64.lds diff --git a/extras/mini-os/x86_32.S b/extras/mini-os/arch/x86/x86_32.S similarity index 100% rename from extras/mini-os/x86_32.S rename to extras/mini-os/arch/x86/x86_32.S diff --git a/extras/mini-os/x86_64.S b/extras/mini-os/arch/x86/x86_64.S similarity index 100% rename from extras/mini-os/x86_64.S rename to extras/mini-os/arch/x86/x86_64.S diff --git a/extras/mini-os/minios.mk b/extras/mini-os/minios.mk new file mode 100644 index 0000000000..47542a5852 --- /dev/null +++ b/extras/mini-os/minios.mk @@ -0,0 +1,62 @@ +# +# The file contains the common make rules for building mini-os. +# + +debug = y + +# Define some default flags. +# NB. '-Wcast-qual' is nasty, so I omitted it. +DEF_CFLAGS := -fno-builtin -Wall -Werror -Wredundant-decls -Wno-format +DEF_CFLAGS += -Wstrict-prototypes -Wnested-externs -Wpointer-arith -Winline +DEF_CFLAGS += -D__XEN_INTERFACE_VERSION__=$(XEN_INTERFACE_VERSION) + +DEF_ASFLAGS = -D__ASSEMBLY__ + +ifeq ($(debug),y) +DEF_CFLAGS += -g +else +DEF_CFLAGS += -O3 +endif + +# Build the CFLAGS and ASFLAGS for compiling and assembling. +# DEF_... flags are the common mini-os flags, +# ARCH_... flags may be defined in arch/$(TARGET_ARCH_FAM/rules.mk +CFLAGS := $(DEF_CFLAGS) $(ARCH_CFLAGS) +ASFLAGS := $(DEF_ASFLAGS) $(ARCH_ASFLAGS) + +# The path pointing to the architecture specific header files. +ARCH_SPEC_INC := $(MINI-OS_ROOT)/include/$(TARGET_ARCH_FAM) + +# Find all header files for checking dependencies. +HDRS := $(wildcard $(MINI-OS_ROOT)/include/*.h) +HDRS += $(wildcard $(MINI-OS_ROOT)/include/xen/*.h) +HDRS += $(wildcard $(ARCH_SPEC_INC)/*.h) +# For special wanted header directories. +extra_heads := $(foreach dir,$(EXTRA_INC),$(wildcard $(dir)/*.h)) +HDRS += $(extra_heads) + +# Add the special header directories to the include paths. +extra_incl := $(foreach dir,$(EXTRA_INC),-I$(MINI-OS_ROOT)/include/$(dir)) +override CPPFLAGS := -I$(MINI-OS_ROOT)/include $(CPPFLAGS) -I$(ARCH_SPEC_INC) $(extra_incl) + +# The name of the architecture specific library. +# This is on x86_32: libx86_32.a +# $(ARCH_LIB) has to built in the architecture specific directory. +ARCH_LIB_NAME = $(TARGET_ARCH) +ARCH_LIB := lib$(ARCH_LIB_NAME).a + +# This object contains the entrypoint for startup from Xen. +# $(HEAD_ARCH_OBJ) has to be built in the architecture specific directory. +HEAD_ARCH_OBJ := $(TARGET_ARCH).o +HEAD_OBJ := $(TARGET_ARCH_DIR)/$(HEAD_ARCH_OBJ) + + +%.o: %.c $(HDRS) Makefile $(SPEC_DEPENDS) + $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ + +%.o: %.S $(HDRS) Makefile $(SPEC_DEPENDS) + $(CC) $(ASFLAGS) $(CPPFLAGS) -c $< -o $@ + + + + From cc1ecba9d6c3894a4ebb35c920a9a1348d3ac8e5 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 17 Jan 2007 15:41:39 +0000 Subject: [PATCH 21/22] [XEN] A few emulator fixes. Signed-off-by: Keir Fraser --- xen/arch/x86/x86_emulate.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/xen/arch/x86/x86_emulate.c b/xen/arch/x86/x86_emulate.c index feeccd53de..7788961f36 100644 --- a/xen/arch/x86/x86_emulate.c +++ b/xen/arch/x86/x86_emulate.c @@ -1156,7 +1156,9 @@ x86_emulate( break; } - case 0x80 ... 0x83: /* Grp1 */ + case 0x82: /* Grp1 (x86/32 only) */ + generate_exception_if(mode_64bit(), EXC_UD); + case 0x80: case 0x81: case 0x83: /* Grp1 */ switch ( modrm_reg & 7 ) { case 0: goto add; @@ -1477,7 +1479,7 @@ x86_emulate( emulate_1op("dec", dst, _regs.eflags); break; case 2: /* call (near) */ - case 3: /* jmp (near) */ + case 4: /* jmp (near) */ if ( ((op_bytes = dst.bytes) != 8) && mode_64bit() ) { dst.bytes = op_bytes = 8; @@ -2049,12 +2051,13 @@ x86_emulate( break; case 0xba: /* Grp8 */ - switch ( modrm_reg & 3 ) + switch ( modrm_reg & 7 ) { - case 0: goto bt; - case 1: goto bts; - case 2: goto btr; - case 3: goto btc; + case 4: goto bt; + case 5: goto bts; + case 6: goto btr; + case 7: goto btc; + default: generate_exception_if(1, EXC_UD); } break; @@ -2103,6 +2106,7 @@ x86_emulate( #if defined(__i386__) { unsigned long old_lo, old_hi; + generate_exception_if((modrm_reg & 7) != 1, EXC_UD); if ( (rc = ops->read(ea.mem.seg, ea.mem.off+0, &old_lo, 4, ctxt)) || (rc = ops->read(ea.mem.seg, ea.mem.off+4, &old_hi, 4, ctxt)) ) goto done; @@ -2129,6 +2133,7 @@ x86_emulate( #elif defined(__x86_64__) { unsigned long old, new; + generate_exception_if((modrm_reg & 7) != 1, EXC_UD); if ( (rc = ops->read(ea.mem.seg, ea.mem.off, &old, 8, ctxt)) != 0 ) goto done; if ( ((uint32_t)(old>>0) != (uint32_t)_regs.eax) || From 9d15d8d54a82cc665b83e98ecb03ef68e123f718 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 17 Jan 2007 16:42:34 +0000 Subject: [PATCH 22/22] Export XEN_TARGET_ARCH to buildconfig sub-Makefiles even if it is not specified on the command line. Signed-off-by: Keir Fraser --- Makefile | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index c7004c0ae2..cac9547a3d 100644 --- a/Makefile +++ b/Makefile @@ -2,18 +2,15 @@ # Grand Unified Makefile for Xen. # -# Export target architecture overrides to Xen and Linux sub-trees. -ifneq ($(XEN_TARGET_ARCH),) -SUBARCH := $(subst x86_32,i386,$(XEN_TARGET_ARCH)) -export XEN_TARGET_ARCH SUBARCH XEN_SYSTYPE -endif - # Default target must appear before any include lines .PHONY: all all: dist export XEN_ROOT=$(CURDIR) include Config.mk + +SUBARCH := $(subst x86_32,i386,$(XEN_TARGET_ARCH)) +export XEN_TARGET_ARCH SUBARCH XEN_SYSTYPE include buildconfigs/Rules.mk ifeq ($(XEN_TARGET_X86_PAE),y)