From 785137cb6b2ebfa54bfb6af5d985ac10fa8a4560 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 7 Feb 2008 18:00:44 +0000 Subject: x86_emulate: Fix MUL emulation. Signed-off-by: Keir Fraser --- xen/arch/x86/x86_emulate.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/xen/arch/x86/x86_emulate.c b/xen/arch/x86/x86_emulate.c index ee0118a7b3..c111f1ca36 100644 --- a/xen/arch/x86/x86_emulate.c +++ b/xen/arch/x86/x86_emulate.c @@ -1710,11 +1710,14 @@ x86_emulate( switch ( src.bytes ) { case 1: + dst.val = (uint8_t)dst.val; dst.val *= src.val; if ( (uint8_t)dst.val != (uint16_t)dst.val ) _regs.eflags |= EFLG_OF|EFLG_CF; + dst.bytes = 2; break; case 2: + dst.val = (uint16_t)dst.val; dst.val *= src.val; if ( (uint16_t)dst.val != (uint32_t)dst.val ) _regs.eflags |= EFLG_OF|EFLG_CF; @@ -1722,6 +1725,7 @@ x86_emulate( break; #ifdef __x86_64__ case 4: + dst.val = (uint32_t)dst.val; dst.val *= src.val; if ( (uint32_t)dst.val != dst.val ) _regs.eflags |= EFLG_OF|EFLG_CF; -- cgit v1.2.3 From 23c077d931414c31ba2907cbf7b07b1a49bdfa21 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 7 Feb 2008 18:56:47 +0000 Subject: x86_emulate: Handle rep_ins, rep_outs, rep_movs hook failure and fall back to slow path. Signed-off-by: Keir Fraser --- xen/arch/x86/x86_emulate.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/xen/arch/x86/x86_emulate.c b/xen/arch/x86/x86_emulate.c index c111f1ca36..32a11b6be4 100644 --- a/xen/arch/x86/x86_emulate.c +++ b/xen/arch/x86/x86_emulate.c @@ -2225,11 +2225,12 @@ x86_emulate( dst.bytes = !(b & 1) ? 1 : (op_bytes == 8) ? 4 : op_bytes; dst.mem.seg = x86_seg_es; dst.mem.off = truncate_ea(_regs.edi); - if ( (nr_reps > 1) && (ops->rep_ins != NULL) ) + if ( (nr_reps > 1) && (ops->rep_ins != NULL) && + ((rc = ops->rep_ins((uint16_t)_regs.edx, dst.mem.seg, + dst.mem.off, dst.bytes, + &nr_reps, ctxt)) != X86EMUL_UNHANDLEABLE) ) { - if ( (rc = ops->rep_ins((uint16_t)_regs.edx, dst.mem.seg, - dst.mem.off, dst.bytes, - &nr_reps, ctxt)) != 0 ) + if ( rc != 0 ) goto done; } else @@ -2252,11 +2253,12 @@ x86_emulate( unsigned long nr_reps = get_rep_prefix(); generate_exception_if(!mode_iopl(), EXC_GP); dst.bytes = !(b & 1) ? 1 : (op_bytes == 8) ? 4 : op_bytes; - if ( (nr_reps > 1) && (ops->rep_outs != NULL) ) + if ( (nr_reps > 1) && (ops->rep_outs != NULL) && + ((rc = ops->rep_outs(ea.mem.seg, truncate_ea(_regs.esi), + (uint16_t)_regs.edx, dst.bytes, + &nr_reps, ctxt)) != X86EMUL_UNHANDLEABLE) ) { - if ( (rc = ops->rep_outs(ea.mem.seg, truncate_ea(_regs.esi), - (uint16_t)_regs.edx, dst.bytes, - &nr_reps, ctxt)) != 0 ) + if ( rc != 0 ) goto done; } else @@ -2403,11 +2405,12 @@ x86_emulate( dst.bytes = (d & ByteOp) ? 1 : op_bytes; dst.mem.seg = x86_seg_es; dst.mem.off = truncate_ea(_regs.edi); - if ( (nr_reps > 1) && (ops->rep_movs != NULL) ) + if ( (nr_reps > 1) && (ops->rep_movs != NULL) && + ((rc = ops->rep_movs(ea.mem.seg, truncate_ea(_regs.esi), + dst.mem.seg, dst.mem.off, dst.bytes, + &nr_reps, ctxt)) != X86EMUL_UNHANDLEABLE) ) { - if ( (rc = ops->rep_movs(ea.mem.seg, truncate_ea(_regs.esi), - dst.mem.seg, dst.mem.off, dst.bytes, - &nr_reps, ctxt)) != 0 ) + if ( rc != 0 ) goto done; } else -- cgit v1.2.3 From 690e710ebfa75aa224314b5b7d1c2d86e4f442f5 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 7 Feb 2008 18:57:12 +0000 Subject: vmx realmode: Add REP MOVS handler. Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/vmx/realmode.c | 53 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/xen/arch/x86/hvm/vmx/realmode.c b/xen/arch/x86/hvm/vmx/realmode.c index 6c591d1f16..dc9f76e645 100644 --- a/xen/arch/x86/hvm/vmx/realmode.c +++ b/xen/arch/x86/hvm/vmx/realmode.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -313,6 +314,57 @@ realmode_rep_outs( return X86EMUL_OKAY; } +static int +realmode_rep_movs( + enum x86_segment src_seg, + unsigned long src_offset, + enum x86_segment dst_seg, + unsigned long dst_offset, + unsigned int bytes_per_rep, + unsigned long *reps, + struct x86_emulate_ctxt *ctxt) +{ + struct realmode_emulate_ctxt *rm_ctxt = + container_of(ctxt, struct realmode_emulate_ctxt, ctxt); + struct vcpu *curr = current; + uint32_t saddr = virtual_to_linear(src_seg, src_offset, rm_ctxt); + uint32_t daddr = virtual_to_linear(dst_seg, dst_offset, rm_ctxt); + p2m_type_t p2mt; + + if ( (curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE) || + curr->arch.hvm_vmx.real_mode_io_in_progress ) + return X86EMUL_UNHANDLEABLE; + + mfn_x(gfn_to_mfn_current(saddr >> PAGE_SHIFT, &p2mt)); + if ( !p2m_is_ram(p2mt) ) + { + if ( !curr->arch.hvm_vmx.real_mode_io_completed ) + { + curr->arch.hvm_vmx.real_mode_io_in_progress = 1; + send_mmio_req(IOREQ_TYPE_COPY, saddr, *reps, bytes_per_rep, + daddr, IOREQ_READ, + !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1); + } + + if ( !curr->arch.hvm_vmx.real_mode_io_completed ) + return X86EMUL_RETRY; + + curr->arch.hvm_vmx.real_mode_io_completed = 0; + } + else + { + mfn_x(gfn_to_mfn_current(daddr >> PAGE_SHIFT, &p2mt)); + if ( p2m_is_ram(p2mt) ) + return X86EMUL_UNHANDLEABLE; + curr->arch.hvm_vmx.real_mode_io_in_progress = 1; + send_mmio_req(IOREQ_TYPE_COPY, daddr, *reps, bytes_per_rep, + saddr, IOREQ_WRITE, + !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1); + } + + return X86EMUL_OKAY; +} + static int realmode_read_segment( enum x86_segment seg, @@ -600,6 +652,7 @@ static struct x86_emulate_ops realmode_emulator_ops = { .cmpxchg = realmode_emulate_cmpxchg, .rep_ins = realmode_rep_ins, .rep_outs = realmode_rep_outs, + .rep_movs = realmode_rep_movs, .read_segment = realmode_read_segment, .write_segment = realmode_write_segment, .read_io = realmode_read_io, -- cgit v1.2.3 From cb87e2c31a75778469165cd60a7044661b047780 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 7 Feb 2008 19:30:36 +0000 Subject: x86_emulate: Fix IMUL r/m8 emulation. Signed-off-by: Keir Fraser --- xen/arch/x86/x86_emulate.c | 1 + 1 file changed, 1 insertion(+) diff --git a/xen/arch/x86/x86_emulate.c b/xen/arch/x86/x86_emulate.c index 32a11b6be4..b240a0a48e 100644 --- a/xen/arch/x86/x86_emulate.c +++ b/xen/arch/x86/x86_emulate.c @@ -1755,6 +1755,7 @@ x86_emulate( (uint16_t)(int8_t)dst.val); if ( (int8_t)dst.val != (uint16_t)dst.val ) _regs.eflags |= EFLG_OF|EFLG_CF; + dst.bytes = 2; break; case 2: dst.val = ((uint32_t)(int16_t)src.val * -- cgit v1.2.3 From 4be9201e8c34104b15ac2eda6b8c3092d7baa191 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 11 Feb 2008 09:45:36 +0000 Subject: xentrace: Fix bug in logic for bytes_to_wrap in trace buffer. Admittedly, the bug could only be manifest with much larger trace records than are currently allowed (or equivalently, much smaller trace buffers), but the old code was harder to read, and thus hid the logic bug well, too. Signed-off-by: Michael A Fetterman --- xen/common/trace.c | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/xen/common/trace.c b/xen/common/trace.c index 9af70798bb..d2f8fceeae 100644 --- a/xen/common/trace.c +++ b/xen/common/trace.c @@ -425,25 +425,18 @@ void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data) total_size += bytes_to_wrap; bytes_to_wrap = data_size; } - else - { - bytes_to_wrap -= LOST_REC_SIZE; - if ( bytes_to_wrap == 0 ) - bytes_to_wrap = data_size; - } total_size += LOST_REC_SIZE; + bytes_to_wrap -= LOST_REC_SIZE; + + /* LOST_REC might line up perfectly with the buffer wrap */ + if ( bytes_to_wrap == 0 ) + bytes_to_wrap = data_size; } if ( rec_size > bytes_to_wrap ) { total_size += bytes_to_wrap; - bytes_to_wrap = data_size; } - else - { - bytes_to_wrap -= rec_size; - } - total_size += rec_size; /* Do we have enough space for everything? */ @@ -466,14 +459,12 @@ void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data) insert_wrap_record(buf, LOST_REC_SIZE); bytes_to_wrap = data_size; } - else - { - bytes_to_wrap -= LOST_REC_SIZE; - /* LOST_REC might line up perfectly with the buffer wrap */ - if ( bytes_to_wrap == 0 ) - bytes_to_wrap = data_size; - } insert_lost_records(buf); + bytes_to_wrap -= LOST_REC_SIZE; + + /* LOST_REC might line up perfectly with the buffer wrap */ + if ( bytes_to_wrap == 0 ) + bytes_to_wrap = data_size; } if ( rec_size > bytes_to_wrap ) -- cgit v1.2.3 From d37035e9f9ee9dc1fddd3fc8fd541b91504b3d43 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 11 Feb 2008 09:46:21 +0000 Subject: xentrace: Allow xentrace to handle >4G of trace data. It was previously assert'ing when it hit 4G. Also, because the trace buffer is not a power of 2 in size, using modulo arithmetic to address the buffer does not work when the index wraps around 2^32. This patch fixes both issues, and as a side effect, removes all integer division from the hypervisor side of the trace mechanism. Signed-off-by: Michael A Fetterman --- tools/xentrace/xentrace.c | 13 ++++++++-- xen/common/trace.c | 65 +++++++++++++++++++++++++++++++++++----------- xen/include/public/trace.h | 8 ++++++ 3 files changed, 69 insertions(+), 17 deletions(-) diff --git a/tools/xentrace/xentrace.c b/tools/xentrace/xentrace.c index 26415bdb7d..bd276cc3ed 100644 --- a/tools/xentrace/xentrace.c +++ b/tools/xentrace/xentrace.c @@ -362,9 +362,18 @@ int monitor_tbufs(int outfd) if ( cons == prod ) continue; - assert(prod > cons); + assert(cons < 2*data_size); + assert(prod < 2*data_size); + + // NB: if (prod 0); + assert(window_size <= data_size); - window_size = prod - cons; start_offset = cons % data_size; end_offset = prod % data_size; diff --git a/xen/common/trace.c b/xen/common/trace.c index d2f8fceeae..863816b9ee 100644 --- a/xen/common/trace.c +++ b/xen/common/trace.c @@ -239,14 +239,46 @@ static inline int calc_rec_size(int cycles, int extra) return rec_size; } +static inline int calc_unconsumed_bytes(struct t_buf *buf) +{ + int x = buf->prod - buf->cons; + if ( x < 0 ) + x += 2*data_size; + + ASSERT(x >= 0); + ASSERT(x <= data_size); + + return x; +} + static inline int calc_bytes_to_wrap(struct t_buf *buf) { - return data_size - (buf->prod % data_size); + int x = data_size - buf->prod; + if ( x <= 0 ) + x += data_size; + + ASSERT(x > 0); + ASSERT(x <= data_size); + + return x; } -static inline unsigned calc_bytes_avail(struct t_buf *buf) +static inline int calc_bytes_avail(struct t_buf *buf) { - return data_size - (buf->prod - buf->cons); + return data_size - calc_unconsumed_bytes(buf); +} + +static inline struct t_rec * +next_record(struct t_buf *buf) +{ + int x = buf->prod; + if ( x >= data_size ) + x -= data_size; + + ASSERT(x >= 0); + ASSERT(x < data_size); + + return (struct t_rec *)&this_cpu(t_data)[x]; } static inline int __insert_record(struct t_buf *buf, @@ -260,24 +292,25 @@ static inline int __insert_record(struct t_buf *buf, unsigned char *dst; unsigned long extra_word = extra/sizeof(u32); int local_rec_size = calc_rec_size(cycles, extra); + uint32_t next; BUG_ON(local_rec_size != rec_size); + BUG_ON(extra & 3); /* Double-check once more that we have enough space. * Don't bugcheck here, in case the userland tool is doing * something stupid. */ if ( calc_bytes_avail(buf) < rec_size ) { - printk("%s: %u bytes left (%u - (%u - %u)) recsize %u.\n", + printk("%s: %u bytes left (%u - ((%u - %u) %% %u) recsize %u.\n", __func__, - data_size - (buf->prod - buf->cons), - data_size, - buf->prod, buf->cons, rec_size); + calc_bytes_avail(buf), + data_size, buf->prod, buf->cons, data_size, rec_size); return 0; } rmb(); - rec = (struct t_rec *)&this_cpu(t_data)[buf->prod % data_size]; + rec = next_record(buf); rec->event = event; rec->extra_u32 = extra_word; dst = (unsigned char *)rec->u.nocycles.extra_u32; @@ -293,7 +326,13 @@ static inline int __insert_record(struct t_buf *buf, memcpy(dst, extra_data, extra); wmb(); - buf->prod += rec_size; + + next = buf->prod + rec_size; + if ( next >= 2*data_size ) + next -= 2*data_size; + ASSERT(next >= 0); + ASSERT(next < 2*data_size); + buf->prod = next; return rec_size; } @@ -395,7 +434,7 @@ void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data) local_irq_save(flags); - started_below_highwater = ((buf->prod - buf->cons) < t_buf_highwater); + started_below_highwater = (calc_unconsumed_bytes(buf) < t_buf_highwater); /* Calculate the record size */ rec_size = calc_rec_size(cycles, extra); @@ -413,10 +452,6 @@ void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data) total_size = 0; /* First, check to see if we need to include a lost_record. - * - * calc_bytes_to_wrap() involves integer division, which we'd like to - * avoid if we can. So do the math, check it in debug versions, and - * do a final check always if we happen to write a record. */ if ( this_cpu(lost_records) ) { @@ -477,7 +512,7 @@ void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data) /* Notify trace buffer consumer that we've crossed the high water mark. */ if ( started_below_highwater && - ((buf->prod - buf->cons) >= t_buf_highwater) ) + (calc_unconsumed_bytes(buf) >= t_buf_highwater) ) raise_softirq(TRACE_SOFTIRQ); } diff --git a/xen/include/public/trace.h b/xen/include/public/trace.h index 4cbb896342..21fe15ffb9 100644 --- a/xen/include/public/trace.h +++ b/xen/include/public/trace.h @@ -141,6 +141,14 @@ struct t_rec { * field, indexes into an array of struct t_rec's. */ struct t_buf { + /* Assume the data buffer size is X. X is generally not a power of 2. + * CONS and PROD are incremented modulo (2*X): + * 0 <= cons < 2*X + * 0 <= prod < 2*X + * This is done because addition modulo X breaks at 2^32 when X is not a + * power of 2: + * (((2^32 - 1) % X) + 1) % X != (2^32) % X + */ uint32_t cons; /* Offset of next item to be consumed by control tools. */ uint32_t prod; /* Offset of next item to be produced by Xen. */ /* Records follow immediately after the meta-data header. */ -- cgit v1.2.3 From 1c8d4c1040bcfda0be3402025efe15c360c2c52d Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 11 Feb 2008 09:46:53 +0000 Subject: xentrace: Improve xentrace to use VIRQ_TBUF interrupts as well as a user-specified polling interval in order to determine when to empty the trace buffers. Removed the old and unused/unimplemented new_data_threshold logic. Signed-off-by: Michael A Fetterman --- tools/xentrace/xentrace.c | 138 +++++++++++++++++++++++++++------------------- 1 file changed, 82 insertions(+), 56 deletions(-) diff --git a/tools/xentrace/xentrace.c b/tools/xentrace/xentrace.c index bd276cc3ed..0879576645 100644 --- a/tools/xentrace/xentrace.c +++ b/tools/xentrace/xentrace.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -40,9 +41,6 @@ do { \ /***** Compile time configuration of defaults ********************************/ -/* when we've got more records than this waiting, we log it to the output */ -#define NEW_DATA_THRESH 1 - /* sleep for this long (milliseconds) between checking the trace buffers */ #define POLL_SLEEP_MILLIS 100 @@ -51,8 +49,7 @@ do { \ typedef struct settings_st { char *outfile; - struct timespec poll_sleep; - unsigned long new_data_thresh; + unsigned long poll_sleep; /* milliseconds to sleep between polls */ uint32_t evt_mask; uint32_t cpu_mask; unsigned long tbuf_size; @@ -63,25 +60,15 @@ settings_t opts; int interrupted = 0; /* gets set if we get a SIGHUP */ +static int xc_handle = -1; +static int event_fd = -1; +static int virq_port = -1; + void close_handler(int signal) { interrupted = 1; } -/** - * millis_to_timespec - convert a time in milliseconds to a struct timespec - * @millis: time interval in milliseconds - */ -struct timespec millis_to_timespec(unsigned long millis) -{ - struct timespec spec; - - spec.tv_sec = millis / 1000; - spec.tv_nsec = (millis % 1000) * 1000; - - return spec; -} - /** * write_buffer - write a section of the trace buffer * @cpu - source buffer CPU ID @@ -143,14 +130,8 @@ void write_buffer(unsigned int cpu, unsigned char *start, int size, static void get_tbufs(unsigned long *mfn, unsigned long *size) { - int xc_handle = xc_interface_open(); int ret; - if ( xc_handle < 0 ) - { - exit(EXIT_FAILURE); - } - if(!opts.tbuf_size) opts.tbuf_size = DEFAULT_TBUF_SIZE; @@ -161,8 +142,6 @@ static void get_tbufs(unsigned long *mfn, unsigned long *size) perror("Couldn't enable trace buffers"); exit(1); } - - xc_interface_close(xc_handle); } /** @@ -176,22 +155,12 @@ static void get_tbufs(unsigned long *mfn, unsigned long *size) struct t_buf *map_tbufs(unsigned long tbufs_mfn, unsigned int num, unsigned long size) { - int xc_handle; struct t_buf *tbufs_mapped; - xc_handle = xc_interface_open(); - - if ( xc_handle < 0 ) - { - exit(EXIT_FAILURE); - } - tbufs_mapped = xc_map_foreign_range(xc_handle, DOMID_XEN, size * num, PROT_READ | PROT_WRITE, tbufs_mfn); - xc_interface_close(xc_handle); - if ( tbufs_mapped == 0 ) { PERROR("Failed to mmap trace buffers"); @@ -210,7 +179,6 @@ struct t_buf *map_tbufs(unsigned long tbufs_mfn, unsigned int num, void set_mask(uint32_t mask, int type) { int ret = 0; - int xc_handle = xc_interface_open(); /* for accessing control interface */ if (type == 1) { ret = xc_tbuf_set_cpu_mask(xc_handle, mask); @@ -220,8 +188,6 @@ void set_mask(uint32_t mask, int type) fprintf(stderr, "change evtmask to 0x%x\n", mask); } - xc_interface_close(xc_handle); - if ( ret != 0 ) { PERROR("Failure to get trace buffer pointer from Xen and set the new mask"); @@ -295,7 +261,6 @@ unsigned char **init_rec_ptrs(struct t_buf **meta, unsigned int num) unsigned int get_num_cpus(void) { xc_physinfo_t physinfo = { 0 }; - int xc_handle = xc_interface_open(); int ret; ret = xc_physinfo(xc_handle, &physinfo); @@ -306,11 +271,70 @@ unsigned int get_num_cpus(void) exit(EXIT_FAILURE); } - xc_interface_close(xc_handle); - return physinfo.nr_cpus; } +/** + * event_init - setup to receive the VIRQ_TBUF event + */ +void event_init(void) +{ + int rc; + + rc = xc_evtchn_open(); + if (rc < 0) { + perror(xc_get_last_error()->message); + exit(EXIT_FAILURE); + } + event_fd = rc; + + rc = xc_evtchn_bind_virq(event_fd, VIRQ_TBUF); + if (rc == -1) { + PERROR("failed to bind to VIRQ port"); + exit(EXIT_FAILURE); + } + virq_port = rc; +} + +/** + * wait_for_event_or_timeout - sleep for the specified number of milliseconds, + * or until an VIRQ_TBUF event occurs + */ +void wait_for_event_or_timeout(unsigned long milliseconds) +{ + int rc; + struct pollfd fd = { .fd = event_fd, + .events = POLLIN | POLLERR }; + int port; + + rc = poll(&fd, 1, milliseconds); + if (rc == -1) { + if (errno == EINTR) + return; + PERROR("poll exitted with an error"); + exit(EXIT_FAILURE); + } + + if (rc == 1) { + port = xc_evtchn_pending(event_fd); + if (port == -1) { + PERROR("failed to read port from evtchn"); + exit(EXIT_FAILURE); + } + if (port != virq_port) { + fprintf(stderr, + "unexpected port returned from evtchn (got %d vs expected %d)\n", + port, virq_port); + exit(EXIT_FAILURE); + } + rc = xc_evtchn_unmask(event_fd, port); + if (rc == -1) { + PERROR("failed to write port to evtchn"); + exit(EXIT_FAILURE); + } + } +} + /** * monitor_tbufs - monitor the contents of tbufs and output to a file @@ -330,6 +354,9 @@ int monitor_tbufs(int outfd) unsigned long data_size; + /* prepare to listen for VIRQ_TBUF */ + event_init(); + /* get number of logical CPUs (and therefore number of trace buffers) */ num = get_num_cpus(); @@ -405,7 +432,7 @@ int monitor_tbufs(int outfd) meta[i]->cons = prod; } - nanosleep(&opts.poll_sleep, NULL); + wait_for_event_or_timeout(opts.poll_sleep); } /* cleanup */ @@ -425,7 +452,7 @@ int monitor_tbufs(int outfd) #define xstr(x) str(x) #define str(x) #x -const char *program_version = "xentrace v1.1"; +const char *program_version = "xentrace v1.2"; const char *program_bug_address = ""; void usage(void) @@ -444,9 +471,6 @@ void usage(void) " N.B. that the trace buffer cannot be resized.\n" \ " if it has already been set this boot cycle,\n" \ " this argument will be ignored.\n" \ -" -t, --log-thresh=l Set number, l, of new records required to\n" \ -" trigger a write to output (default " \ - xstr(NEW_DATA_THRESH) ").\n" \ " -?, --help Show this message\n" \ " -V, --version Print program version\n" \ "\n" \ @@ -525,12 +549,8 @@ void parse_args(int argc, char **argv) { switch ( option ) { - case 't': /* set new records threshold for logging */ - opts.new_data_thresh = argtol(optarg, 0); - break; - case 's': /* set sleep time (given in milliseconds) */ - opts.poll_sleep = millis_to_timespec(argtol(optarg, 0)); + opts.poll_sleep = argtol(optarg, 0); break; case 'c': /* set new cpu mask for filtering*/ @@ -574,13 +594,19 @@ int main(int argc, char **argv) struct sigaction act; opts.outfile = 0; - opts.poll_sleep = millis_to_timespec(POLL_SLEEP_MILLIS); - opts.new_data_thresh = NEW_DATA_THRESH; + opts.poll_sleep = POLL_SLEEP_MILLIS; opts.evt_mask = 0; opts.cpu_mask = 0; parse_args(argc, argv); - + + xc_handle = xc_interface_open(); + if ( xc_handle < 0 ) + { + perror(xc_get_last_error()->message); + exit(EXIT_FAILURE); + } + if ( opts.evt_mask != 0 ) set_mask(opts.evt_mask, 0); -- cgit v1.2.3 From e1b02119e639a9e13f79c99d145bf8a3c535593a Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 11 Feb 2008 09:47:19 +0000 Subject: xentrace: Remove redundant tb_done_init checks, and add missing ones. Hand inspection of gcc -02 output confirms significantly shorter codepaths for inactive (i.e. normal case) tracing. Signed-off-by: Michael A Fetterman --- xen/arch/x86/trace.c | 18 ---------- xen/include/asm-x86/hvm/trace.h | 41 ++++++++++++++++------- xen/include/asm-x86/trace.h | 10 +++--- xen/include/xen/trace.h | 73 +++++++++++++++++++++++++---------------- 4 files changed, 79 insertions(+), 63 deletions(-) diff --git a/xen/arch/x86/trace.c b/xen/arch/x86/trace.c index ddb32202bd..65e66a3280 100644 --- a/xen/arch/x86/trace.c +++ b/xen/arch/x86/trace.c @@ -15,9 +15,6 @@ asmlinkage void trace_hypercall(void) { struct cpu_user_regs *regs = guest_cpu_user_regs(); - if ( !tb_init_done ) - return; - #ifdef __x86_64__ if ( is_pv_32on64_vcpu(current) ) { @@ -52,9 +49,6 @@ asmlinkage void trace_hypercall(void) void __trace_pv_trap(int trapnr, unsigned long eip, int use_error_code, unsigned error_code) { - if ( !tb_init_done ) - return; - #ifdef __x86_64__ if ( is_pv_32on64_vcpu(current) ) { @@ -99,9 +93,6 @@ void __trace_pv_page_fault(unsigned long addr, unsigned error_code) { unsigned long eip = guest_cpu_user_regs()->eip; - if ( !tb_init_done ) - return; - #ifdef __x86_64__ if ( is_pv_32on64_vcpu(current) ) { @@ -135,9 +126,6 @@ void __trace_pv_page_fault(unsigned long addr, unsigned error_code) void __trace_trap_one_addr(unsigned event, unsigned long va) { - if ( !tb_init_done ) - return; - #ifdef __x86_64__ if ( is_pv_32on64_vcpu(current) ) { @@ -155,9 +143,6 @@ void __trace_trap_one_addr(unsigned event, unsigned long va) void __trace_trap_two_addr(unsigned event, unsigned long va1, unsigned long va2) { - if ( !tb_init_done ) - return; - #ifdef __x86_64__ if ( is_pv_32on64_vcpu(current) ) { @@ -185,9 +170,6 @@ void __trace_ptwr_emulation(unsigned long addr, l1_pgentry_t npte) { unsigned long eip = guest_cpu_user_regs()->eip; - if ( !tb_init_done ) - return; - /* We have a couple of different modes to worry about: * - 32-on-32: 32-bit pte, 32-bit virtual addresses * - pae-on-pae, pae-on-64: 64-bit pte, 32-bit virtual addresses diff --git a/xen/include/asm-x86/hvm/trace.h b/xen/include/asm-x86/hvm/trace.h index 54c578f912..04f90e0f98 100644 --- a/xen/include/asm-x86/hvm/trace.h +++ b/xen/include/asm-x86/hvm/trace.h @@ -37,6 +37,9 @@ static inline void hvmtrace_vmexit(struct vcpu *v, unsigned long rip, unsigned long exit_reason) { + if ( likely(!tb_init_done) ) + return; + #ifdef __x86_64__ if(hvm_long_mode_enabled(v)) { @@ -50,7 +53,7 @@ static inline void hvmtrace_vmexit(struct vcpu *v, d.vid = v->vcpu_id; d.exit_reason = exit_reason; d.rip = rip; - trace_var(TRC_HVM_VMEXIT64, 1/*cycles*/, sizeof(d), (unsigned char *)&d); + __trace_var(TRC_HVM_VMEXIT64, 1/*cycles*/, sizeof(d), (unsigned char *)&d); } else { #endif struct { @@ -63,7 +66,7 @@ static inline void hvmtrace_vmexit(struct vcpu *v, d.vid = v->vcpu_id; d.exit_reason = exit_reason; d.eip = rip; - trace_var(TRC_HVM_VMEXIT, 1/*cycles*/, sizeof(d), (unsigned char *)&d); + __trace_var(TRC_HVM_VMEXIT, 1/*cycles*/, sizeof(d), (unsigned char *)&d); #ifdef __x86_64__ } #endif @@ -75,9 +78,13 @@ static inline void hvmtrace_vmentry(struct vcpu *v) struct { unsigned did:16, vid:16; } d; + + if ( likely(!tb_init_done) ) + return; + d.did = v->domain->domain_id; d.vid = v->vcpu_id; - trace_var(TRC_HVM_VMENTRY, 1/*cycles*/, sizeof(d), (unsigned char *)&d); + __trace_var(TRC_HVM_VMENTRY, 1/*cycles*/, sizeof(d), (unsigned char *)&d); } static inline void hvmtrace_msr_read(struct vcpu *v, u32 ecx, u64 msr_content) @@ -87,11 +94,15 @@ static inline void hvmtrace_msr_read(struct vcpu *v, u32 ecx, u64 msr_content) u32 ecx; u64 msr_content; } d; + + if ( likely(!tb_init_done) ) + return; + d.did = v->domain->domain_id; d.vid = v->vcpu_id; d.ecx = ecx; d.msr_content = msr_content; - trace_var(TRC_HVM_MSR_READ, 0/*!cycles*/, sizeof(d), (unsigned char *)&d); + __trace_var(TRC_HVM_MSR_READ, 0/*!cycles*/, sizeof(d), (unsigned char *)&d); } static inline void hvmtrace_msr_write(struct vcpu *v, u32 ecx, u64 msr_content) @@ -101,16 +112,23 @@ static inline void hvmtrace_msr_write(struct vcpu *v, u32 ecx, u64 msr_content) u32 ecx; u64 msr_content; } d; + + if ( likely(!tb_init_done) ) + return; + d.did = v->domain->domain_id; d.vid = v->vcpu_id; d.ecx = ecx; d.msr_content = msr_content; - trace_var(TRC_HVM_MSR_WRITE, 0/*!cycles*/,sizeof(d), (unsigned char *)&d); + __trace_var(TRC_HVM_MSR_WRITE, 0/*!cycles*/,sizeof(d), (unsigned char *)&d); } static inline void hvmtrace_pf_xen(struct vcpu *v, unsigned long va, u32 error_code) { + if ( likely(!tb_init_done) ) + return; + #ifdef __x86_64__ if(hvm_long_mode_enabled(v)) { @@ -123,8 +141,8 @@ static inline void hvmtrace_pf_xen(struct vcpu *v, unsigned long va, d.vid = v->vcpu_id; d.error_code = error_code; d.va = va; - trace_var(TRC_HVM_PF_XEN64, 0/*!cycles*/,sizeof(d), - (unsigned char *)&d); + __trace_var(TRC_HVM_PF_XEN64, 0/*!cycles*/,sizeof(d), + (unsigned char *)&d); } else { #endif struct { @@ -136,7 +154,8 @@ static inline void hvmtrace_pf_xen(struct vcpu *v, unsigned long va, d.vid = v->vcpu_id; d.error_code = error_code; d.va = va; - trace_var(TRC_HVM_PF_XEN, 0/*!cycles*/,sizeof(d), (unsigned char *)&d); + __trace_var(TRC_HVM_PF_XEN, 0/*!cycles*/,sizeof(d), + (unsigned char *)&d); #ifdef __x86_64__ } #endif @@ -144,7 +163,7 @@ static inline void hvmtrace_pf_xen(struct vcpu *v, unsigned long va, #define HVMTRACE_ND(evt, vcpu, count, d1, d2, d3, d4) \ do { \ - if (DO_TRC_HVM_ ## evt) \ + if ( unlikely(tb_init_done) && DO_TRC_HVM_ ## evt ) \ { \ struct { \ unsigned did:16, vid:16; \ @@ -156,8 +175,8 @@ static inline void hvmtrace_pf_xen(struct vcpu *v, unsigned long va, _d.d[1]=(d2); \ _d.d[2]=(d3); \ _d.d[3]=(d4); \ - trace_var(TRC_HVM_ ## evt, 0/*!cycles*/, \ - sizeof(u32)*count+1, (unsigned char *)&_d); \ + __trace_var(TRC_HVM_ ## evt, 0/*!cycles*/, \ + sizeof(u32)*count+1, (unsigned char *)&_d); \ } \ } while(0) diff --git a/xen/include/asm-x86/trace.h b/xen/include/asm-x86/trace.h index c8b13c4b86..e65b5de6ee 100644 --- a/xen/include/asm-x86/trace.h +++ b/xen/include/asm-x86/trace.h @@ -8,7 +8,7 @@ void __trace_pv_trap(int trapnr, unsigned long eip, static inline void trace_pv_trap(int trapnr, unsigned long eip, int use_error_code, unsigned error_code) { - if ( tb_init_done ) + if ( unlikely(tb_init_done) ) __trace_pv_trap(trapnr, eip, use_error_code, error_code); } @@ -16,14 +16,14 @@ void __trace_pv_page_fault(unsigned long addr, unsigned error_code); static inline void trace_pv_page_fault(unsigned long addr, unsigned error_code) { - if ( tb_init_done ) + if ( unlikely(tb_init_done) ) __trace_pv_page_fault(addr, error_code); } void __trace_trap_one_addr(unsigned event, unsigned long va); static inline void trace_trap_one_addr(unsigned event, unsigned long va) { - if ( tb_init_done ) + if ( unlikely(tb_init_done) ) __trace_trap_one_addr(event, va); } @@ -32,14 +32,14 @@ void __trace_trap_two_addr(unsigned event, unsigned long va1, static inline void trace_trap_two_addr(unsigned event, unsigned long va1, unsigned long va2) { - if ( tb_init_done ) + if ( unlikely(tb_init_done) ) __trace_trap_two_addr(event, va1, va2); } void __trace_ptwr_emulation(unsigned long addr, l1_pgentry_t npte); static inline void trace_ptwr_emulation(unsigned long addr, l1_pgentry_t npte) { - if ( tb_init_done ) + if ( unlikely(tb_init_done) ) __trace_ptwr_emulation(addr, npte); } diff --git a/xen/include/xen/trace.h b/xen/include/xen/trace.h index 7635f2dbf6..c5ce88f7ca 100644 --- a/xen/include/xen/trace.h +++ b/xen/include/xen/trace.h @@ -39,7 +39,7 @@ void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data); static inline void trace_var(u32 event, int cycles, int extra, unsigned char *extra_data) { - if( unlikely(tb_init_done) ) + if ( unlikely(tb_init_done) ) __trace_var(event, cycles, extra, extra_data); } @@ -49,49 +49,64 @@ static inline void trace_var(u32 event, int cycles, int extra, trace_var(_e, 1, 0, NULL); \ } while ( 0 ) -#define TRACE_1D(_e,_d) \ +#define TRACE_1D(_e,d1) \ do { \ - u32 _d1; \ - _d1 = _d; \ - trace_var(_e, 1, sizeof(_d1), (unsigned char *)&_d1); \ + if ( unlikely(tb_init_done) ) \ + { \ + u32 _d[1]; \ + _d[0] = d1; \ + __trace_var(_e, 1, sizeof(*_d), (unsigned char *)_d); \ + } \ } while ( 0 ) #define TRACE_2D(_e,d1,d2) \ - do { \ - u32 _d[2]; \ - _d[0]=d1; \ - _d[1]=d2; \ - trace_var(_e, 1, sizeof(*_d)*2, (unsigned char *)_d); \ + do { \ + if ( unlikely(tb_init_done) ) \ + { \ + u32 _d[2]; \ + _d[0] = d1; \ + _d[1] = d2; \ + __trace_var(_e, 1, sizeof(*_d)*2, (unsigned char *)_d); \ + } \ } while ( 0 ) #define TRACE_3D(_e,d1,d2,d3) \ do { \ - u32 _d[3]; \ - _d[0]=d1; \ - _d[1]=d2; \ - _d[2]=d3; \ - trace_var(_e, 1, sizeof(*_d)*3, (unsigned char *)_d); \ + if ( unlikely(tb_init_done) ) \ + { \ + u32 _d[3]; \ + _d[0] = d1; \ + _d[1] = d2; \ + _d[2] = d3; \ + __trace_var(_e, 1, sizeof(*_d)*3, (unsigned char *)_d); \ + } \ } while ( 0 ) #define TRACE_4D(_e,d1,d2,d3,d4) \ do { \ - u32 _d[4]; \ - _d[0]=d1; \ - _d[1]=d2; \ - _d[2]=d3; \ - _d[3]=d4; \ - trace_var(_e, 1, sizeof(*_d)*4, (unsigned char *)_d); \ + if ( unlikely(tb_init_done) ) \ + { \ + u32 _d[4]; \ + _d[0] = d1; \ + _d[1] = d2; \ + _d[2] = d3; \ + _d[3] = d4; \ + __trace_var(_e, 1, sizeof(*_d)*4, (unsigned char *)_d); \ + } \ } while ( 0 ) #define TRACE_5D(_e,d1,d2,d3,d4,d5) \ - do { \ - u32 _d[5]; \ - _d[0]=d1; \ - _d[1]=d2; \ - _d[2]=d3; \ - _d[3]=d4; \ - _d[4]=d5; \ - trace_var(_e, 1, sizeof(*_d)*5, (unsigned char *)_d); \ + do { \ + if ( unlikely(tb_init_done) ) \ + { \ + u32 _d[5]; \ + _d[0] = d1; \ + _d[1] = d2; \ + _d[2] = d3; \ + _d[3] = d4; \ + _d[4] = d5; \ + __trace_var(_e, 1, sizeof(*_d)*5, (unsigned char *)_d); \ + } \ } while ( 0 ) #endif /* __XEN_TRACE_H__ */ -- cgit v1.2.3 From 0c55a3582f09bea5aa3761012bff7c897d1d3d88 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 11 Feb 2008 09:57:38 +0000 Subject: qemu: Queue mouse clicks. qemu doesn't enqueue mouse events, just records the latest mouse state. This can cause some lost mouse double clicks if the events are not processed fast enought. This patch implements a simple queue for left mouse click events. Signed-off-by: Stefano Stabellini --- tools/ioemu/hw/usb-hid.c | 68 ++++++++++++++++++++++++++++++++++++++++++++---- tools/ioemu/sdl.c | 29 ++++++++++++++------- 2 files changed, 82 insertions(+), 15 deletions(-) diff --git a/tools/ioemu/hw/usb-hid.c b/tools/ioemu/hw/usb-hid.c index e947977313..78b48b8dbb 100644 --- a/tools/ioemu/hw/usb-hid.c +++ b/tools/ioemu/hw/usb-hid.c @@ -224,15 +224,37 @@ static const uint8_t qemu_tablet_hid_report_descriptor[] = { 0xC0, /* End Collection */ }; +static int currentbutton = 0; +typedef struct _mouseclick { + int button_state; + struct _mouseclick *next; +} mouseclick; +static mouseclick mousequeue[20]; +static mouseclick *head = mousequeue; +static mouseclick *tail = mousequeue; + static void usb_mouse_event(void *opaque, int dx1, int dy1, int dz1, int buttons_state) { USBMouseState *s = opaque; + if (s->status_changed == 1){ + //A mouse event is lost + if (buttons_state != currentbutton && tail->next != head) { + //A left click event is lost: let's add it to the queue + //counter++; + tail->button_state = buttons_state; + tail = tail->next; + } + } + else { + s->buttons_state = buttons_state; + } + s->dx += dx1; s->dy += dy1; s->dz += dz1; - s->buttons_state = buttons_state; + currentbutton = buttons_state; s->status_changed = 1; } @@ -240,11 +262,24 @@ static void usb_tablet_event(void *opaque, int x, int y, int dz, int buttons_state) { USBMouseState *s = opaque; + + if (s->status_changed == 1){ + //A mouse event is lost + if (buttons_state != currentbutton && tail->next != head) { + //A left click event is lost: let's add it to the queue + //counter++; + tail->button_state = buttons_state; + tail = tail->next; + } + } + else { + s->buttons_state = buttons_state; + } s->x = x; s->y = y; s->dz += dz; - s->buttons_state = buttons_state; + currentbutton = buttons_state; s->status_changed = 1; } @@ -493,10 +528,17 @@ static int usb_mouse_handle_data(USBDevice *dev, USBPacket *p) else if (s->kind == USB_TABLET) ret = usb_tablet_poll(s, p->data, p->len); - if (!s->status_changed) + if (!s->status_changed) { ret = USB_RET_NAK; - else - s->status_changed = 0; + } else { + if (head != tail) { + s->buttons_state = head->button_state; + head = head->next; + } + else { + s->status_changed = 0; + } + } } else { goto fail; @@ -567,6 +609,14 @@ int usb_mouse_load(QEMUFile *f, void *opaque, int version_id) USBDevice *usb_tablet_init(void) { USBMouseState *s; + int i; + + for (i = 0; i < 19; i++) { + mousequeue[i].button_state = 0; + mousequeue[i].next = &(mousequeue[i + 1]); + } + mousequeue[i].button_state = 0; + mousequeue[i].next = mousequeue; s = qemu_mallocz(sizeof(USBMouseState)); if (!s) @@ -591,6 +641,14 @@ USBDevice *usb_tablet_init(void) USBDevice *usb_mouse_init(void) { USBMouseState *s; + int i; + + for (i = 0; i < 19; i++) { + mousequeue[i].button_state = 0; + mousequeue[i].next = &(mousequeue[i + 1]); + } + mousequeue[i].button_state = 0; + mousequeue[i].next = mousequeue; s = qemu_mallocz(sizeof(USBMouseState)); if (!s) diff --git a/tools/ioemu/sdl.c b/tools/ioemu/sdl.c index 4d6d73a6a1..d2af24752b 100644 --- a/tools/ioemu/sdl.c +++ b/tools/ioemu/sdl.c @@ -259,11 +259,9 @@ static void sdl_grab_end(void) sdl_update_caption(); } -static void sdl_send_mouse_event(int dz) +static void sdl_send_mouse_event(int dx, int dy, int dz, int state) { - int dx, dy, state, buttons; - state = SDL_GetRelativeMouseState(&dx, &dy); - buttons = 0; + int buttons = 0; if (state & SDL_BUTTON(SDL_BUTTON_LEFT)) buttons |= MOUSE_EVENT_LBUTTON; if (state & SDL_BUTTON(SDL_BUTTON_RIGHT)) @@ -425,11 +423,19 @@ static void sdl_refresh(DisplayState *ds) case SDL_MOUSEMOTION: if (gui_grab || kbd_mouse_is_absolute() || absolute_enabled) { - sdl_send_mouse_event(0); + int dx, dy, state; + state = SDL_GetRelativeMouseState(&dx, &dy); + sdl_send_mouse_event(dx, dy, 0, state); } break; - case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: + if (gui_grab || kbd_mouse_is_absolute()) { + int dx, dy, state; + state = SDL_GetRelativeMouseState(&dx, &dy); + sdl_send_mouse_event(dx, dy, 0, state); + } + break; + case SDL_MOUSEBUTTONDOWN: { SDL_MouseButtonEvent *bev = &ev->button; if (!gui_grab && !kbd_mouse_is_absolute()) { @@ -439,16 +445,19 @@ static void sdl_refresh(DisplayState *ds) sdl_grab_start(); } } else { - int dz; + int dx, dy, dz, state; dz = 0; + state = SDL_GetRelativeMouseState(&dx, &dy); #ifdef SDL_BUTTON_WHEELUP - if (bev->button == SDL_BUTTON_WHEELUP && ev->type == SDL_MOUSEBUTTONDOWN) { + if (bev->button == SDL_BUTTON_WHEELUP) { dz = -1; - } else if (bev->button == SDL_BUTTON_WHEELDOWN && ev->type == SDL_MOUSEBUTTONDOWN) { + } else if (bev->button == SDL_BUTTON_WHEELDOWN) { dz = 1; + } else { + state = bev->button | state; } #endif - sdl_send_mouse_event(dz); + sdl_send_mouse_event(dx, dy, dz, state); } } break; -- cgit v1.2.3 From b108e290094d61a8fc3fdd5d131cc3a523ad1eb2 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 11 Feb 2008 10:01:42 +0000 Subject: ioemu stubdom: make TPM optional Signed-off-by: Samuel Thibault --- tools/ioemu/Makefile.target | 1 + tools/ioemu/hw/pc.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/tools/ioemu/Makefile.target b/tools/ioemu/Makefile.target index ebd691b5f0..2b1bc6bb13 100644 --- a/tools/ioemu/Makefile.target +++ b/tools/ioemu/Makefile.target @@ -420,6 +420,7 @@ VL_OBJS+= xen_machine_pv.o VL_OBJS+= xenfb.o VL_OBJS+= xen_console.o VL_OBJS+= tpm_tis.o +CPPFLAGS += -DHAS_TPM CPPFLAGS += -DHAS_AUDIO endif ifeq ($(TARGET_BASE_ARCH), ppc) diff --git a/tools/ioemu/hw/pc.c b/tools/ioemu/hw/pc.c index 5d982016a6..430d932942 100644 --- a/tools/ioemu/hw/pc.c +++ b/tools/ioemu/hw/pc.c @@ -1013,8 +1013,10 @@ static void pc_init1(uint64_t ram_size, int vga_ram_size, char *boot_device, } } +#ifdef HAS_TPM if (has_tpm_device()) tpm_tis_init(&pic_set_irq_new, isa_pic, 11); +#endif kbd_init(); DMA_init(0); -- cgit v1.2.3 From 3988274ce74895aca83ebbf1c492fa94e8fc9797 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 11 Feb 2008 10:02:39 +0000 Subject: ioemu: fix compilation without softfloat Signed-off-by: Samuel Thibault --- tools/ioemu/cpu-all.h | 10 ++++++++++ tools/ioemu/target-i386-dm/cpu.h | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/tools/ioemu/cpu-all.h b/tools/ioemu/cpu-all.h index 2f125b785d..9cc854ed7c 100644 --- a/tools/ioemu/cpu-all.h +++ b/tools/ioemu/cpu-all.h @@ -116,6 +116,7 @@ static inline void tswap64s(uint64_t *s) #define bswaptls(s) bswap64s(s) #endif +#ifdef CONFIG_SOFTFLOAT /* NOTE: arm FPA is horrible as double 32 bit words are stored in big endian ! */ typedef union { @@ -134,6 +135,7 @@ typedef union { #endif uint64_t ll; } CPU_DoubleU; +#endif /* CPU memory access without any memory or io remapping */ @@ -267,6 +269,7 @@ static inline void stq_le_p(void *ptr, uint64_t v) stl_le_p(p + 4, v >> 32); } +#ifdef CONFIG_SOFTFLOAT /* float access */ static inline float32 ldfl_le_p(void *ptr) @@ -304,6 +307,7 @@ static inline void stfq_le_p(void *ptr, float64 v) stl_le_p(ptr, u.l.lower); stl_le_p(ptr + 4, u.l.upper); } +#endif #else @@ -342,6 +346,7 @@ static inline void stq_le_p(void *ptr, uint64_t v) *(uint64_t *)ptr = v; } +#ifdef CONFIG_SOFTFLOAT /* float access */ static inline float32 ldfl_le_p(void *ptr) @@ -364,6 +369,7 @@ static inline void stfq_le_p(void *ptr, float64 v) *(float64 *)ptr = v; } #endif +#endif #if !defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED) @@ -456,6 +462,7 @@ static inline void stq_be_p(void *ptr, uint64_t v) stl_be_p(ptr + 4, v); } +#ifdef CONFIG_SOFTFLOAT /* float access */ static inline float32 ldfl_be_p(void *ptr) @@ -493,6 +500,7 @@ static inline void stfq_be_p(void *ptr, float64 v) stl_be_p(ptr, u.l.upper); stl_be_p(ptr + 4, u.l.lower); } +#endif #else @@ -531,6 +539,7 @@ static inline void stq_be_p(void *ptr, uint64_t v) *(uint64_t *)ptr = v; } +#ifdef CONFIG_SOFTFLOAT /* float access */ static inline float32 ldfl_be_p(void *ptr) @@ -552,6 +561,7 @@ static inline void stfq_be_p(void *ptr, float64 v) { *(float64 *)ptr = v; } +#endif #endif diff --git a/tools/ioemu/target-i386-dm/cpu.h b/tools/ioemu/target-i386-dm/cpu.h index 017b8c021b..6071a8529e 100644 --- a/tools/ioemu/target-i386-dm/cpu.h +++ b/tools/ioemu/target-i386-dm/cpu.h @@ -37,17 +37,21 @@ #include "cpu-defs.h" +#ifdef CONFIG_SOFTFLOAT #include "softfloat.h" +#endif #if defined(__i386__) && !defined(CONFIG_SOFTMMU) #define USE_CODE_COPY #endif +#ifdef CONFIG_SOFTFLOAT #ifdef USE_X86LDOUBLE typedef floatx80 CPU86_LDouble; #else typedef float64 CPU86_LDouble; #endif +#endif /* Empty for now */ typedef struct CPUX86State { -- cgit v1.2.3 From a408cea2055b5cc0ff84349a979c675c1e3e4109 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 11 Feb 2008 10:03:05 +0000 Subject: ioemu: make AIO optional (already done upstream) Signed-off-by: Samuel Thibault --- tools/ioemu/block-raw.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/ioemu/block-raw.c b/tools/ioemu/block-raw.c index 68e8a370ca..1ecf29cdb5 100644 --- a/tools/ioemu/block-raw.c +++ b/tools/ioemu/block-raw.c @@ -25,7 +25,9 @@ #include "block_int.h" #include #ifndef _WIN32 +#ifndef NO_AIO #include +#endif #ifndef QEMU_TOOL #include "exec-all.h" @@ -255,6 +257,7 @@ label__raw_write__success: /***********************************************************/ /* Unix AIO using POSIX AIO */ +#ifndef NO_AIO typedef struct RawAIOCB { BlockDriverAIOCB common; struct aiocb aiocb; @@ -480,6 +483,7 @@ static void raw_aio_cancel(BlockDriverAIOCB *blockacb) pacb = &acb->next; } } +#endif static void raw_close(BlockDriverState *bs) { @@ -600,10 +604,12 @@ BlockDriver bdrv_raw = { raw_create, raw_flush, +#ifndef NO_AIO .bdrv_aio_read = raw_aio_read, .bdrv_aio_write = raw_aio_write, .bdrv_aio_cancel = raw_aio_cancel, .aiocb_size = sizeof(RawAIOCB), +#endif .protocol_name = "file", .bdrv_pread = raw_pread, .bdrv_pwrite = raw_pwrite, @@ -936,10 +942,12 @@ BlockDriver bdrv_host_device = { NULL, raw_flush, +#ifndef NO_AIO .bdrv_aio_read = raw_aio_read, .bdrv_aio_write = raw_aio_write, .bdrv_aio_cancel = raw_aio_cancel, .aiocb_size = sizeof(RawAIOCB), +#endif .bdrv_pread = raw_pread, .bdrv_pwrite = raw_pwrite, .bdrv_getlength = raw_getlength, -- cgit v1.2.3 From a20ab8a007d760117956003cdd7389de7bd45f23 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 11 Feb 2008 10:03:19 +0000 Subject: ioemu: some ifndef NO_UNIX_SOCKETS were missing Signed-off-by: Samuel Thibault --- tools/ioemu/vl.c | 14 +++++++------- tools/ioemu/vnc.c | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index fc81fd16e1..ebd35c5656 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -2532,7 +2532,7 @@ static void udp_chr_update_read_handler(CharDriverState *chr) } int parse_host_port(struct sockaddr_in *saddr, const char *str); -#ifndef _WIN32 +#ifndef NO_UNIX_SOCKETS static int parse_unix_path(struct sockaddr_un *uaddr, const char *str); #endif int parse_host_src_port(struct sockaddr_in *haddr, @@ -2740,7 +2740,7 @@ static void tcp_chr_accept(void *opaque) CharDriverState *chr = opaque; TCPCharDriver *s = chr->opaque; struct sockaddr_in saddr; -#ifndef _WIN32 +#ifndef NO_UNIX_SOCKETS struct sockaddr_un uaddr; #endif struct sockaddr *addr; @@ -2748,7 +2748,7 @@ static void tcp_chr_accept(void *opaque) int fd; for(;;) { -#ifndef _WIN32 +#ifndef NO_UNIX_SOCKETS if (s->is_unix) { len = sizeof(uaddr); addr = (struct sockaddr *)&uaddr; @@ -2797,13 +2797,13 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, int do_nodelay = 0; const char *ptr; struct sockaddr_in saddr; -#ifndef _WIN32 +#ifndef NO_UNIX_SOCKETS struct sockaddr_un uaddr; #endif struct sockaddr *addr; socklen_t addrlen; -#ifndef _WIN32 +#ifndef NO_UNIX_SOCKETS if (is_unix) { addr = (struct sockaddr *)&uaddr; addrlen = sizeof(uaddr); @@ -2842,7 +2842,7 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, if (!s) goto fail; -#ifndef _WIN32 +#ifndef NO_UNIX_SOCKETS if (is_unix) fd = socket(PF_UNIX, SOCK_STREAM, 0); else @@ -2867,7 +2867,7 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, if (is_listen) { /* allow fast reuse */ -#ifndef _WIN32 +#ifndef NO_UNIX_SOCKETS if (is_unix) { char path[109]; strncpy(path, uaddr.sun_path, 108); diff --git a/tools/ioemu/vnc.c b/tools/ioemu/vnc.c index 0dd78dd4b4..df83f51650 100644 --- a/tools/ioemu/vnc.c +++ b/tools/ioemu/vnc.c @@ -2297,7 +2297,7 @@ int vnc_display_open(DisplayState *ds, const char *display, int find_unused) { struct sockaddr *addr; struct sockaddr_in iaddr; -#ifndef _WIN32 +#ifndef NO_UNIX_SOCKETS struct sockaddr_un uaddr; #endif int reuse_addr, ret; -- cgit v1.2.3 From 0d037cb707a0a6c8d55c099f709420192359d8d4 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 11 Feb 2008 10:03:48 +0000 Subject: ioemu stubdom: make daemonize optional Signed-off-by: Samuel Thibault --- tools/ioemu/vl.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index ebd35c5656..82300c510d 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -80,6 +80,7 @@ #include #define getopt_long_only getopt_long #define memalign(align, size) malloc(size) +#define NO_DAEMONIZE 1 #endif #include "qemu_socket.h" @@ -186,7 +187,9 @@ const char *vnc_display; int acpi_enabled = 0; int fd_bootchk = 1; int no_reboot = 0; +#ifndef NO_DAEMONIZE int daemonize = 0; +#endif const char *option_rom[MAX_OPTION_ROMS]; int nb_option_roms; int semihosting_enabled = 0; @@ -6510,7 +6513,7 @@ void help(void) "-vnc display start a VNC server on display\n" "-vncviewer start a vncviewer process for this domain\n" "-vncunused bind the VNC server to an unused port\n" -#ifndef _WIN32 +#ifndef NO_DAEMONIZE "-daemonize daemonize QEMU after initializing\n" #endif "-option-rom rom load a file, rom, into the option ROM space\n" @@ -6600,7 +6603,9 @@ enum { QEMU_OPTION_vnc, QEMU_OPTION_no_acpi, QEMU_OPTION_no_reboot, +#ifndef NO_DAEMONIZE QEMU_OPTION_daemonize, +#endif QEMU_OPTION_option_rom, QEMU_OPTION_semihosting , @@ -6698,7 +6703,9 @@ const QEMUOption qemu_options[] = { { "cirrusvga", 0, QEMU_OPTION_cirrusvga }, { "no-acpi", 0, QEMU_OPTION_no_acpi }, { "no-reboot", 0, QEMU_OPTION_no_reboot }, +#ifndef NO_DAEMONIZE { "daemonize", 0, QEMU_OPTION_daemonize }, +#endif { "option-rom", HAS_ARG, QEMU_OPTION_option_rom }, #if defined(TARGET_ARM) { "semihosting", 0, QEMU_OPTION_semihosting }, @@ -7496,9 +7503,11 @@ int main(int argc, char **argv) case QEMU_OPTION_no_reboot: no_reboot = 1; break; +#ifndef NO_DAEMONIZE case QEMU_OPTION_daemonize: daemonize = 1; break; +#endif case QEMU_OPTION_option_rom: if (nb_option_roms >= MAX_OPTION_ROMS) { fprintf(stderr, "Too many option ROMs\n"); @@ -7542,7 +7551,7 @@ int main(int argc, char **argv) sprintf(qemu_dm_logfilename, "/var/log/xen/qemu-dm-%d.log", domid); cpu_set_log_filename(qemu_dm_logfilename); -#ifndef _WIN32 +#ifndef NO_DAEMONIZE if (daemonize && !nographic && vnc_display == NULL && vncunused == 0) { fprintf(stderr, "Can only daemonize if using -nographic or -vnc\n"); daemonize = 0; @@ -7863,6 +7872,7 @@ int main(int argc, char **argv) } } +#ifndef NO_DAEMONIZE if (daemonize) { uint8_t status = 0; ssize_t len; @@ -7886,6 +7896,7 @@ int main(int argc, char **argv) close(fd); } +#endif /* Unblock SIGTERM, which may have been blocked by the caller */ sigemptyset(&set); -- cgit v1.2.3 From 250e4ae1c7cd9b51ce0fe265d522dcb6379911a6 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 11 Feb 2008 10:06:51 +0000 Subject: domain builder: make vfb = [ 'type=sdl' ] work When setting vfb = [ 'type=sdl' ] in a domain config file, qemu seems to be still using vnc. Make it use sdl as expected. Signed-off-by: Samuel Thibault --- tools/python/xen/xend/image.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py index 02ea81c748..0519e32a26 100644 --- a/tools/python/xen/xend/image.py +++ b/tools/python/xen/xend/image.py @@ -91,12 +91,12 @@ class ImageHandler: ("image/cmdline", self.cmdline), ("image/ramdisk", self.ramdisk)) - self.dmargs = self.parseDeviceModelArgs(vmConfig) self.device_model = vmConfig['platform'].get('device_model') self.display = vmConfig['platform'].get('display') self.xauthority = vmConfig['platform'].get('xauthority') self.vncconsole = vmConfig['platform'].get('vncconsole') + self.dmargs = self.parseDeviceModelArgs(vmConfig) self.pid = None @@ -204,8 +204,14 @@ class ImageHandler: for dev_uuid in vmConfig['console_refs']: dev_type, dev_info = vmConfig['devices'][dev_uuid] if dev_type == 'vfb': - vnc_config = dev_info.get('other_config', {}) - has_vnc = True + vfb_type = dev_info.get('type', {}) + if vfb_type == 'sdl': + self.display = dev_info.get('display', {}) + self.xauthority = dev_info.get('xauthority', {}) + has_sdl = True + else: + vnc_config = dev_info.get('other_config', {}) + has_vnc = True break keymap = vmConfig['platform'].get("keymap") -- cgit v1.2.3 From ce49af7f2c633c65cbf0eb10c1b1d503cff7688f Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 11 Feb 2008 10:15:07 +0000 Subject: xend: Remove redundant xc.domain_setcpuweight() all the way down to libxenctrl. Signed-off-by: Masaki Kanno Signed-off-by: Keir Fraser --- tools/libxc/xc_domain.c | 15 --------------- tools/libxc/xenctrl.h | 3 --- tools/python/xen/lowlevel/xc/xc.c | 28 ---------------------------- tools/python/xen/xend/XendDomainInfo.py | 3 --- 4 files changed, 49 deletions(-) diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c index f75955c577..0f28ed5ca5 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -350,21 +350,6 @@ int xc_shadow_control(int xc_handle, return (rc == 0) ? domctl.u.shadow_op.pages : rc; } -int xc_domain_setcpuweight(int xc_handle, - uint32_t domid, - float weight) -{ - int sched_id; - int ret; - - /* Figure out which scheduler is currently used: */ - if ( (ret = xc_sched_id(xc_handle, &sched_id)) != 0 ) - return ret; - - /* No-op. */ - return 0; -} - int xc_domain_setmaxmem(int xc_handle, uint32_t domid, unsigned int max_memkb) diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index f6778dd946..b9e9abd249 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -380,9 +380,6 @@ int xc_vcpu_getinfo(int xc_handle, uint32_t vcpu, xc_vcpuinfo_t *info); -int xc_domain_setcpuweight(int xc_handle, - uint32_t domid, - float weight); long long xc_domain_get_cpu_usage(int xc_handle, domid_t domid, int vcpu); diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c index 425ed7b0fe..305138bd70 100644 --- a/tools/python/xen/lowlevel/xc/xc.c +++ b/tools/python/xen/lowlevel/xc/xc.c @@ -237,26 +237,6 @@ static PyObject *pyxc_vcpu_setaffinity(XcObject *self, return zero; } -static PyObject *pyxc_domain_setcpuweight(XcObject *self, - PyObject *args, - PyObject *kwds) -{ - uint32_t dom; - float cpuweight = 1; - - static char *kwd_list[] = { "domid", "cpuweight", NULL }; - - if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|f", kwd_list, - &dom, &cpuweight) ) - return NULL; - - if ( xc_domain_setcpuweight(self->xc_handle, dom, cpuweight) != 0 ) - return pyxc_error_to_exception(); - - Py_INCREF(zero); - return zero; -} - static PyObject *pyxc_domain_sethandle(XcObject *self, PyObject *args) { int i; @@ -1325,14 +1305,6 @@ static PyMethodDef pyxc_methods[] = { " cpumap [list, []]: list of usable CPUs.\n\n" "Returns: [int] 0 on success; -1 on error.\n" }, - { "domain_setcpuweight", - (PyCFunction)pyxc_domain_setcpuweight, - METH_VARARGS | METH_KEYWORDS, "\n" - "Set cpuweight scheduler parameter for domain.\n" - " dom [int]: Identifier of domain to be changed.\n" - " cpuweight [float, 1]: VCPU being pinned.\n" - "Returns: [int] 0 on success; -1 on error.\n" }, - { "domain_sethandle", (PyCFunction)pyxc_domain_sethandle, METH_VARARGS, "\n" diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 1e9c1b11f5..f00ac38ce6 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -1750,9 +1750,6 @@ class XendDomainInfo: self.image = image.create(self, self.info) - xc.domain_setcpuweight(self.domid, \ - self.info['vcpus_params']['weight']) - # repin domain vcpus if a restricted cpus list is provided # this is done prior to memory allocation to aide in memory # distribution for NUMA systems. -- cgit v1.2.3 From 670d6b908ff2fba90536b8f139fb2c66506b253e Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 11 Feb 2008 10:16:53 +0000 Subject: x86 shadow: Move the shadow linear mapping for n-on-3-on-4 shadows so that guest mappings of the bottom 4GB are not reflected in the monitor pagetable. This ensures in particular that page 0 is not mapped, allowing us to catch NULL dereferences in the hypervisor. Signed-off-by: Tim Deegan --- xen/arch/x86/mm/shadow/multi.c | 104 +++++++++++++++++++++++++++-------------- 1 file changed, 70 insertions(+), 34 deletions(-) diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c index f12a97fbde..1be74c70d6 100644 --- a/xen/arch/x86/mm/shadow/multi.c +++ b/xen/arch/x86/mm/shadow/multi.c @@ -1470,10 +1470,14 @@ void sh_install_xen_entries_in_l4(struct vcpu *v, mfn_t gl4mfn, mfn_t sl4mfn) shadow_l4e_from_mfn(page_to_mfn(virt_to_page(d->arch.mm_perdomain_l3)), __PAGE_HYPERVISOR); - /* Linear mapping */ + /* Shadow linear mapping for 4-level shadows. N.B. for 3-level + * shadows on 64-bit xen, this linear mapping is later replaced by the + * monitor pagetable structure, which is built in make_monitor_table + * and maintained by sh_update_linear_entries. */ sl4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)] = shadow_l4e_from_mfn(sl4mfn, __PAGE_HYPERVISOR); + /* Self linear mapping. */ if ( shadow_mode_translate(v->domain) && !shadow_mode_external(v->domain) ) { // linear tables may not be used with translated PV guests @@ -1745,7 +1749,7 @@ sh_make_monitor_table(struct vcpu *v) ASSERT(pagetable_get_pfn(v->arch.monitor_table) == 0); /* Guarantee we can get the memory we need */ - shadow_prealloc(d, SH_type_monitor_table, CONFIG_PAGING_LEVELS - 1); + shadow_prealloc(d, SH_type_monitor_table, CONFIG_PAGING_LEVELS); #if CONFIG_PAGING_LEVELS == 4 { @@ -1755,22 +1759,34 @@ sh_make_monitor_table(struct vcpu *v) /* Remember the level of this table */ mfn_to_page(m4mfn)->shadow_flags = 4; #if SHADOW_PAGING_LEVELS < 4 - // Install a monitor l3 table in slot 0 of the l4 table. - // This is used for shadow linear maps. { - mfn_t m3mfn; + mfn_t m3mfn, m2mfn; l4_pgentry_t *l4e; + l3_pgentry_t *l3e; + /* Install an l3 table and an l2 table that will hold the shadow + * linear map entries. This overrides the linear map entry that + * was installed by sh_install_xen_entries_in_l4. */ + l4e = sh_map_domain_page(m4mfn); + m3mfn = shadow_alloc(d, SH_type_monitor_table, 0); mfn_to_page(m3mfn)->shadow_flags = 3; - l4e = sh_map_domain_page(m4mfn); - l4e[0] = l4e_from_pfn(mfn_x(m3mfn), __PAGE_HYPERVISOR); - sh_unmap_domain_page(l4e); + l4e[shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START)] + = l4e_from_pfn(mfn_x(m3mfn), __PAGE_HYPERVISOR); + + m2mfn = shadow_alloc(d, SH_type_monitor_table, 0); + mfn_to_page(m2mfn)->shadow_flags = 2; + l3e = sh_map_domain_page(m3mfn); + l3e[0] = l3e_from_pfn(mfn_x(m2mfn), __PAGE_HYPERVISOR); + sh_unmap_domain_page(l3e); + if ( is_pv_32on64_vcpu(v) ) { - // Install a monitor l2 table in slot 3 of the l3 table. - // This is used for all Xen entries. - mfn_t m2mfn; - l3_pgentry_t *l3e; + /* For 32-on-64 PV guests, we need to map the 32-bit Xen + * area into its usual VAs in the monitor tables */ + m3mfn = shadow_alloc(d, SH_type_monitor_table, 0); + mfn_to_page(m3mfn)->shadow_flags = 3; + l4e[0] = l4e_from_pfn(mfn_x(m3mfn), __PAGE_HYPERVISOR); + m2mfn = shadow_alloc(d, SH_type_monitor_table, 0); mfn_to_page(m2mfn)->shadow_flags = 2; l3e = sh_map_domain_page(m3mfn); @@ -1778,6 +1794,8 @@ sh_make_monitor_table(struct vcpu *v) sh_install_xen_entries_in_l2h(v, m2mfn); sh_unmap_domain_page(l3e); } + + sh_unmap_domain_page(l4e); } #endif /* SHADOW_PAGING_LEVELS < 4 */ return m4mfn; @@ -2181,21 +2199,34 @@ void sh_destroy_monitor_table(struct vcpu *v, mfn_t mmfn) ASSERT(mfn_to_shadow_page(mmfn)->type == SH_type_monitor_table); #if (CONFIG_PAGING_LEVELS == 4) && (SHADOW_PAGING_LEVELS != 4) - /* Need to destroy the l3 monitor page in slot 0 too */ { mfn_t m3mfn; l4_pgentry_t *l4e = sh_map_domain_page(mmfn); - ASSERT(l4e_get_flags(l4e[0]) & _PAGE_PRESENT); - m3mfn = _mfn(l4e_get_pfn(l4e[0])); + l3_pgentry_t *l3e; + int linear_slot = shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START); + + /* Need to destroy the l3 and l2 monitor pages used + * for the linear map */ + ASSERT(l4e_get_flags(l4e[linear_slot]) & _PAGE_PRESENT); + m3mfn = _mfn(l4e_get_pfn(l4e[linear_slot])); + l3e = sh_map_domain_page(m3mfn); + ASSERT(l3e_get_flags(l3e[0]) & _PAGE_PRESENT); + shadow_free(d, _mfn(l3e_get_pfn(l3e[0]))); + sh_unmap_domain_page(l3e); + shadow_free(d, m3mfn); + if ( is_pv_32on64_vcpu(v) ) { - /* Need to destroy the l2 monitor page in slot 3 too */ - l3_pgentry_t *l3e = sh_map_domain_page(m3mfn); + /* Need to destroy the l3 and l2 monitor pages that map the + * Xen VAs at 3GB-4GB */ + ASSERT(l4e_get_flags(l4e[0]) & _PAGE_PRESENT); + m3mfn = _mfn(l4e_get_pfn(l4e[0])); + l3e = sh_map_domain_page(m3mfn); ASSERT(l3e_get_flags(l3e[3]) & _PAGE_PRESENT); shadow_free(d, _mfn(l3e_get_pfn(l3e[3]))); sh_unmap_domain_page(l3e); + shadow_free(d, m3mfn); } - shadow_free(d, m3mfn); sh_unmap_domain_page(l4e); } #elif CONFIG_PAGING_LEVELS == 3 @@ -3222,28 +3253,33 @@ sh_update_linear_entries(struct vcpu *v) if ( shadow_mode_external(d) ) { - /* Install copies of the shadow l3es into the monitor l3 table. - * The monitor l3 table is hooked into slot 0 of the monitor - * l4 table, so we use l3 linear indices 0 to 3 */ + /* Install copies of the shadow l3es into the monitor l2 table + * that maps SH_LINEAR_PT_VIRT_START. */ shadow_l3e_t *sl3e; - l3_pgentry_t *ml3e; - mfn_t l3mfn; + l2_pgentry_t *ml2e; int i; /* Use linear mappings if we can; otherwise make new mappings */ - if ( v == current ) - { - ml3e = __linear_l3_table; - l3mfn = _mfn(l4e_get_pfn(__linear_l4_table[0])); - } + if ( v == current ) + ml2e = __linear_l2_table + + l2_linear_offset(SH_LINEAR_PT_VIRT_START); else { + mfn_t l3mfn, l2mfn; l4_pgentry_t *ml4e; + l3_pgentry_t *ml3e; + int linear_slot = shadow_l4_table_offset(SH_LINEAR_PT_VIRT_START); ml4e = sh_map_domain_page(pagetable_get_mfn(v->arch.monitor_table)); - ASSERT(l4e_get_flags(ml4e[0]) & _PAGE_PRESENT); - l3mfn = _mfn(l4e_get_pfn(ml4e[0])); + + ASSERT(l4e_get_flags(ml4e[linear_slot]) & _PAGE_PRESENT); + l3mfn = _mfn(l4e_get_pfn(ml4e[linear_slot])); ml3e = sh_map_domain_page(l3mfn); sh_unmap_domain_page(ml4e); + + ASSERT(l3e_get_flags(ml3e[0]) & _PAGE_PRESENT); + l2mfn = _mfn(l3e_get_pfn(ml3e[0])); + ml2e = sh_map_domain_page(l2mfn); + sh_unmap_domain_page(ml3e); } /* Shadow l3 tables are made up by sh_update_cr3 */ @@ -3251,15 +3287,15 @@ sh_update_linear_entries(struct vcpu *v) for ( i = 0; i < SHADOW_L3_PAGETABLE_ENTRIES; i++ ) { - ml3e[i] = + ml2e[i] = (shadow_l3e_get_flags(sl3e[i]) & _PAGE_PRESENT) - ? l3e_from_pfn(mfn_x(shadow_l3e_get_mfn(sl3e[i])), + ? l2e_from_pfn(mfn_x(shadow_l3e_get_mfn(sl3e[i])), __PAGE_HYPERVISOR) - : l3e_empty(); + : l2e_empty(); } if ( v != current ) - sh_unmap_domain_page(ml3e); + sh_unmap_domain_page(ml2e); } else domain_crash(d); /* XXX */ -- cgit v1.2.3 From 9990562d743ae236991e49af6a439b4f67a67649 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 11 Feb 2008 10:20:31 +0000 Subject: Document XenStore's new SET_TARGET message Signed-off-by: Ryan O'Connor --- docs/misc/xenstore.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/misc/xenstore.txt b/docs/misc/xenstore.txt index 90632863df..baf2c42dc0 100644 --- a/docs/misc/xenstore.txt +++ b/docs/misc/xenstore.txt @@ -296,6 +296,16 @@ RESUME | xenstored prevents the use of RESUME other than by dom0. +SET_TARGET || + Notifies xenstored that domain is targeting domain + . This grants domain full access to paths + owned by . Domain also inherits all + permissions granted to on all other paths. This + allows to behave as if it were dom0 when modifying + paths related to . + + xenstored prevents the use of SET_TARGET other than by dom0. + ---------- Miscellaneous ---------- DEBUG print||?? sends to debug log -- cgit v1.2.3 From b65a97ff7378c6aae7f3c9326823b58c29d28a07 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 11 Feb 2008 10:50:57 +0000 Subject: x86: Fix build after xentrace changes. Signed-off-by: Keir Fraser --- xen/include/asm-x86/hvm/trace.h | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/xen/include/asm-x86/hvm/trace.h b/xen/include/asm-x86/hvm/trace.h index 04f90e0f98..cb4dc10ad8 100644 --- a/xen/include/asm-x86/hvm/trace.h +++ b/xen/include/asm-x86/hvm/trace.h @@ -31,8 +31,6 @@ #define DO_TRC_HVM_CLTS 1 #define DO_TRC_HVM_LMSW 1 - - static inline void hvmtrace_vmexit(struct vcpu *v, unsigned long rip, unsigned long exit_reason) @@ -41,7 +39,7 @@ static inline void hvmtrace_vmexit(struct vcpu *v, return; #ifdef __x86_64__ - if(hvm_long_mode_enabled(v)) + if ( hvm_long_mode_enabled(v) ) { struct { unsigned did:16, vid:16; @@ -53,9 +51,12 @@ static inline void hvmtrace_vmexit(struct vcpu *v, d.vid = v->vcpu_id; d.exit_reason = exit_reason; d.rip = rip; - __trace_var(TRC_HVM_VMEXIT64, 1/*cycles*/, sizeof(d), (unsigned char *)&d); - } else { + __trace_var(TRC_HVM_VMEXIT64, 1/*cycles*/, sizeof(d), + (unsigned char *)&d); + } + else #endif + { struct { unsigned did:16, vid:16; unsigned exit_reason:32; @@ -66,10 +67,9 @@ static inline void hvmtrace_vmexit(struct vcpu *v, d.vid = v->vcpu_id; d.exit_reason = exit_reason; d.eip = rip; - __trace_var(TRC_HVM_VMEXIT, 1/*cycles*/, sizeof(d), (unsigned char *)&d); -#ifdef __x86_64__ + __trace_var(TRC_HVM_VMEXIT, 1/*cycles*/, sizeof(d), + (unsigned char *)&d); } -#endif } @@ -102,7 +102,8 @@ static inline void hvmtrace_msr_read(struct vcpu *v, u32 ecx, u64 msr_content) d.vid = v->vcpu_id; d.ecx = ecx; d.msr_content = msr_content; - __trace_var(TRC_HVM_MSR_READ, 0/*!cycles*/, sizeof(d), (unsigned char *)&d); + __trace_var(TRC_HVM_MSR_READ, 0/*!cycles*/, sizeof(d), + (unsigned char *)&d); } static inline void hvmtrace_msr_write(struct vcpu *v, u32 ecx, u64 msr_content) @@ -120,7 +121,8 @@ static inline void hvmtrace_msr_write(struct vcpu *v, u32 ecx, u64 msr_content) d.vid = v->vcpu_id; d.ecx = ecx; d.msr_content = msr_content; - __trace_var(TRC_HVM_MSR_WRITE, 0/*!cycles*/,sizeof(d), (unsigned char *)&d); + __trace_var(TRC_HVM_MSR_WRITE, 0/*!cycles*/,sizeof(d), + (unsigned char *)&d); } static inline void hvmtrace_pf_xen(struct vcpu *v, unsigned long va, @@ -130,7 +132,7 @@ static inline void hvmtrace_pf_xen(struct vcpu *v, unsigned long va, return; #ifdef __x86_64__ - if(hvm_long_mode_enabled(v)) + if( hvm_long_mode_enabled(v) ) { struct { unsigned did:16, vid:16; @@ -143,8 +145,10 @@ static inline void hvmtrace_pf_xen(struct vcpu *v, unsigned long va, d.va = va; __trace_var(TRC_HVM_PF_XEN64, 0/*!cycles*/,sizeof(d), (unsigned char *)&d); - } else { + } + else #endif + { struct { unsigned did:16, vid:16; u32 error_code; @@ -156,9 +160,7 @@ static inline void hvmtrace_pf_xen(struct vcpu *v, unsigned long va, d.va = va; __trace_var(TRC_HVM_PF_XEN, 0/*!cycles*/,sizeof(d), (unsigned char *)&d); -#ifdef __x86_64__ } -#endif } #define HVMTRACE_ND(evt, vcpu, count, d1, d2, d3, d4) \ @@ -186,7 +188,8 @@ static inline void hvmtrace_pf_xen(struct vcpu *v, unsigned long va, #define HVMTRACE_1D(evt, vcpu, d1) HVMTRACE_ND(evt, vcpu, 1, d1, 0, 0, 0) #define HVMTRACE_0D(evt, vcpu) HVMTRACE_ND(evt, vcpu, 0, 0, 0, 0, 0) -#endif //__ASM_X86_HVM_TRACE_H__ +#endif /* __ASM_X86_HVM_TRACE_H__ */ + /* * Local variables: * mode: C -- cgit v1.2.3 From be0999cb87d4e5fbaa9b96f604918db02229f71e Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 11 Feb 2008 10:51:41 +0000 Subject: vt-d: Remap interrupt for passthru device if such HW is detected on VT-d platforms. Signed-off-by: Allen Kay --- xen/arch/x86/hvm/vmx/vtd/Makefile | 1 + xen/arch/x86/hvm/vmx/vtd/extern.h | 7 +- xen/arch/x86/hvm/vmx/vtd/intel-iommu.c | 6 +- xen/arch/x86/hvm/vmx/vtd/intremap.c | 340 +++++++++++++++++++++++++++++++++ xen/include/asm-x86/io_apic.h | 5 + xen/include/asm-x86/iommu.h | 4 + 6 files changed, 356 insertions(+), 7 deletions(-) create mode 100644 xen/arch/x86/hvm/vmx/vtd/intremap.c diff --git a/xen/arch/x86/hvm/vmx/vtd/Makefile b/xen/arch/x86/hvm/vmx/vtd/Makefile index 1cae6385ab..dcff4e3ab1 100644 --- a/xen/arch/x86/hvm/vmx/vtd/Makefile +++ b/xen/arch/x86/hvm/vmx/vtd/Makefile @@ -3,3 +3,4 @@ obj-y += dmar.o obj-y += utils.o obj-y += io.o obj-y += qinval.o +obj-y += intremap.o diff --git a/xen/arch/x86/hvm/vmx/vtd/extern.h b/xen/arch/x86/hvm/vmx/vtd/extern.h index 6143b935b9..9e2ac576ea 100644 --- a/xen/arch/x86/hvm/vmx/vtd/extern.h +++ b/xen/arch/x86/hvm/vmx/vtd/extern.h @@ -23,11 +23,6 @@ #include "dmar.h" -extern int iommu_setup_done; -extern int vtd2_thurley_enabled; -extern int vtd2_qinval_enabled; - -extern spinlock_t ioapic_lock; extern struct qi_ctrl *qi_ctrl; extern struct ir_ctrl *ir_ctrl; @@ -37,6 +32,7 @@ void print_vtd_entries(struct domain *d, struct iommu *iommu, void pdev_flr(u8 bus, u8 devfn); int qinval_setup(struct iommu *iommu); +int intremap_setup(struct iommu *iommu); int queue_invalidate_context(struct iommu *iommu, u16 did, u16 source_id, u8 function_mask, u8 granu); int queue_invalidate_iotlb(struct iommu *iommu, @@ -46,7 +42,6 @@ int queue_invalidate_iec(struct iommu *iommu, int invalidate_sync(struct iommu *iommu); int iommu_flush_iec_global(struct iommu *iommu); int iommu_flush_iec_index(struct iommu *iommu, u8 im, u16 iidx); -void gsi_remapping(unsigned int gsi); void print_iommu_regs(struct acpi_drhd_unit *drhd); int vtd_hw_check(void); struct iommu * ioapic_to_iommu(unsigned int apic_id); diff --git a/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c b/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c index 4b05f1d87c..eb2c5eef8e 100644 --- a/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c +++ b/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c @@ -1816,9 +1816,13 @@ static int init_vtd_hw(void) flush->context = flush_context_reg; flush->iotlb = flush_iotlb_reg; - if ( qinval_setup(iommu) != 0); + if ( qinval_setup(iommu) != 0 ) dprintk(XENLOG_ERR VTDPREFIX, "Queued Invalidation hardware not found\n"); + + if ( intremap_setup(iommu) != 0 ) + dprintk(XENLOG_ERR VTDPREFIX, + "Interrupt Remapping hardware not found\n"); } return 0; } diff --git a/xen/arch/x86/hvm/vmx/vtd/intremap.c b/xen/arch/x86/hvm/vmx/vtd/intremap.c new file mode 100644 index 0000000000..21645599b6 --- /dev/null +++ b/xen/arch/x86/hvm/vmx/vtd/intremap.c @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2006, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + * Copyright (C) Allen Kay + * Copyright (C) Xiaohui Xin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "dmar.h" +#include "vtd.h" +#include "pci-direct.h" +#include "pci_regs.h" +#include "msi.h" +#include "extern.h" + +u16 apicid_to_bdf(int apic_id) +{ + struct acpi_drhd_unit *drhd = ioapic_to_drhd(apic_id); + struct acpi_ioapic_unit *acpi_ioapic_unit; + + list_for_each_entry ( acpi_ioapic_unit, &drhd->ioapic_list, list ) + if ( acpi_ioapic_unit->apic_id == apic_id ) + return acpi_ioapic_unit->ioapic.info; + + dprintk(XENLOG_ERR VTDPREFIX, "Didn't find the bdf for the apic_id!\n"); + return 0; +} + +static void remap_entry_to_ioapic_rte( + struct iommu *iommu, struct IO_APIC_route_entry *old_rte) +{ + struct iremap_entry *iremap_entry = NULL; + struct IO_APIC_route_remap_entry *remap_rte; + unsigned int index; + unsigned long flags; + struct ir_ctrl *ir_ctrl = iommu_ir_ctrl(iommu); + + if ( ir_ctrl == NULL ) + { + dprintk(XENLOG_ERR VTDPREFIX, + "remap_entry_to_ioapic_rte: ir_ctl == NULL"); + return; + } + + remap_rte = (struct IO_APIC_route_remap_entry *) old_rte; + index = (remap_rte->index_15 << 15) + remap_rte->index_0_14; + + if ( index > ir_ctrl->iremap_index ) + { + dprintk(XENLOG_ERR VTDPREFIX, + "Index is larger than remap table entry size. Error!\n"); + return; + } + + spin_lock_irqsave(&ir_ctrl->iremap_lock, flags); + + iremap_entry = &ir_ctrl->iremap[index]; + + old_rte->vector = iremap_entry->lo.vector; + old_rte->delivery_mode = iremap_entry->lo.dlm; + old_rte->dest_mode = iremap_entry->lo.dm; + old_rte->trigger = iremap_entry->lo.tm; + old_rte->__reserved_2 = 0; + old_rte->dest.logical.__reserved_1 = 0; + old_rte->dest.logical.logical_dest = iremap_entry->lo.dst; + + spin_unlock_irqrestore(&ir_ctrl->iremap_lock, flags); +} + +static void ioapic_rte_to_remap_entry(struct iommu *iommu, + int apic_id, struct IO_APIC_route_entry *old_rte) +{ + struct iremap_entry *iremap_entry = NULL; + struct IO_APIC_route_remap_entry *remap_rte; + unsigned int index; + unsigned long flags; + int ret = 0; + struct ir_ctrl *ir_ctrl = iommu_ir_ctrl(iommu); + + remap_rte = (struct IO_APIC_route_remap_entry *) old_rte; + spin_lock_irqsave(&ir_ctrl->iremap_lock, flags); + index = ir_ctrl->iremap_index; + if ( index > IREMAP_ENTRY_NR - 1 ) + { + dprintk(XENLOG_ERR VTDPREFIX, + "The interrupt number is more than 256!\n"); + goto out; + } + + iremap_entry = &(ir_ctrl->iremap[index]); + if ( *(u64 *)iremap_entry != 0 ) + dprintk(XENLOG_WARNING VTDPREFIX, + "Interrupt remapping entry is in use already!\n"); + iremap_entry->lo.fpd = 0; + iremap_entry->lo.dm = old_rte->dest_mode; + iremap_entry->lo.rh = 0; + iremap_entry->lo.tm = old_rte->trigger; + iremap_entry->lo.dlm = old_rte->delivery_mode; + iremap_entry->lo.avail = 0; + iremap_entry->lo.res_1 = 0; + iremap_entry->lo.vector = old_rte->vector; + iremap_entry->lo.res_2 = 0; + iremap_entry->lo.dst = (old_rte->dest.logical.logical_dest << 8); + iremap_entry->hi.sid = apicid_to_bdf(apic_id); + iremap_entry->hi.sq = 0; /* comparing all 16-bit of SID */ + iremap_entry->hi.svt = 1; /* turn on requestor ID verification SID/SQ */ + iremap_entry->hi.res_1 = 0; + iremap_entry->lo.p = 1; /* finally, set present bit */ + ir_ctrl->iremap_index++; + + iommu_flush_iec_index(iommu, 0, index); + ret = invalidate_sync(iommu); + + /* now construct new ioapic rte entry */ + remap_rte->vector = old_rte->vector; + remap_rte->delivery_mode = 0; /* has to be 0 for remap format */ + remap_rte->index_15 = index & 0x8000; + remap_rte->index_0_14 = index & 0x7fff; + remap_rte->delivery_status = old_rte->delivery_status; + remap_rte->polarity = old_rte->polarity; + remap_rte->irr = old_rte->irr; + remap_rte->trigger = old_rte->trigger; + remap_rte->mask = 1; + remap_rte->reserved = 0; + remap_rte->format = 1; /* indicate remap format */ +out: + spin_unlock_irqrestore(&ir_ctrl->iremap_lock, flags); + return; +} + +unsigned int +io_apic_read_remap_rte( + unsigned int apic, unsigned int reg) +{ + struct IO_APIC_route_entry old_rte = { 0 }; + struct IO_APIC_route_remap_entry *remap_rte; + int rte_upper = (reg & 1) ? 1 : 0; + struct iommu *iommu = ioapic_to_iommu(mp_ioapics[apic].mpc_apicid); + struct ir_ctrl *ir_ctrl = iommu_ir_ctrl(iommu); + + if ( !iommu || !(ir_ctrl->iremap) ) + { + *IO_APIC_BASE(apic) = reg; + return *(IO_APIC_BASE(apic)+4); + } + + if ( rte_upper ) + reg--; + + /* read lower and upper 32-bits of rte entry */ + *IO_APIC_BASE(apic) = reg; + *(((u32 *)&old_rte) + 0) = *(IO_APIC_BASE(apic)+4); + *IO_APIC_BASE(apic) = reg + 1; + *(((u32 *)&old_rte) + 1) = *(IO_APIC_BASE(apic)+4); + + remap_rte = (struct IO_APIC_route_remap_entry *) &old_rte; + + if ( remap_rte->mask || (remap_rte->format == 0) ) + { + *IO_APIC_BASE(apic) = reg; + return *(IO_APIC_BASE(apic)+4); + } + + remap_entry_to_ioapic_rte(iommu, &old_rte); + if ( rte_upper ) + { + *IO_APIC_BASE(apic) = reg + 1; + return (*(((u32 *)&old_rte) + 1)); + } + else + { + *IO_APIC_BASE(apic) = reg; + return (*(((u32 *)&old_rte) + 0)); + } +} + +void +io_apic_write_remap_rte( + unsigned int apic, unsigned int reg, unsigned int value) +{ + struct IO_APIC_route_entry old_rte = { 0 }; + struct IO_APIC_route_remap_entry *remap_rte; + int rte_upper = (reg & 1) ? 1 : 0; + struct iommu *iommu = ioapic_to_iommu(mp_ioapics[apic].mpc_apicid); + struct ir_ctrl *ir_ctrl = iommu_ir_ctrl(iommu); + + if ( !iommu || !(ir_ctrl->iremap) ) + { + *IO_APIC_BASE(apic) = reg; + *(IO_APIC_BASE(apic)+4) = value; + return; + } + + if ( rte_upper ) + reg--; + + /* read both lower and upper 32-bits of rte entry */ + *IO_APIC_BASE(apic) = reg; + *(((u32 *)&old_rte) + 0) = *(IO_APIC_BASE(apic)+4); + *IO_APIC_BASE(apic) = reg + 1; + *(((u32 *)&old_rte) + 1) = *(IO_APIC_BASE(apic)+4); + + remap_rte = (struct IO_APIC_route_remap_entry *) &old_rte; + if ( remap_rte->mask || (remap_rte->format == 0) ) + { + *IO_APIC_BASE(apic) = rte_upper ? ++reg : reg; + *(IO_APIC_BASE(apic)+4) = value; + return; + } + + *(((u32 *)&old_rte) + rte_upper) = value; + ioapic_rte_to_remap_entry(iommu, mp_ioapics[apic].mpc_apicid, &old_rte); + + /* write new entry to ioapic */ + *IO_APIC_BASE(apic) = reg; + *(IO_APIC_BASE(apic)+4) = *(((int *)&old_rte)+0); + *IO_APIC_BASE(apic) = reg + 1; + *(IO_APIC_BASE(apic)+4) = *(((int *)&old_rte)+1); +} + +int intremap_setup(struct iommu *iommu) +{ + struct ir_ctrl *ir_ctrl; + unsigned long start_time; + u64 paddr; + + if ( !ecap_intr_remap(iommu->ecap) ) + return -ENODEV; + + ir_ctrl = iommu_ir_ctrl(iommu); + if ( ir_ctrl->iremap == NULL ) + { + ir_ctrl->iremap = alloc_xenheap_page(); + if ( ir_ctrl->iremap == NULL ) + { + dprintk(XENLOG_WARNING VTDPREFIX, + "Cannot allocate memory for ir_ctrl->iremap\n"); + return -ENODEV; + } + memset(ir_ctrl->iremap, 0, PAGE_SIZE); + } + + paddr = virt_to_maddr(ir_ctrl->iremap); +#if defined(ENABLED_EXTENDED_INTERRUPT_SUPPORT) + /* set extended interrupt mode bit */ + paddr |= ecap_ext_intr(iommu->ecap) ? (1 << IRTA_REG_EIMI_SHIFT) : 0; +#endif + /* size field = 256 entries per 4K page = 8 - 1 */ + paddr |= 7; + dmar_writeq(iommu->reg, DMAR_IRTA_REG, paddr); + + /* set SIRTP */ + iommu->gcmd |= DMA_GCMD_SIRTP; + dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd); + + /* Make sure hardware complete it */ + start_time = jiffies; + while ( !(dmar_readl(iommu->reg, DMAR_GSTS_REG) & DMA_GSTS_SIRTPS) ) + { + if ( time_after(jiffies, start_time + DMAR_OPERATION_TIMEOUT) ) + { + dprintk(XENLOG_ERR VTDPREFIX, + "Cannot set SIRTP field for interrupt remapping\n"); + return -ENODEV; + } + cpu_relax(); + } + + /* enable comaptiblity format interrupt pass through */ + iommu->gcmd |= DMA_GCMD_CFI; + dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd); + + start_time = jiffies; + while ( !(dmar_readl(iommu->reg, DMAR_GSTS_REG) & DMA_GSTS_CFIS) ) + { + if ( time_after(jiffies, start_time + DMAR_OPERATION_TIMEOUT) ) + { + dprintk(XENLOG_ERR VTDPREFIX, + "Cannot set CFI field for interrupt remapping\n"); + return -ENODEV; + } + cpu_relax(); + } + + /* enable interrupt remapping hardware */ + iommu->gcmd |= DMA_GCMD_IRE; + dmar_writel(iommu->reg, DMAR_GCMD_REG, iommu->gcmd); + + start_time = jiffies; + while ( !(dmar_readl(iommu->reg, DMAR_GSTS_REG) & DMA_GSTS_IRES) ) + { + if ( time_after(jiffies, start_time + DMAR_OPERATION_TIMEOUT) ) + { + dprintk(XENLOG_ERR VTDPREFIX, + "Cannot set IRE field for interrupt remapping\n"); + return -ENODEV; + } + cpu_relax(); + } + + /* After set SIRTP, we should do globally invalidate the IEC */ + iommu_flush_iec_global(iommu); + + return 0; +} diff --git a/xen/include/asm-x86/io_apic.h b/xen/include/asm-x86/io_apic.h index e8e102a6b8..86c91b6762 100644 --- a/xen/include/asm-x86/io_apic.h +++ b/xen/include/asm-x86/io_apic.h @@ -6,6 +6,7 @@ #include #include #include +#include /* * Intel IO-APIC support for SMP and UP systems. @@ -124,12 +125,16 @@ extern int mpc_default_type; static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) { + if (vtd_enabled) + return io_apic_read_remap_rte(apic, reg); *IO_APIC_BASE(apic) = reg; return *(IO_APIC_BASE(apic)+4); } static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value) { + if (vtd_enabled) + return io_apic_write_remap_rte(apic, reg, value); *IO_APIC_BASE(apic) = reg; *(IO_APIC_BASE(apic)+4) = value; } diff --git a/xen/include/asm-x86/iommu.h b/xen/include/asm-x86/iommu.h index daec64bf76..1f5e61ee63 100644 --- a/xen/include/asm-x86/iommu.h +++ b/xen/include/asm-x86/iommu.h @@ -81,6 +81,10 @@ int hvm_do_IRQ_dpci(struct domain *d, unsigned int irq); int dpci_ioport_intercept(ioreq_t *p); int pt_irq_create_bind_vtd(struct domain *d, xen_domctl_bind_pt_irq_t *pt_irq_bind); +unsigned int io_apic_read_remap_rte( + unsigned int apic, unsigned int reg); +void io_apic_write_remap_rte(unsigned int apic, + unsigned int reg, unsigned int value); #define PT_IRQ_TIME_OUT MILLISECS(8) #define VTDPREFIX "[VT-D]" -- cgit v1.2.3 From 25c2136e0d717a4ca0275efe5270e0f9da2c7aea Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 11 Feb 2008 10:57:17 +0000 Subject: x86: Compile fix for p2m audit code. From Tom Woller. Signed-off-by: Tim Deegan --- xen/arch/x86/mm/p2m.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c index ee98ae8c6a..b82e7ef704 100644 --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -486,6 +486,7 @@ static void audit_p2m(struct domain *d) mfn_t p2mfn; unsigned long orphans_d = 0, orphans_i = 0, mpbad = 0, pmbad = 0; int test_linear; + p2m_type_t type; if ( !paging_mode_translate(d) ) return; @@ -534,7 +535,7 @@ static void audit_p2m(struct domain *d) continue; } - p2mfn = gfn_to_mfn_foreign(d, gfn); + p2mfn = gfn_to_mfn_foreign(d, gfn, &type); if ( mfn_x(p2mfn) != mfn ) { mpbad++; @@ -547,12 +548,12 @@ static void audit_p2m(struct domain *d) /* This m2p entry is stale: the domain has another frame in * this physical slot. No great disaster, but for neatness, * blow away the m2p entry. */ - set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY, __PAGE_HYPERVISOR|_PAGE_USER); + set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY); } if ( test_linear && (gfn <= d->arch.p2m.max_mapped_pfn) ) { - lp2mfn = mfn_x(gfn_to_mfn_current(gfn)); + lp2mfn = mfn_x(gfn_to_mfn_current(gfn, &type)); if ( lp2mfn != mfn_x(p2mfn) ) { P2M_PRINTK("linear mismatch gfn %#lx -> mfn %#lx " -- cgit v1.2.3 From 81375c4b062c25871e2af0b45977b4a0a2141250 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 11 Feb 2008 14:42:52 +0000 Subject: xend: Better support for legacy HVM config with hvmloader configured via the 'kernel' config option: 1. Look for any string containing 'hvmloader'. 2. The 'kernel' option must be scrubbed to avoid taking PV-kernel-loading paths during later guest setup. Signed-off-by: Keir Fraser --- tools/python/xen/xend/XendConfig.py | 10 ++++------ tools/python/xen/xend/image.py | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index 1eb7ee78ca..5c76e02650 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -406,15 +406,13 @@ class XendConfig(dict): if self.is_hvm(): if 'loader' not in self['platform']: - log.debug("No loader present") - # Old configs may have hvmloder set as PV_kernel param, - # so lets migrate them.... - if self['PV_kernel'] == "/usr/lib/xen/boot/hvmloader": + # Old configs may have hvmloader set as PV_kernel param + if self.has_key('PV_kernel') and re.search('hvmloader', self['PV_kernel']): self['platform']['loader'] = self['PV_kernel'] - log.debug("Loader copied from kernel %s" % str(self['platform']['loader'])) + self['PV_kernel'] = '' else: self['platform']['loader'] = "/usr/lib/xen/boot/hvmloader" - log.debug("Loader %s" % str(self['platform']['loader'])) + log.debug("Loader is %s" % str(self['platform']['loader'])) # Compatibility hack, can go away soon. if 'soundhw' not in self['platform'] and \ diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py index 0519e32a26..4ceb36194f 100644 --- a/tools/python/xen/xend/image.py +++ b/tools/python/xen/xend/image.py @@ -455,7 +455,7 @@ class HVMImageHandler(ImageHandler): ret = ImageHandler.parseDeviceModelArgs(self, vmConfig) ret = ret + ['-vcpus', str(self.vm.getVCpuCount())] - if self.kernel and self.kernel != "/usr/lib/xen/boot/hvmloader": + if self.kernel: log.debug("kernel = %s", self.kernel) ret = ret + ['-kernel', self.kernel] if self.ramdisk: -- cgit v1.2.3 From 3f8e22de799b510d3ee20b730e4a30cc6c01dc6f Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 11 Feb 2008 14:45:29 +0000 Subject: x86 hvm: Allow HPET to be configured as a per-domain config option. A new platform variable 'hpet' is added, which defaults to 0 for new guests (that is, hpet disabled). Default is off (no hpet) because hpet is currently less accurate in keeping time than PIT (because no timer_mode adjustments). Signed-off-by: Dan Magenheimer Signed-off-by: Keir Fraser --- tools/firmware/hvmloader/acpi/build.c | 18 +- tools/firmware/hvmloader/acpi/dsdt.asl | 8 + tools/firmware/hvmloader/acpi/dsdt.c | 896 ++++++++++++++++---------------- tools/python/xen/xend/XendConfig.py | 2 +- tools/python/xen/xend/XendConstants.py | 1 + tools/python/xen/xend/XendDomainInfo.py | 6 + tools/python/xen/xm/create.py | 6 +- tools/python/xen/xm/xenapi_create.py | 3 +- xen/arch/x86/hvm/hpet.c | 3 +- xen/arch/x86/hvm/hvm.c | 2 + xen/include/public/hvm/params.h | 5 +- 11 files changed, 496 insertions(+), 454 deletions(-) diff --git a/tools/firmware/hvmloader/acpi/build.c b/tools/firmware/hvmloader/acpi/build.c index 247c3b5928..e33cc04795 100644 --- a/tools/firmware/hvmloader/acpi/build.c +++ b/tools/firmware/hvmloader/acpi/build.c @@ -62,11 +62,18 @@ static int uart_exists(uint16_t uart_base) return ((b == 0) && (c == 0xf)); } +static int hpet_exists(unsigned long hpet_base) +{ + uint32_t hpet_id = *(uint32_t *)hpet_base; + return ((hpet_id >> 16) == 0x8086); +} + static int construct_bios_info_table(uint8_t *buf) { struct bios_info { uint8_t com1_present:1; uint8_t com2_present:1; + uint8_t hpet_present:1; uint32_t pci_min, pci_len; } *bios_info = (struct bios_info *)buf; @@ -75,6 +82,8 @@ static int construct_bios_info_table(uint8_t *buf) bios_info->com1_present = uart_exists(0x3f8); bios_info->com2_present = uart_exists(0x2f8); + bios_info->hpet_present = hpet_exists(ACPI_HPET_ADDRESS); + bios_info->pci_min = 0xf0000000; bios_info->pci_len = 0x0c000000; @@ -272,9 +281,12 @@ static int construct_secondary_tables(uint8_t *buf, unsigned long *table_ptrs) } /* HPET. */ - hpet = (struct acpi_20_hpet *)&buf[offset]; - offset += construct_hpet(hpet); - table_ptrs[nr_tables++] = (unsigned long)hpet; + if ( hpet_exists(ACPI_HPET_ADDRESS) ) + { + hpet = (struct acpi_20_hpet *)&buf[offset]; + offset += construct_hpet(hpet); + table_ptrs[nr_tables++] = (unsigned long)hpet; + } /* Processor Object SSDT. */ table_ptrs[nr_tables++] = (unsigned long)&buf[offset]; diff --git a/tools/firmware/hvmloader/acpi/dsdt.asl b/tools/firmware/hvmloader/acpi/dsdt.asl index f5c2fefda5..fde51ac0ad 100644 --- a/tools/firmware/hvmloader/acpi/dsdt.asl +++ b/tools/firmware/hvmloader/acpi/dsdt.asl @@ -49,6 +49,7 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, "Xen", "HVM", 0) Field(BIOS, ByteAcc, NoLock, Preserve) { UAR1, 1, UAR2, 1, + HPET, 1, Offset(4), PMIN, 32, PLEN, 32 @@ -296,6 +297,13 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, "Xen", "HVM", 0) Device(HPET) { Name(_HID, EISAID("PNP0103")) Name(_UID, 0) + Method (_STA, 0, NotSerialized) { + If(LEqual(\_SB.HPET, 0)) { + Return(0x00) + } Else { + Return(0x0F) + } + } Name(_CRS, ResourceTemplate() { DWordMemory( ResourceConsumer, PosDecode, MinFixed, MaxFixed, diff --git a/tools/firmware/hvmloader/acpi/dsdt.c b/tools/firmware/hvmloader/acpi/dsdt.c index ab34c068bb..54088c6746 100644 --- a/tools/firmware/hvmloader/acpi/dsdt.c +++ b/tools/firmware/hvmloader/acpi/dsdt.c @@ -5,15 +5,15 @@ * Copyright (C) 2000 - 2006 Intel Corporation * Supports ACPI Specification Revision 3.0a * - * Compilation of "dsdt.asl" - Mon Jan 21 14:11:31 2008 + * Compilation of "dsdt.asl" - Mon Feb 11 13:31:53 2008 * * C source code output * */ unsigned char AmlCode[] = { - 0x44,0x53,0x44,0x54,0x6F,0x0E,0x00,0x00, /* 00000000 "DSDTo..." */ - 0x02,0xE1,0x58,0x65,0x6E,0x00,0x00,0x00, /* 00000008 "..Xen..." */ + 0x44,0x53,0x44,0x54,0x8E,0x0E,0x00,0x00, /* 00000000 "DSDT...." */ + 0x02,0x6E,0x58,0x65,0x6E,0x00,0x00,0x00, /* 00000008 ".nXen..." */ 0x48,0x56,0x4D,0x00,0x00,0x00,0x00,0x00, /* 00000010 "HVM....." */ 0x00,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ 0x07,0x07,0x06,0x20,0x08,0x50,0x4D,0x42, /* 00000020 "... .PMB" */ @@ -27,452 +27,456 @@ unsigned char AmlCode[] = 0x04,0x0A,0x07,0x0A,0x07,0x00,0x00,0x08, /* 00000060 "........" */ 0x50,0x49,0x43,0x44,0x00,0x14,0x0C,0x5F, /* 00000068 "PICD..._" */ 0x50,0x49,0x43,0x01,0x70,0x68,0x50,0x49, /* 00000070 "PIC.phPI" */ - 0x43,0x44,0x10,0x44,0xDF,0x5F,0x53,0x42, /* 00000078 "CD.D._SB" */ + 0x43,0x44,0x10,0x43,0xE1,0x5F,0x53,0x42, /* 00000078 "CD.C._SB" */ 0x5F,0x5B,0x80,0x42,0x49,0x4F,0x53,0x00, /* 00000080 "_[.BIOS." */ 0x0C,0x00,0xA0,0x0E,0x00,0x0A,0x10,0x5B, /* 00000088 ".......[" */ - 0x81,0x1C,0x42,0x49,0x4F,0x53,0x01,0x55, /* 00000090 "..BIOS.U" */ + 0x81,0x21,0x42,0x49,0x4F,0x53,0x01,0x55, /* 00000090 ".!BIOS.U" */ 0x41,0x52,0x31,0x01,0x55,0x41,0x52,0x32, /* 00000098 "AR1.UAR2" */ - 0x01,0x00,0x1E,0x50,0x4D,0x49,0x4E,0x20, /* 000000A0 "...PMIN " */ - 0x50,0x4C,0x45,0x4E,0x20,0x5B,0x82,0x49, /* 000000A8 "PLEN [.I" */ - 0x04,0x4D,0x45,0x4D,0x30,0x08,0x5F,0x48, /* 000000B0 ".MEM0._H" */ - 0x49,0x44,0x0C,0x41,0xD0,0x0C,0x02,0x08, /* 000000B8 "ID.A...." */ - 0x5F,0x43,0x52,0x53,0x11,0x33,0x0A,0x30, /* 000000C0 "_CRS.3.0" */ - 0x8A,0x2B,0x00,0x00,0x0D,0x03,0x00,0x00, /* 000000C8 ".+......" */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000D0 "........" */ - 0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF, /* 000000D8 "........" */ - 0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000E0 "........" */ + 0x01,0x48,0x50,0x45,0x54,0x01,0x00,0x1D, /* 000000A0 ".HPET..." */ + 0x50,0x4D,0x49,0x4E,0x20,0x50,0x4C,0x45, /* 000000A8 "PMIN PLE" */ + 0x4E,0x20,0x5B,0x82,0x49,0x04,0x4D,0x45, /* 000000B0 "N [.I.ME" */ + 0x4D,0x30,0x08,0x5F,0x48,0x49,0x44,0x0C, /* 000000B8 "M0._HID." */ + 0x41,0xD0,0x0C,0x02,0x08,0x5F,0x43,0x52, /* 000000C0 "A...._CR" */ + 0x53,0x11,0x33,0x0A,0x30,0x8A,0x2B,0x00, /* 000000C8 "S.3.0.+." */ + 0x00,0x0D,0x03,0x00,0x00,0x00,0x00,0x00, /* 000000D0 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000D8 "........" */ + 0x00,0x00,0x00,0xFF,0xFF,0x09,0x00,0x00, /* 000000E0 "........" */ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 000000E8 "........" */ - 0x0A,0x00,0x00,0x00,0x00,0x00,0x79,0x00, /* 000000F0 "......y." */ - 0x5B,0x82,0x45,0xD7,0x50,0x43,0x49,0x30, /* 000000F8 "[.E.PCI0" */ - 0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 00000100 "._HID.A." */ - 0x0A,0x03,0x08,0x5F,0x55,0x49,0x44,0x00, /* 00000108 "..._UID." */ - 0x08,0x5F,0x41,0x44,0x52,0x00,0x08,0x5F, /* 00000110 "._ADR.._" */ - 0x42,0x42,0x4E,0x00,0x14,0x4E,0x0C,0x5F, /* 00000118 "BBN..N._" */ - 0x43,0x52,0x53,0x00,0x08,0x50,0x52,0x54, /* 00000120 "CRS..PRT" */ - 0x30,0x11,0x42,0x07,0x0A,0x6E,0x88,0x0D, /* 00000128 "0.B..n.." */ - 0x00,0x02,0x0E,0x00,0x00,0x00,0x00,0x00, /* 00000130 "........" */ - 0xFF,0x00,0x00,0x00,0x00,0x01,0x47,0x01, /* 00000138 "......G." */ - 0xF8,0x0C,0xF8,0x0C,0x01,0x08,0x88,0x0D, /* 00000140 "........" */ - 0x00,0x01,0x0C,0x03,0x00,0x00,0x00,0x00, /* 00000148 "........" */ - 0xF7,0x0C,0x00,0x00,0xF8,0x0C,0x88,0x0D, /* 00000150 "........" */ - 0x00,0x01,0x0C,0x03,0x00,0x00,0x00,0x0D, /* 00000158 "........" */ - 0xFF,0xFF,0x00,0x00,0x00,0xF3,0x87,0x17, /* 00000160 "........" */ - 0x00,0x00,0x0C,0x03,0x00,0x00,0x00,0x00, /* 00000168 "........" */ - 0x00,0x00,0x0A,0x00,0xFF,0xFF,0x0B,0x00, /* 00000170 "........" */ - 0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00, /* 00000178 "........" */ - 0x87,0x17,0x00,0x00,0x0C,0x03,0x00,0x00, /* 00000180 "........" */ - 0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0xFF, /* 00000188 "........" */ - 0xFF,0xF4,0x00,0x00,0x00,0x00,0x00,0x00, /* 00000190 "........" */ - 0x00,0x05,0x79,0x00,0x8A,0x50,0x52,0x54, /* 00000198 "..y..PRT" */ - 0x30,0x0A,0x5C,0x4D,0x4D,0x49,0x4E,0x8A, /* 000001A0 "0.\MMIN." */ - 0x50,0x52,0x54,0x30,0x0A,0x60,0x4D,0x4D, /* 000001A8 "PRT0.`MM" */ - 0x41,0x58,0x8A,0x50,0x52,0x54,0x30,0x0A, /* 000001B0 "AX.PRT0." */ - 0x68,0x4D,0x4C,0x45,0x4E,0x70,0x50,0x4D, /* 000001B8 "hMLENpPM" */ - 0x49,0x4E,0x4D,0x4D,0x49,0x4E,0x70,0x50, /* 000001C0 "INMMINpP" */ - 0x4C,0x45,0x4E,0x4D,0x4C,0x45,0x4E,0x72, /* 000001C8 "LENMLENr" */ - 0x4D,0x4D,0x49,0x4E,0x4D,0x4C,0x45,0x4E, /* 000001D0 "MMINMLEN" */ - 0x4D,0x4D,0x41,0x58,0x74,0x4D,0x4D,0x41, /* 000001D8 "MMAXtMMA" */ - 0x58,0x01,0x4D,0x4D,0x41,0x58,0xA4,0x50, /* 000001E0 "X.MMAX.P" */ - 0x52,0x54,0x30,0x08,0x42,0x55,0x46,0x41, /* 000001E8 "RT0.BUFA" */ - 0x11,0x09,0x0A,0x06,0x23,0x20,0x0C,0x18, /* 000001F0 "....# .." */ - 0x79,0x00,0x08,0x42,0x55,0x46,0x42,0x11, /* 000001F8 "y..BUFB." */ - 0x09,0x0A,0x06,0x23,0x00,0x00,0x18,0x79, /* 00000200 "...#...y" */ - 0x00,0x8B,0x42,0x55,0x46,0x42,0x01,0x49, /* 00000208 "..BUFB.I" */ - 0x52,0x51,0x56,0x5B,0x82,0x48,0x08,0x4C, /* 00000210 "RQV[.H.L" */ - 0x4E,0x4B,0x41,0x08,0x5F,0x48,0x49,0x44, /* 00000218 "NKA._HID" */ - 0x0C,0x41,0xD0,0x0C,0x0F,0x08,0x5F,0x55, /* 00000220 ".A...._U" */ - 0x49,0x44,0x01,0x14,0x1C,0x5F,0x53,0x54, /* 00000228 "ID..._ST" */ - 0x41,0x00,0x7B,0x50,0x49,0x52,0x41,0x0A, /* 00000230 "A.{PIRA." */ - 0x80,0x60,0xA0,0x08,0x93,0x60,0x0A,0x80, /* 00000238 ".`...`.." */ - 0xA4,0x0A,0x09,0xA1,0x04,0xA4,0x0A,0x0B, /* 00000240 "........" */ - 0x14,0x0B,0x5F,0x50,0x52,0x53,0x00,0xA4, /* 00000248 ".._PRS.." */ - 0x42,0x55,0x46,0x41,0x14,0x11,0x5F,0x44, /* 00000250 "BUFA.._D" */ - 0x49,0x53,0x00,0x7D,0x50,0x49,0x52,0x41, /* 00000258 "IS.}PIRA" */ - 0x0A,0x80,0x50,0x49,0x52,0x41,0x14,0x1A, /* 00000260 "..PIRA.." */ - 0x5F,0x43,0x52,0x53,0x00,0x7B,0x50,0x49, /* 00000268 "_CRS.{PI" */ - 0x52,0x41,0x0A,0x0F,0x60,0x79,0x01,0x60, /* 00000270 "RA..`y.`" */ - 0x49,0x52,0x51,0x56,0xA4,0x42,0x55,0x46, /* 00000278 "IRQV.BUF" */ - 0x42,0x14,0x1B,0x5F,0x53,0x52,0x53,0x01, /* 00000280 "B.._SRS." */ - 0x8B,0x68,0x01,0x49,0x52,0x51,0x31,0x82, /* 00000288 ".h.IRQ1." */ - 0x49,0x52,0x51,0x31,0x60,0x76,0x60,0x70, /* 00000290 "IRQ1`v`p" */ - 0x60,0x50,0x49,0x52,0x41,0x5B,0x82,0x49, /* 00000298 "`PIRA[.I" */ - 0x08,0x4C,0x4E,0x4B,0x42,0x08,0x5F,0x48, /* 000002A0 ".LNKB._H" */ - 0x49,0x44,0x0C,0x41,0xD0,0x0C,0x0F,0x08, /* 000002A8 "ID.A...." */ - 0x5F,0x55,0x49,0x44,0x0A,0x02,0x14,0x1C, /* 000002B0 "_UID...." */ - 0x5F,0x53,0x54,0x41,0x00,0x7B,0x50,0x49, /* 000002B8 "_STA.{PI" */ - 0x52,0x42,0x0A,0x80,0x60,0xA0,0x08,0x93, /* 000002C0 "RB..`..." */ - 0x60,0x0A,0x80,0xA4,0x0A,0x09,0xA1,0x04, /* 000002C8 "`......." */ - 0xA4,0x0A,0x0B,0x14,0x0B,0x5F,0x50,0x52, /* 000002D0 "....._PR" */ - 0x53,0x00,0xA4,0x42,0x55,0x46,0x41,0x14, /* 000002D8 "S..BUFA." */ - 0x11,0x5F,0x44,0x49,0x53,0x00,0x7D,0x50, /* 000002E0 "._DIS.}P" */ - 0x49,0x52,0x42,0x0A,0x80,0x50,0x49,0x52, /* 000002E8 "IRB..PIR" */ - 0x42,0x14,0x1A,0x5F,0x43,0x52,0x53,0x00, /* 000002F0 "B.._CRS." */ - 0x7B,0x50,0x49,0x52,0x42,0x0A,0x0F,0x60, /* 000002F8 "{PIRB..`" */ - 0x79,0x01,0x60,0x49,0x52,0x51,0x56,0xA4, /* 00000300 "y.`IRQV." */ - 0x42,0x55,0x46,0x42,0x14,0x1B,0x5F,0x53, /* 00000308 "BUFB.._S" */ - 0x52,0x53,0x01,0x8B,0x68,0x01,0x49,0x52, /* 00000310 "RS..h.IR" */ - 0x51,0x31,0x82,0x49,0x52,0x51,0x31,0x60, /* 00000318 "Q1.IRQ1`" */ - 0x76,0x60,0x70,0x60,0x50,0x49,0x52,0x42, /* 00000320 "v`p`PIRB" */ - 0x5B,0x82,0x49,0x08,0x4C,0x4E,0x4B,0x43, /* 00000328 "[.I.LNKC" */ - 0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 00000330 "._HID.A." */ - 0x0C,0x0F,0x08,0x5F,0x55,0x49,0x44,0x0A, /* 00000338 "..._UID." */ - 0x03,0x14,0x1C,0x5F,0x53,0x54,0x41,0x00, /* 00000340 "..._STA." */ - 0x7B,0x50,0x49,0x52,0x43,0x0A,0x80,0x60, /* 00000348 "{PIRC..`" */ - 0xA0,0x08,0x93,0x60,0x0A,0x80,0xA4,0x0A, /* 00000350 "...`...." */ - 0x09,0xA1,0x04,0xA4,0x0A,0x0B,0x14,0x0B, /* 00000358 "........" */ - 0x5F,0x50,0x52,0x53,0x00,0xA4,0x42,0x55, /* 00000360 "_PRS..BU" */ - 0x46,0x41,0x14,0x11,0x5F,0x44,0x49,0x53, /* 00000368 "FA.._DIS" */ - 0x00,0x7D,0x50,0x49,0x52,0x43,0x0A,0x80, /* 00000370 ".}PIRC.." */ - 0x50,0x49,0x52,0x43,0x14,0x1A,0x5F,0x43, /* 00000378 "PIRC.._C" */ - 0x52,0x53,0x00,0x7B,0x50,0x49,0x52,0x43, /* 00000380 "RS.{PIRC" */ - 0x0A,0x0F,0x60,0x79,0x01,0x60,0x49,0x52, /* 00000388 "..`y.`IR" */ - 0x51,0x56,0xA4,0x42,0x55,0x46,0x42,0x14, /* 00000390 "QV.BUFB." */ - 0x1B,0x5F,0x53,0x52,0x53,0x01,0x8B,0x68, /* 00000398 "._SRS..h" */ - 0x01,0x49,0x52,0x51,0x31,0x82,0x49,0x52, /* 000003A0 ".IRQ1.IR" */ - 0x51,0x31,0x60,0x76,0x60,0x70,0x60,0x50, /* 000003A8 "Q1`v`p`P" */ - 0x49,0x52,0x43,0x5B,0x82,0x49,0x08,0x4C, /* 000003B0 "IRC[.I.L" */ - 0x4E,0x4B,0x44,0x08,0x5F,0x48,0x49,0x44, /* 000003B8 "NKD._HID" */ - 0x0C,0x41,0xD0,0x0C,0x0F,0x08,0x5F,0x55, /* 000003C0 ".A...._U" */ - 0x49,0x44,0x0A,0x04,0x14,0x1C,0x5F,0x53, /* 000003C8 "ID...._S" */ - 0x54,0x41,0x00,0x7B,0x50,0x49,0x52,0x44, /* 000003D0 "TA.{PIRD" */ - 0x0A,0x80,0x60,0xA0,0x08,0x93,0x60,0x0A, /* 000003D8 "..`...`." */ - 0x80,0xA4,0x0A,0x09,0xA1,0x04,0xA4,0x0A, /* 000003E0 "........" */ - 0x0B,0x14,0x0B,0x5F,0x50,0x52,0x53,0x00, /* 000003E8 "..._PRS." */ - 0xA4,0x42,0x55,0x46,0x41,0x14,0x11,0x5F, /* 000003F0 ".BUFA.._" */ - 0x44,0x49,0x53,0x00,0x7D,0x50,0x49,0x52, /* 000003F8 "DIS.}PIR" */ - 0x44,0x0A,0x80,0x50,0x49,0x52,0x44,0x14, /* 00000400 "D..PIRD." */ - 0x1A,0x5F,0x43,0x52,0x53,0x00,0x7B,0x50, /* 00000408 "._CRS.{P" */ - 0x49,0x52,0x44,0x0A,0x0F,0x60,0x79,0x01, /* 00000410 "IRD..`y." */ - 0x60,0x49,0x52,0x51,0x56,0xA4,0x42,0x55, /* 00000418 "`IRQV.BU" */ - 0x46,0x42,0x14,0x1B,0x5F,0x53,0x52,0x53, /* 00000420 "FB.._SRS" */ - 0x01,0x8B,0x68,0x01,0x49,0x52,0x51,0x31, /* 00000428 "..h.IRQ1" */ - 0x82,0x49,0x52,0x51,0x31,0x60,0x76,0x60, /* 00000430 ".IRQ1`v`" */ - 0x70,0x60,0x50,0x49,0x52,0x44,0x5B,0x82, /* 00000438 "p`PIRD[." */ - 0x3A,0x48,0x50,0x45,0x54,0x08,0x5F,0x48, /* 00000440 ":HPET._H" */ - 0x49,0x44,0x0C,0x41,0xD0,0x01,0x03,0x08, /* 00000448 "ID.A...." */ - 0x5F,0x55,0x49,0x44,0x00,0x08,0x5F,0x43, /* 00000450 "_UID.._C" */ - 0x52,0x53,0x11,0x1F,0x0A,0x1C,0x87,0x17, /* 00000458 "RS......" */ - 0x00,0x00,0x0D,0x01,0x00,0x00,0x00,0x00, /* 00000460 "........" */ - 0x00,0x00,0xD0,0xFE,0xFF,0x03,0xD0,0xFE, /* 00000468 "........" */ - 0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00, /* 00000470 "........" */ - 0x79,0x00,0x14,0x16,0x5F,0x50,0x52,0x54, /* 00000478 "y..._PRT" */ - 0x00,0xA0,0x0A,0x50,0x49,0x43,0x44,0xA4, /* 00000480 "...PICD." */ - 0x50,0x52,0x54,0x41,0xA4,0x50,0x52,0x54, /* 00000488 "PRTA.PRT" */ - 0x50,0x08,0x50,0x52,0x54,0x50,0x12,0x49, /* 00000490 "P.PRTP.I" */ - 0x36,0x3C,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 00000498 "6<......" */ - 0x01,0x00,0x00,0x4C,0x4E,0x4B,0x42,0x00, /* 000004A0 "...LNKB." */ - 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x01,0x00, /* 000004A8 "........" */ - 0x01,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E, /* 000004B0 ".LNKC..." */ - 0x04,0x0C,0xFF,0xFF,0x01,0x00,0x0A,0x02, /* 000004B8 "........" */ - 0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04, /* 000004C0 "LNKD...." */ - 0x0C,0xFF,0xFF,0x01,0x00,0x0A,0x03,0x4C, /* 000004C8 ".......L" */ - 0x4E,0x4B,0x41,0x00,0x12,0x0D,0x04,0x0C, /* 000004D0 "NKA....." */ - 0xFF,0xFF,0x02,0x00,0x00,0x4C,0x4E,0x4B, /* 000004D8 ".....LNK" */ - 0x43,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 000004E0 "C......." */ - 0x02,0x00,0x01,0x4C,0x4E,0x4B,0x44,0x00, /* 000004E8 "...LNKD." */ - 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x02,0x00, /* 000004F0 "........" */ - 0x0A,0x02,0x4C,0x4E,0x4B,0x41,0x00,0x12, /* 000004F8 "..LNKA.." */ - 0x0E,0x04,0x0C,0xFF,0xFF,0x02,0x00,0x0A, /* 00000500 "........" */ - 0x03,0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0D, /* 00000508 ".LNKB..." */ - 0x04,0x0C,0xFF,0xFF,0x03,0x00,0x00,0x4C, /* 00000510 ".......L" */ - 0x4E,0x4B,0x44,0x00,0x12,0x0D,0x04,0x0C, /* 00000518 "NKD....." */ - 0xFF,0xFF,0x03,0x00,0x01,0x4C,0x4E,0x4B, /* 00000520 ".....LNK" */ - 0x41,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 00000528 "A......." */ - 0x03,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x42, /* 00000530 "....LNKB" */ - 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x03, /* 00000538 "........" */ - 0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x43,0x00, /* 00000540 "...LNKC." */ - 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x04,0x00, /* 00000548 "........" */ - 0x00,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0D, /* 00000550 ".LNKA..." */ - 0x04,0x0C,0xFF,0xFF,0x04,0x00,0x01,0x4C, /* 00000558 ".......L" */ - 0x4E,0x4B,0x42,0x00,0x12,0x0E,0x04,0x0C, /* 00000560 "NKB....." */ - 0xFF,0xFF,0x04,0x00,0x0A,0x02,0x4C,0x4E, /* 00000568 "......LN" */ - 0x4B,0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 00000570 "KC......" */ - 0xFF,0x04,0x00,0x0A,0x03,0x4C,0x4E,0x4B, /* 00000578 ".....LNK" */ - 0x44,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 00000580 "D......." */ - 0x05,0x00,0x00,0x4C,0x4E,0x4B,0x42,0x00, /* 00000588 "...LNKB." */ - 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x05,0x00, /* 00000590 "........" */ - 0x01,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E, /* 00000598 ".LNKC..." */ - 0x04,0x0C,0xFF,0xFF,0x05,0x00,0x0A,0x02, /* 000005A0 "........" */ - 0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04, /* 000005A8 "LNKD...." */ - 0x0C,0xFF,0xFF,0x05,0x00,0x0A,0x03,0x4C, /* 000005B0 ".......L" */ - 0x4E,0x4B,0x41,0x00,0x12,0x0D,0x04,0x0C, /* 000005B8 "NKA....." */ - 0xFF,0xFF,0x06,0x00,0x00,0x4C,0x4E,0x4B, /* 000005C0 ".....LNK" */ - 0x43,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 000005C8 "C......." */ - 0x06,0x00,0x01,0x4C,0x4E,0x4B,0x44,0x00, /* 000005D0 "...LNKD." */ - 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x06,0x00, /* 000005D8 "........" */ - 0x0A,0x02,0x4C,0x4E,0x4B,0x41,0x00,0x12, /* 000005E0 "..LNKA.." */ - 0x0E,0x04,0x0C,0xFF,0xFF,0x06,0x00,0x0A, /* 000005E8 "........" */ - 0x03,0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0D, /* 000005F0 ".LNKB..." */ - 0x04,0x0C,0xFF,0xFF,0x07,0x00,0x00,0x4C, /* 000005F8 ".......L" */ - 0x4E,0x4B,0x44,0x00,0x12,0x0D,0x04,0x0C, /* 00000600 "NKD....." */ - 0xFF,0xFF,0x07,0x00,0x01,0x4C,0x4E,0x4B, /* 00000608 ".....LNK" */ - 0x41,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 00000610 "A......." */ - 0x07,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x42, /* 00000618 "....LNKB" */ - 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x07, /* 00000620 "........" */ - 0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x43,0x00, /* 00000628 "...LNKC." */ - 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x08,0x00, /* 00000630 "........" */ - 0x00,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0D, /* 00000638 ".LNKA..." */ - 0x04,0x0C,0xFF,0xFF,0x08,0x00,0x01,0x4C, /* 00000640 ".......L" */ - 0x4E,0x4B,0x42,0x00,0x12,0x0E,0x04,0x0C, /* 00000648 "NKB....." */ - 0xFF,0xFF,0x08,0x00,0x0A,0x02,0x4C,0x4E, /* 00000650 "......LN" */ - 0x4B,0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 00000658 "KC......" */ - 0xFF,0x08,0x00,0x0A,0x03,0x4C,0x4E,0x4B, /* 00000660 ".....LNK" */ - 0x44,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 00000668 "D......." */ - 0x09,0x00,0x00,0x4C,0x4E,0x4B,0x42,0x00, /* 00000670 "...LNKB." */ - 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x09,0x00, /* 00000678 "........" */ - 0x01,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E, /* 00000680 ".LNKC..." */ - 0x04,0x0C,0xFF,0xFF,0x09,0x00,0x0A,0x02, /* 00000688 "........" */ - 0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04, /* 00000690 "LNKD...." */ - 0x0C,0xFF,0xFF,0x09,0x00,0x0A,0x03,0x4C, /* 00000698 ".......L" */ - 0x4E,0x4B,0x41,0x00,0x12,0x0D,0x04,0x0C, /* 000006A0 "NKA....." */ - 0xFF,0xFF,0x0A,0x00,0x00,0x4C,0x4E,0x4B, /* 000006A8 ".....LNK" */ - 0x43,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 000006B0 "C......." */ - 0x0A,0x00,0x01,0x4C,0x4E,0x4B,0x44,0x00, /* 000006B8 "...LNKD." */ - 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x0A,0x00, /* 000006C0 "........" */ - 0x0A,0x02,0x4C,0x4E,0x4B,0x41,0x00,0x12, /* 000006C8 "..LNKA.." */ - 0x0E,0x04,0x0C,0xFF,0xFF,0x0A,0x00,0x0A, /* 000006D0 "........" */ - 0x03,0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0D, /* 000006D8 ".LNKB..." */ - 0x04,0x0C,0xFF,0xFF,0x0B,0x00,0x00,0x4C, /* 000006E0 ".......L" */ - 0x4E,0x4B,0x44,0x00,0x12,0x0D,0x04,0x0C, /* 000006E8 "NKD....." */ - 0xFF,0xFF,0x0B,0x00,0x01,0x4C,0x4E,0x4B, /* 000006F0 ".....LNK" */ - 0x41,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 000006F8 "A......." */ - 0x0B,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x42, /* 00000700 "....LNKB" */ - 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x0B, /* 00000708 "........" */ - 0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x43,0x00, /* 00000710 "...LNKC." */ - 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x0C,0x00, /* 00000718 "........" */ - 0x00,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0D, /* 00000720 ".LNKA..." */ - 0x04,0x0C,0xFF,0xFF,0x0C,0x00,0x01,0x4C, /* 00000728 ".......L" */ - 0x4E,0x4B,0x42,0x00,0x12,0x0E,0x04,0x0C, /* 00000730 "NKB....." */ - 0xFF,0xFF,0x0C,0x00,0x0A,0x02,0x4C,0x4E, /* 00000738 "......LN" */ - 0x4B,0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 00000740 "KC......" */ - 0xFF,0x0C,0x00,0x0A,0x03,0x4C,0x4E,0x4B, /* 00000748 ".....LNK" */ - 0x44,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 00000750 "D......." */ - 0x0D,0x00,0x00,0x4C,0x4E,0x4B,0x42,0x00, /* 00000758 "...LNKB." */ - 0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x0D,0x00, /* 00000760 "........" */ - 0x01,0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E, /* 00000768 ".LNKC..." */ - 0x04,0x0C,0xFF,0xFF,0x0D,0x00,0x0A,0x02, /* 00000770 "........" */ - 0x4C,0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04, /* 00000778 "LNKD...." */ - 0x0C,0xFF,0xFF,0x0D,0x00,0x0A,0x03,0x4C, /* 00000780 ".......L" */ - 0x4E,0x4B,0x41,0x00,0x12,0x0D,0x04,0x0C, /* 00000788 "NKA....." */ - 0xFF,0xFF,0x0E,0x00,0x00,0x4C,0x4E,0x4B, /* 00000790 ".....LNK" */ - 0x43,0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF, /* 00000798 "C......." */ - 0x0E,0x00,0x01,0x4C,0x4E,0x4B,0x44,0x00, /* 000007A0 "...LNKD." */ - 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x0E,0x00, /* 000007A8 "........" */ - 0x0A,0x02,0x4C,0x4E,0x4B,0x41,0x00,0x12, /* 000007B0 "..LNKA.." */ - 0x0E,0x04,0x0C,0xFF,0xFF,0x0E,0x00,0x0A, /* 000007B8 "........" */ - 0x03,0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0D, /* 000007C0 ".LNKB..." */ - 0x04,0x0C,0xFF,0xFF,0x0F,0x00,0x00,0x4C, /* 000007C8 ".......L" */ - 0x4E,0x4B,0x44,0x00,0x12,0x0D,0x04,0x0C, /* 000007D0 "NKD....." */ - 0xFF,0xFF,0x0F,0x00,0x01,0x4C,0x4E,0x4B, /* 000007D8 ".....LNK" */ - 0x41,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 000007E0 "A......." */ - 0x0F,0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x42, /* 000007E8 "....LNKB" */ - 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x0F, /* 000007F0 "........" */ - 0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x43,0x00, /* 000007F8 "...LNKC." */ - 0x08,0x50,0x52,0x54,0x41,0x12,0x41,0x2F, /* 00000800 ".PRTA.A/" */ - 0x3C,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x01, /* 00000808 "<......." */ - 0x00,0x00,0x00,0x0A,0x14,0x12,0x0B,0x04, /* 00000810 "........" */ - 0x0C,0xFF,0xFF,0x01,0x00,0x01,0x00,0x0A, /* 00000818 "........" */ - 0x15,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x01, /* 00000820 "........" */ - 0x00,0x0A,0x02,0x00,0x0A,0x16,0x12,0x0C, /* 00000828 "........" */ - 0x04,0x0C,0xFF,0xFF,0x01,0x00,0x0A,0x03, /* 00000830 "........" */ - 0x00,0x0A,0x17,0x12,0x0B,0x04,0x0C,0xFF, /* 00000838 "........" */ - 0xFF,0x02,0x00,0x00,0x00,0x0A,0x18,0x12, /* 00000840 "........" */ - 0x0B,0x04,0x0C,0xFF,0xFF,0x02,0x00,0x01, /* 00000848 "........" */ - 0x00,0x0A,0x19,0x12,0x0C,0x04,0x0C,0xFF, /* 00000850 "........" */ - 0xFF,0x02,0x00,0x0A,0x02,0x00,0x0A,0x1A, /* 00000858 "........" */ - 0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x02,0x00, /* 00000860 "........" */ - 0x0A,0x03,0x00,0x0A,0x1B,0x12,0x0B,0x04, /* 00000868 "........" */ - 0x0C,0xFF,0xFF,0x03,0x00,0x00,0x00,0x0A, /* 00000870 "........" */ - 0x1C,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x03, /* 00000878 "........" */ - 0x00,0x01,0x00,0x0A,0x1D,0x12,0x0C,0x04, /* 00000880 "........" */ - 0x0C,0xFF,0xFF,0x03,0x00,0x0A,0x02,0x00, /* 00000888 "........" */ - 0x0A,0x1E,0x12,0x0C,0x04,0x0C,0xFF,0xFF, /* 00000890 "........" */ - 0x03,0x00,0x0A,0x03,0x00,0x0A,0x1F,0x12, /* 00000898 "........" */ - 0x0B,0x04,0x0C,0xFF,0xFF,0x04,0x00,0x00, /* 000008A0 "........" */ - 0x00,0x0A,0x20,0x12,0x0B,0x04,0x0C,0xFF, /* 000008A8 ".. ....." */ - 0xFF,0x04,0x00,0x01,0x00,0x0A,0x21,0x12, /* 000008B0 "......!." */ - 0x0C,0x04,0x0C,0xFF,0xFF,0x04,0x00,0x0A, /* 000008B8 "........" */ - 0x02,0x00,0x0A,0x22,0x12,0x0C,0x04,0x0C, /* 000008C0 "..."...." */ - 0xFF,0xFF,0x04,0x00,0x0A,0x03,0x00,0x0A, /* 000008C8 "........" */ - 0x23,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x05, /* 000008D0 "#......." */ - 0x00,0x00,0x00,0x0A,0x24,0x12,0x0B,0x04, /* 000008D8 "....$..." */ - 0x0C,0xFF,0xFF,0x05,0x00,0x01,0x00,0x0A, /* 000008E0 "........" */ - 0x25,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x05, /* 000008E8 "%......." */ - 0x00,0x0A,0x02,0x00,0x0A,0x26,0x12,0x0C, /* 000008F0 ".....&.." */ - 0x04,0x0C,0xFF,0xFF,0x05,0x00,0x0A,0x03, /* 000008F8 "........" */ - 0x00,0x0A,0x27,0x12,0x0B,0x04,0x0C,0xFF, /* 00000900 "..'....." */ - 0xFF,0x06,0x00,0x00,0x00,0x0A,0x28,0x12, /* 00000908 "......(." */ - 0x0B,0x04,0x0C,0xFF,0xFF,0x06,0x00,0x01, /* 00000910 "........" */ - 0x00,0x0A,0x29,0x12,0x0C,0x04,0x0C,0xFF, /* 00000918 "..)....." */ - 0xFF,0x06,0x00,0x0A,0x02,0x00,0x0A,0x2A, /* 00000920 ".......*" */ - 0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x06,0x00, /* 00000928 "........" */ - 0x0A,0x03,0x00,0x0A,0x2B,0x12,0x0B,0x04, /* 00000930 "....+..." */ - 0x0C,0xFF,0xFF,0x07,0x00,0x00,0x00,0x0A, /* 00000938 "........" */ - 0x2C,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x07, /* 00000940 ",......." */ - 0x00,0x01,0x00,0x0A,0x2D,0x12,0x0C,0x04, /* 00000948 "....-..." */ - 0x0C,0xFF,0xFF,0x07,0x00,0x0A,0x02,0x00, /* 00000950 "........" */ - 0x0A,0x2E,0x12,0x0C,0x04,0x0C,0xFF,0xFF, /* 00000958 "........" */ - 0x07,0x00,0x0A,0x03,0x00,0x0A,0x2F,0x12, /* 00000960 "....../." */ - 0x0B,0x04,0x0C,0xFF,0xFF,0x08,0x00,0x00, /* 00000968 "........" */ - 0x00,0x0A,0x11,0x12,0x0B,0x04,0x0C,0xFF, /* 00000970 "........" */ - 0xFF,0x08,0x00,0x01,0x00,0x0A,0x12,0x12, /* 00000978 "........" */ - 0x0C,0x04,0x0C,0xFF,0xFF,0x08,0x00,0x0A, /* 00000980 "........" */ - 0x02,0x00,0x0A,0x13,0x12,0x0C,0x04,0x0C, /* 00000988 "........" */ - 0xFF,0xFF,0x08,0x00,0x0A,0x03,0x00,0x0A, /* 00000990 "........" */ - 0x14,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x09, /* 00000998 "........" */ - 0x00,0x00,0x00,0x0A,0x15,0x12,0x0B,0x04, /* 000009A0 "........" */ - 0x0C,0xFF,0xFF,0x09,0x00,0x01,0x00,0x0A, /* 000009A8 "........" */ - 0x16,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x09, /* 000009B0 "........" */ - 0x00,0x0A,0x02,0x00,0x0A,0x17,0x12,0x0C, /* 000009B8 "........" */ - 0x04,0x0C,0xFF,0xFF,0x09,0x00,0x0A,0x03, /* 000009C0 "........" */ - 0x00,0x0A,0x18,0x12,0x0B,0x04,0x0C,0xFF, /* 000009C8 "........" */ - 0xFF,0x0A,0x00,0x00,0x00,0x0A,0x19,0x12, /* 000009D0 "........" */ - 0x0B,0x04,0x0C,0xFF,0xFF,0x0A,0x00,0x01, /* 000009D8 "........" */ - 0x00,0x0A,0x1A,0x12,0x0C,0x04,0x0C,0xFF, /* 000009E0 "........" */ - 0xFF,0x0A,0x00,0x0A,0x02,0x00,0x0A,0x1B, /* 000009E8 "........" */ - 0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x0A,0x00, /* 000009F0 "........" */ - 0x0A,0x03,0x00,0x0A,0x1C,0x12,0x0B,0x04, /* 000009F8 "........" */ - 0x0C,0xFF,0xFF,0x0B,0x00,0x00,0x00,0x0A, /* 00000A00 "........" */ - 0x1D,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x0B, /* 00000A08 "........" */ - 0x00,0x01,0x00,0x0A,0x1E,0x12,0x0C,0x04, /* 00000A10 "........" */ - 0x0C,0xFF,0xFF,0x0B,0x00,0x0A,0x02,0x00, /* 00000A18 "........" */ - 0x0A,0x1F,0x12,0x0C,0x04,0x0C,0xFF,0xFF, /* 00000A20 "........" */ - 0x0B,0x00,0x0A,0x03,0x00,0x0A,0x20,0x12, /* 00000A28 "...... ." */ - 0x0B,0x04,0x0C,0xFF,0xFF,0x0C,0x00,0x00, /* 00000A30 "........" */ - 0x00,0x0A,0x21,0x12,0x0B,0x04,0x0C,0xFF, /* 00000A38 "..!....." */ - 0xFF,0x0C,0x00,0x01,0x00,0x0A,0x22,0x12, /* 00000A40 "......"." */ - 0x0C,0x04,0x0C,0xFF,0xFF,0x0C,0x00,0x0A, /* 00000A48 "........" */ - 0x02,0x00,0x0A,0x23,0x12,0x0C,0x04,0x0C, /* 00000A50 "...#...." */ - 0xFF,0xFF,0x0C,0x00,0x0A,0x03,0x00,0x0A, /* 00000A58 "........" */ - 0x24,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x0D, /* 00000A60 "$......." */ - 0x00,0x00,0x00,0x0A,0x25,0x12,0x0B,0x04, /* 00000A68 "....%..." */ - 0x0C,0xFF,0xFF,0x0D,0x00,0x01,0x00,0x0A, /* 00000A70 "........" */ - 0x26,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x0D, /* 00000A78 "&......." */ - 0x00,0x0A,0x02,0x00,0x0A,0x27,0x12,0x0C, /* 00000A80 ".....'.." */ - 0x04,0x0C,0xFF,0xFF,0x0D,0x00,0x0A,0x03, /* 00000A88 "........" */ - 0x00,0x0A,0x28,0x12,0x0B,0x04,0x0C,0xFF, /* 00000A90 "..(....." */ - 0xFF,0x0E,0x00,0x00,0x00,0x0A,0x29,0x12, /* 00000A98 "......)." */ - 0x0B,0x04,0x0C,0xFF,0xFF,0x0E,0x00,0x01, /* 00000AA0 "........" */ - 0x00,0x0A,0x2A,0x12,0x0C,0x04,0x0C,0xFF, /* 00000AA8 "..*....." */ - 0xFF,0x0E,0x00,0x0A,0x02,0x00,0x0A,0x2B, /* 00000AB0 ".......+" */ - 0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x0E,0x00, /* 00000AB8 "........" */ - 0x0A,0x03,0x00,0x0A,0x2C,0x12,0x0B,0x04, /* 00000AC0 "....,..." */ - 0x0C,0xFF,0xFF,0x0F,0x00,0x00,0x00,0x0A, /* 00000AC8 "........" */ - 0x2D,0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x0F, /* 00000AD0 "-......." */ - 0x00,0x01,0x00,0x0A,0x2E,0x12,0x0C,0x04, /* 00000AD8 "........" */ - 0x0C,0xFF,0xFF,0x0F,0x00,0x0A,0x02,0x00, /* 00000AE0 "........" */ - 0x0A,0x2F,0x12,0x0C,0x04,0x0C,0xFF,0xFF, /* 00000AE8 "./......" */ - 0x0F,0x00,0x0A,0x03,0x00,0x0A,0x10,0x5B, /* 00000AF0 ".......[" */ - 0x82,0x46,0x37,0x49,0x53,0x41,0x5F,0x08, /* 00000AF8 ".F7ISA_." */ - 0x5F,0x41,0x44,0x52,0x0C,0x00,0x00,0x01, /* 00000B00 "_ADR...." */ - 0x00,0x5B,0x80,0x50,0x49,0x52,0x51,0x02, /* 00000B08 ".[.PIRQ." */ - 0x0A,0x60,0x0A,0x04,0x10,0x2E,0x5C,0x00, /* 00000B10 ".`....\." */ - 0x5B,0x81,0x29,0x5C,0x2F,0x04,0x5F,0x53, /* 00000B18 "[.)\/._S" */ - 0x42,0x5F,0x50,0x43,0x49,0x30,0x49,0x53, /* 00000B20 "B_PCI0IS" */ - 0x41,0x5F,0x50,0x49,0x52,0x51,0x01,0x50, /* 00000B28 "A_PIRQ.P" */ - 0x49,0x52,0x41,0x08,0x50,0x49,0x52,0x42, /* 00000B30 "IRA.PIRB" */ - 0x08,0x50,0x49,0x52,0x43,0x08,0x50,0x49, /* 00000B38 ".PIRC.PI" */ - 0x52,0x44,0x08,0x5B,0x82,0x46,0x0B,0x53, /* 00000B40 "RD.[.F.S" */ - 0x59,0x53,0x52,0x08,0x5F,0x48,0x49,0x44, /* 00000B48 "YSR._HID" */ - 0x0C,0x41,0xD0,0x0C,0x02,0x08,0x5F,0x55, /* 00000B50 ".A...._U" */ - 0x49,0x44,0x01,0x08,0x43,0x52,0x53,0x5F, /* 00000B58 "ID..CRS_" */ - 0x11,0x4E,0x08,0x0A,0x8A,0x47,0x01,0x10, /* 00000B60 ".N...G.." */ - 0x00,0x10,0x00,0x00,0x10,0x47,0x01,0x22, /* 00000B68 ".....G."" */ - 0x00,0x22,0x00,0x00,0x0C,0x47,0x01,0x30, /* 00000B70 "."...G.0" */ - 0x00,0x30,0x00,0x00,0x10,0x47,0x01,0x44, /* 00000B78 ".0...G.D" */ - 0x00,0x44,0x00,0x00,0x1C,0x47,0x01,0x62, /* 00000B80 ".D...G.b" */ - 0x00,0x62,0x00,0x00,0x02,0x47,0x01,0x65, /* 00000B88 ".b...G.e" */ - 0x00,0x65,0x00,0x00,0x0B,0x47,0x01,0x72, /* 00000B90 ".e...G.r" */ - 0x00,0x72,0x00,0x00,0x0E,0x47,0x01,0x80, /* 00000B98 ".r...G.." */ - 0x00,0x80,0x00,0x00,0x01,0x47,0x01,0x84, /* 00000BA0 ".....G.." */ - 0x00,0x84,0x00,0x00,0x03,0x47,0x01,0x88, /* 00000BA8 ".....G.." */ - 0x00,0x88,0x00,0x00,0x01,0x47,0x01,0x8C, /* 00000BB0 ".....G.." */ - 0x00,0x8C,0x00,0x00,0x03,0x47,0x01,0x90, /* 00000BB8 ".....G.." */ - 0x00,0x90,0x00,0x00,0x10,0x47,0x01,0xA2, /* 00000BC0 ".....G.." */ - 0x00,0xA2,0x00,0x00,0x1C,0x47,0x01,0xE0, /* 00000BC8 ".....G.." */ - 0x00,0xE0,0x00,0x00,0x10,0x47,0x01,0xA0, /* 00000BD0 ".....G.." */ - 0x08,0xA0,0x08,0x00,0x04,0x47,0x01,0xC0, /* 00000BD8 ".....G.." */ - 0x0C,0xC0,0x0C,0x00,0x10,0x47,0x01,0xD0, /* 00000BE0 ".....G.." */ - 0x04,0xD0,0x04,0x00,0x02,0x79,0x00,0x14, /* 00000BE8 ".....y.." */ - 0x0B,0x5F,0x43,0x52,0x53,0x00,0xA4,0x43, /* 00000BF0 "._CRS..C" */ - 0x52,0x53,0x5F,0x5B,0x82,0x2B,0x50,0x49, /* 00000BF8 "RS_[.+PI" */ - 0x43,0x5F,0x08,0x5F,0x48,0x49,0x44,0x0B, /* 00000C00 "C_._HID." */ - 0x41,0xD0,0x08,0x5F,0x43,0x52,0x53,0x11, /* 00000C08 "A.._CRS." */ - 0x18,0x0A,0x15,0x47,0x01,0x20,0x00,0x20, /* 00000C10 "...G. . " */ - 0x00,0x01,0x02,0x47,0x01,0xA0,0x00,0xA0, /* 00000C18 "...G...." */ - 0x00,0x01,0x02,0x22,0x04,0x00,0x79,0x00, /* 00000C20 "..."..y." */ - 0x5B,0x82,0x47,0x05,0x44,0x4D,0x41,0x30, /* 00000C28 "[.G.DMA0" */ - 0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 00000C30 "._HID.A." */ - 0x02,0x00,0x08,0x5F,0x43,0x52,0x53,0x11, /* 00000C38 "..._CRS." */ - 0x41,0x04,0x0A,0x3D,0x2A,0x10,0x04,0x47, /* 00000C40 "A..=*..G" */ - 0x01,0x00,0x00,0x00,0x00,0x00,0x10,0x47, /* 00000C48 ".......G" */ - 0x01,0x81,0x00,0x81,0x00,0x00,0x03,0x47, /* 00000C50 ".......G" */ - 0x01,0x87,0x00,0x87,0x00,0x00,0x01,0x47, /* 00000C58 ".......G" */ - 0x01,0x89,0x00,0x89,0x00,0x00,0x03,0x47, /* 00000C60 ".......G" */ - 0x01,0x8F,0x00,0x8F,0x00,0x00,0x01,0x47, /* 00000C68 ".......G" */ - 0x01,0xC0,0x00,0xC0,0x00,0x00,0x20,0x47, /* 00000C70 "...... G" */ - 0x01,0x80,0x04,0x80,0x04,0x00,0x10,0x79, /* 00000C78 ".......y" */ - 0x00,0x5B,0x82,0x25,0x54,0x4D,0x52,0x5F, /* 00000C80 ".[.%TMR_" */ - 0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 00000C88 "._HID.A." */ - 0x01,0x00,0x08,0x5F,0x43,0x52,0x53,0x11, /* 00000C90 "..._CRS." */ - 0x10,0x0A,0x0D,0x47,0x01,0x40,0x00,0x40, /* 00000C98 "...G.@.@" */ - 0x00,0x00,0x04,0x22,0x01,0x00,0x79,0x00, /* 00000CA0 "..."..y." */ - 0x5B,0x82,0x25,0x52,0x54,0x43,0x5F,0x08, /* 00000CA8 "[.%RTC_." */ - 0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x0B, /* 00000CB0 "_HID.A.." */ - 0x00,0x08,0x5F,0x43,0x52,0x53,0x11,0x10, /* 00000CB8 ".._CRS.." */ - 0x0A,0x0D,0x47,0x01,0x70,0x00,0x70,0x00, /* 00000CC0 "..G.p.p." */ - 0x00,0x02,0x22,0x00,0x01,0x79,0x00,0x5B, /* 00000CC8 ".."..y.[" */ - 0x82,0x22,0x53,0x50,0x4B,0x52,0x08,0x5F, /* 00000CD0 "."SPKR._" */ - 0x48,0x49,0x44,0x0C,0x41,0xD0,0x08,0x00, /* 00000CD8 "HID.A..." */ - 0x08,0x5F,0x43,0x52,0x53,0x11,0x0D,0x0A, /* 00000CE0 "._CRS..." */ - 0x0A,0x47,0x01,0x61,0x00,0x61,0x00,0x00, /* 00000CE8 ".G.a.a.." */ - 0x01,0x79,0x00,0x5B,0x82,0x31,0x50,0x53, /* 00000CF0 ".y.[.1PS" */ - 0x32,0x4D,0x08,0x5F,0x48,0x49,0x44,0x0C, /* 00000CF8 "2M._HID." */ - 0x41,0xD0,0x0F,0x13,0x08,0x5F,0x43,0x49, /* 00000D00 "A...._CI" */ - 0x44,0x0C,0x41,0xD0,0x0F,0x13,0x14,0x09, /* 00000D08 "D.A....." */ - 0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A,0x0F, /* 00000D10 "_STA...." */ - 0x08,0x5F,0x43,0x52,0x53,0x11,0x08,0x0A, /* 00000D18 "._CRS..." */ - 0x05,0x22,0x00,0x10,0x79,0x00,0x5B,0x82, /* 00000D20 "."..y.[." */ - 0x42,0x04,0x50,0x53,0x32,0x4B,0x08,0x5F, /* 00000D28 "B.PS2K._" */ - 0x48,0x49,0x44,0x0C,0x41,0xD0,0x03,0x03, /* 00000D30 "HID.A..." */ - 0x08,0x5F,0x43,0x49,0x44,0x0C,0x41,0xD0, /* 00000D38 "._CID.A." */ - 0x03,0x0B,0x14,0x09,0x5F,0x53,0x54,0x41, /* 00000D40 "...._STA" */ - 0x00,0xA4,0x0A,0x0F,0x08,0x5F,0x43,0x52, /* 00000D48 "....._CR" */ - 0x53,0x11,0x18,0x0A,0x15,0x47,0x01,0x60, /* 00000D50 "S....G.`" */ - 0x00,0x60,0x00,0x00,0x01,0x47,0x01,0x64, /* 00000D58 ".`...G.d" */ - 0x00,0x64,0x00,0x00,0x01,0x22,0x02,0x00, /* 00000D60 ".d...".." */ - 0x79,0x00,0x5B,0x82,0x3A,0x46,0x44,0x43, /* 00000D68 "y.[.:FDC" */ - 0x30,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41, /* 00000D70 "0._HID.A" */ - 0xD0,0x07,0x00,0x14,0x09,0x5F,0x53,0x54, /* 00000D78 "....._ST" */ - 0x41,0x00,0xA4,0x0A,0x0F,0x08,0x5F,0x43, /* 00000D80 "A....._C" */ - 0x52,0x53,0x11,0x1B,0x0A,0x18,0x47,0x01, /* 00000D88 "RS....G." */ - 0xF0,0x03,0xF0,0x03,0x01,0x06,0x47,0x01, /* 00000D90 "......G." */ - 0xF7,0x03,0xF7,0x03,0x01,0x01,0x22,0x40, /* 00000D98 "......"@" */ - 0x00,0x2A,0x04,0x00,0x79,0x00,0x5B,0x82, /* 00000DA0 ".*..y.[." */ - 0x46,0x04,0x55,0x41,0x52,0x31,0x08,0x5F, /* 00000DA8 "F.UAR1._" */ - 0x48,0x49,0x44,0x0C,0x41,0xD0,0x05,0x01, /* 00000DB0 "HID.A..." */ - 0x08,0x5F,0x55,0x49,0x44,0x01,0x14,0x19, /* 00000DB8 "._UID..." */ - 0x5F,0x53,0x54,0x41,0x00,0xA0,0x0D,0x93, /* 00000DC0 "_STA...." */ - 0x5E,0x5E,0x5E,0x5E,0x55,0x41,0x52,0x31, /* 00000DC8 "^^^^UAR1" */ - 0x00,0xA4,0x00,0xA1,0x04,0xA4,0x0A,0x0F, /* 00000DD0 "........" */ - 0x08,0x5F,0x43,0x52,0x53,0x11,0x10,0x0A, /* 00000DD8 "._CRS..." */ - 0x0D,0x47,0x01,0xF8,0x03,0xF8,0x03,0x08, /* 00000DE0 ".G......" */ - 0x08,0x22,0x10,0x00,0x79,0x00,0x5B,0x82, /* 00000DE8 "."..y.[." */ - 0x47,0x04,0x55,0x41,0x52,0x32,0x08,0x5F, /* 00000DF0 "G.UAR2._" */ - 0x48,0x49,0x44,0x0C,0x41,0xD0,0x05,0x01, /* 00000DF8 "HID.A..." */ - 0x08,0x5F,0x55,0x49,0x44,0x0A,0x02,0x14, /* 00000E00 "._UID..." */ - 0x19,0x5F,0x53,0x54,0x41,0x00,0xA0,0x0D, /* 00000E08 "._STA..." */ - 0x93,0x5E,0x5E,0x5E,0x5E,0x55,0x41,0x52, /* 00000E10 ".^^^^UAR" */ - 0x32,0x00,0xA4,0x00,0xA1,0x04,0xA4,0x0A, /* 00000E18 "2......." */ - 0x0F,0x08,0x5F,0x43,0x52,0x53,0x11,0x10, /* 00000E20 ".._CRS.." */ - 0x0A,0x0D,0x47,0x01,0xF8,0x02,0xF8,0x02, /* 00000E28 "..G....." */ - 0x08,0x08,0x22,0x08,0x00,0x79,0x00,0x5B, /* 00000E30 ".."..y.[" */ - 0x82,0x36,0x4C,0x54,0x50,0x31,0x08,0x5F, /* 00000E38 ".6LTP1._" */ - 0x48,0x49,0x44,0x0C,0x41,0xD0,0x04,0x00, /* 00000E40 "HID.A..." */ - 0x08,0x5F,0x55,0x49,0x44,0x0A,0x02,0x14, /* 00000E48 "._UID..." */ - 0x09,0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A, /* 00000E50 "._STA..." */ - 0x0F,0x08,0x5F,0x43,0x52,0x53,0x11,0x10, /* 00000E58 ".._CRS.." */ - 0x0A,0x0D,0x47,0x01,0x78,0x03,0x78,0x03, /* 00000E60 "..G.x.x." */ - 0x08,0x08,0x22,0x80,0x00,0x79,0x00, + 0x00,0x00,0x00,0x00,0x00,0x0A,0x00,0x00, /* 000000F0 "........" */ + 0x00,0x00,0x00,0x79,0x00,0x5B,0x82,0x4F, /* 000000F8 "...y.[.O" */ + 0xD8,0x50,0x43,0x49,0x30,0x08,0x5F,0x48, /* 00000100 ".PCI0._H" */ + 0x49,0x44,0x0C,0x41,0xD0,0x0A,0x03,0x08, /* 00000108 "ID.A...." */ + 0x5F,0x55,0x49,0x44,0x00,0x08,0x5F,0x41, /* 00000110 "_UID.._A" */ + 0x44,0x52,0x00,0x08,0x5F,0x42,0x42,0x4E, /* 00000118 "DR.._BBN" */ + 0x00,0x14,0x4E,0x0C,0x5F,0x43,0x52,0x53, /* 00000120 "..N._CRS" */ + 0x00,0x08,0x50,0x52,0x54,0x30,0x11,0x42, /* 00000128 "..PRT0.B" */ + 0x07,0x0A,0x6E,0x88,0x0D,0x00,0x02,0x0E, /* 00000130 "..n....." */ + 0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00, /* 00000138 "........" */ + 0x00,0x00,0x01,0x47,0x01,0xF8,0x0C,0xF8, /* 00000140 "...G...." */ + 0x0C,0x01,0x08,0x88,0x0D,0x00,0x01,0x0C, /* 00000148 "........" */ + 0x03,0x00,0x00,0x00,0x00,0xF7,0x0C,0x00, /* 00000150 "........" */ + 0x00,0xF8,0x0C,0x88,0x0D,0x00,0x01,0x0C, /* 00000158 "........" */ + 0x03,0x00,0x00,0x00,0x0D,0xFF,0xFF,0x00, /* 00000160 "........" */ + 0x00,0x00,0xF3,0x87,0x17,0x00,0x00,0x0C, /* 00000168 "........" */ + 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x0A, /* 00000170 "........" */ + 0x00,0xFF,0xFF,0x0B,0x00,0x00,0x00,0x00, /* 00000178 "........" */ + 0x00,0x00,0x00,0x02,0x00,0x87,0x17,0x00, /* 00000180 "........" */ + 0x00,0x0C,0x03,0x00,0x00,0x00,0x00,0x00, /* 00000188 "........" */ + 0x00,0x00,0xF0,0xFF,0xFF,0xFF,0xF4,0x00, /* 00000190 "........" */ + 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x79, /* 00000198 ".......y" */ + 0x00,0x8A,0x50,0x52,0x54,0x30,0x0A,0x5C, /* 000001A0 "..PRT0.\" */ + 0x4D,0x4D,0x49,0x4E,0x8A,0x50,0x52,0x54, /* 000001A8 "MMIN.PRT" */ + 0x30,0x0A,0x60,0x4D,0x4D,0x41,0x58,0x8A, /* 000001B0 "0.`MMAX." */ + 0x50,0x52,0x54,0x30,0x0A,0x68,0x4D,0x4C, /* 000001B8 "PRT0.hML" */ + 0x45,0x4E,0x70,0x50,0x4D,0x49,0x4E,0x4D, /* 000001C0 "ENpPMINM" */ + 0x4D,0x49,0x4E,0x70,0x50,0x4C,0x45,0x4E, /* 000001C8 "MINpPLEN" */ + 0x4D,0x4C,0x45,0x4E,0x72,0x4D,0x4D,0x49, /* 000001D0 "MLENrMMI" */ + 0x4E,0x4D,0x4C,0x45,0x4E,0x4D,0x4D,0x41, /* 000001D8 "NMLENMMA" */ + 0x58,0x74,0x4D,0x4D,0x41,0x58,0x01,0x4D, /* 000001E0 "XtMMAX.M" */ + 0x4D,0x41,0x58,0xA4,0x50,0x52,0x54,0x30, /* 000001E8 "MAX.PRT0" */ + 0x08,0x42,0x55,0x46,0x41,0x11,0x09,0x0A, /* 000001F0 ".BUFA..." */ + 0x06,0x23,0x20,0x0C,0x18,0x79,0x00,0x08, /* 000001F8 ".# ..y.." */ + 0x42,0x55,0x46,0x42,0x11,0x09,0x0A,0x06, /* 00000200 "BUFB...." */ + 0x23,0x00,0x00,0x18,0x79,0x00,0x8B,0x42, /* 00000208 "#...y..B" */ + 0x55,0x46,0x42,0x01,0x49,0x52,0x51,0x56, /* 00000210 "UFB.IRQV" */ + 0x5B,0x82,0x48,0x08,0x4C,0x4E,0x4B,0x41, /* 00000218 "[.H.LNKA" */ + 0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 00000220 "._HID.A." */ + 0x0C,0x0F,0x08,0x5F,0x55,0x49,0x44,0x01, /* 00000228 "..._UID." */ + 0x14,0x1C,0x5F,0x53,0x54,0x41,0x00,0x7B, /* 00000230 ".._STA.{" */ + 0x50,0x49,0x52,0x41,0x0A,0x80,0x60,0xA0, /* 00000238 "PIRA..`." */ + 0x08,0x93,0x60,0x0A,0x80,0xA4,0x0A,0x09, /* 00000240 "..`....." */ + 0xA1,0x04,0xA4,0x0A,0x0B,0x14,0x0B,0x5F, /* 00000248 "......._" */ + 0x50,0x52,0x53,0x00,0xA4,0x42,0x55,0x46, /* 00000250 "PRS..BUF" */ + 0x41,0x14,0x11,0x5F,0x44,0x49,0x53,0x00, /* 00000258 "A.._DIS." */ + 0x7D,0x50,0x49,0x52,0x41,0x0A,0x80,0x50, /* 00000260 "}PIRA..P" */ + 0x49,0x52,0x41,0x14,0x1A,0x5F,0x43,0x52, /* 00000268 "IRA.._CR" */ + 0x53,0x00,0x7B,0x50,0x49,0x52,0x41,0x0A, /* 00000270 "S.{PIRA." */ + 0x0F,0x60,0x79,0x01,0x60,0x49,0x52,0x51, /* 00000278 ".`y.`IRQ" */ + 0x56,0xA4,0x42,0x55,0x46,0x42,0x14,0x1B, /* 00000280 "V.BUFB.." */ + 0x5F,0x53,0x52,0x53,0x01,0x8B,0x68,0x01, /* 00000288 "_SRS..h." */ + 0x49,0x52,0x51,0x31,0x82,0x49,0x52,0x51, /* 00000290 "IRQ1.IRQ" */ + 0x31,0x60,0x76,0x60,0x70,0x60,0x50,0x49, /* 00000298 "1`v`p`PI" */ + 0x52,0x41,0x5B,0x82,0x49,0x08,0x4C,0x4E, /* 000002A0 "RA[.I.LN" */ + 0x4B,0x42,0x08,0x5F,0x48,0x49,0x44,0x0C, /* 000002A8 "KB._HID." */ + 0x41,0xD0,0x0C,0x0F,0x08,0x5F,0x55,0x49, /* 000002B0 "A...._UI" */ + 0x44,0x0A,0x02,0x14,0x1C,0x5F,0x53,0x54, /* 000002B8 "D...._ST" */ + 0x41,0x00,0x7B,0x50,0x49,0x52,0x42,0x0A, /* 000002C0 "A.{PIRB." */ + 0x80,0x60,0xA0,0x08,0x93,0x60,0x0A,0x80, /* 000002C8 ".`...`.." */ + 0xA4,0x0A,0x09,0xA1,0x04,0xA4,0x0A,0x0B, /* 000002D0 "........" */ + 0x14,0x0B,0x5F,0x50,0x52,0x53,0x00,0xA4, /* 000002D8 ".._PRS.." */ + 0x42,0x55,0x46,0x41,0x14,0x11,0x5F,0x44, /* 000002E0 "BUFA.._D" */ + 0x49,0x53,0x00,0x7D,0x50,0x49,0x52,0x42, /* 000002E8 "IS.}PIRB" */ + 0x0A,0x80,0x50,0x49,0x52,0x42,0x14,0x1A, /* 000002F0 "..PIRB.." */ + 0x5F,0x43,0x52,0x53,0x00,0x7B,0x50,0x49, /* 000002F8 "_CRS.{PI" */ + 0x52,0x42,0x0A,0x0F,0x60,0x79,0x01,0x60, /* 00000300 "RB..`y.`" */ + 0x49,0x52,0x51,0x56,0xA4,0x42,0x55,0x46, /* 00000308 "IRQV.BUF" */ + 0x42,0x14,0x1B,0x5F,0x53,0x52,0x53,0x01, /* 00000310 "B.._SRS." */ + 0x8B,0x68,0x01,0x49,0x52,0x51,0x31,0x82, /* 00000318 ".h.IRQ1." */ + 0x49,0x52,0x51,0x31,0x60,0x76,0x60,0x70, /* 00000320 "IRQ1`v`p" */ + 0x60,0x50,0x49,0x52,0x42,0x5B,0x82,0x49, /* 00000328 "`PIRB[.I" */ + 0x08,0x4C,0x4E,0x4B,0x43,0x08,0x5F,0x48, /* 00000330 ".LNKC._H" */ + 0x49,0x44,0x0C,0x41,0xD0,0x0C,0x0F,0x08, /* 00000338 "ID.A...." */ + 0x5F,0x55,0x49,0x44,0x0A,0x03,0x14,0x1C, /* 00000340 "_UID...." */ + 0x5F,0x53,0x54,0x41,0x00,0x7B,0x50,0x49, /* 00000348 "_STA.{PI" */ + 0x52,0x43,0x0A,0x80,0x60,0xA0,0x08,0x93, /* 00000350 "RC..`..." */ + 0x60,0x0A,0x80,0xA4,0x0A,0x09,0xA1,0x04, /* 00000358 "`......." */ + 0xA4,0x0A,0x0B,0x14,0x0B,0x5F,0x50,0x52, /* 00000360 "....._PR" */ + 0x53,0x00,0xA4,0x42,0x55,0x46,0x41,0x14, /* 00000368 "S..BUFA." */ + 0x11,0x5F,0x44,0x49,0x53,0x00,0x7D,0x50, /* 00000370 "._DIS.}P" */ + 0x49,0x52,0x43,0x0A,0x80,0x50,0x49,0x52, /* 00000378 "IRC..PIR" */ + 0x43,0x14,0x1A,0x5F,0x43,0x52,0x53,0x00, /* 00000380 "C.._CRS." */ + 0x7B,0x50,0x49,0x52,0x43,0x0A,0x0F,0x60, /* 00000388 "{PIRC..`" */ + 0x79,0x01,0x60,0x49,0x52,0x51,0x56,0xA4, /* 00000390 "y.`IRQV." */ + 0x42,0x55,0x46,0x42,0x14,0x1B,0x5F,0x53, /* 00000398 "BUFB.._S" */ + 0x52,0x53,0x01,0x8B,0x68,0x01,0x49,0x52, /* 000003A0 "RS..h.IR" */ + 0x51,0x31,0x82,0x49,0x52,0x51,0x31,0x60, /* 000003A8 "Q1.IRQ1`" */ + 0x76,0x60,0x70,0x60,0x50,0x49,0x52,0x43, /* 000003B0 "v`p`PIRC" */ + 0x5B,0x82,0x49,0x08,0x4C,0x4E,0x4B,0x44, /* 000003B8 "[.I.LNKD" */ + 0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 000003C0 "._HID.A." */ + 0x0C,0x0F,0x08,0x5F,0x55,0x49,0x44,0x0A, /* 000003C8 "..._UID." */ + 0x04,0x14,0x1C,0x5F,0x53,0x54,0x41,0x00, /* 000003D0 "..._STA." */ + 0x7B,0x50,0x49,0x52,0x44,0x0A,0x80,0x60, /* 000003D8 "{PIRD..`" */ + 0xA0,0x08,0x93,0x60,0x0A,0x80,0xA4,0x0A, /* 000003E0 "...`...." */ + 0x09,0xA1,0x04,0xA4,0x0A,0x0B,0x14,0x0B, /* 000003E8 "........" */ + 0x5F,0x50,0x52,0x53,0x00,0xA4,0x42,0x55, /* 000003F0 "_PRS..BU" */ + 0x46,0x41,0x14,0x11,0x5F,0x44,0x49,0x53, /* 000003F8 "FA.._DIS" */ + 0x00,0x7D,0x50,0x49,0x52,0x44,0x0A,0x80, /* 00000400 ".}PIRD.." */ + 0x50,0x49,0x52,0x44,0x14,0x1A,0x5F,0x43, /* 00000408 "PIRD.._C" */ + 0x52,0x53,0x00,0x7B,0x50,0x49,0x52,0x44, /* 00000410 "RS.{PIRD" */ + 0x0A,0x0F,0x60,0x79,0x01,0x60,0x49,0x52, /* 00000418 "..`y.`IR" */ + 0x51,0x56,0xA4,0x42,0x55,0x46,0x42,0x14, /* 00000420 "QV.BUFB." */ + 0x1B,0x5F,0x53,0x52,0x53,0x01,0x8B,0x68, /* 00000428 "._SRS..h" */ + 0x01,0x49,0x52,0x51,0x31,0x82,0x49,0x52, /* 00000430 ".IRQ1.IR" */ + 0x51,0x31,0x60,0x76,0x60,0x70,0x60,0x50, /* 00000438 "Q1`v`p`P" */ + 0x49,0x52,0x44,0x5B,0x82,0x44,0x05,0x48, /* 00000440 "IRD[.D.H" */ + 0x50,0x45,0x54,0x08,0x5F,0x48,0x49,0x44, /* 00000448 "PET._HID" */ + 0x0C,0x41,0xD0,0x01,0x03,0x08,0x5F,0x55, /* 00000450 ".A...._U" */ + 0x49,0x44,0x00,0x14,0x18,0x5F,0x53,0x54, /* 00000458 "ID..._ST" */ + 0x41,0x00,0xA0,0x0C,0x93,0x5E,0x5E,0x5E, /* 00000460 "A....^^^" */ + 0x48,0x50,0x45,0x54,0x00,0xA4,0x00,0xA1, /* 00000468 "HPET...." */ + 0x04,0xA4,0x0A,0x0F,0x08,0x5F,0x43,0x52, /* 00000470 "....._CR" */ + 0x53,0x11,0x1F,0x0A,0x1C,0x87,0x17,0x00, /* 00000478 "S......." */ + 0x00,0x0D,0x01,0x00,0x00,0x00,0x00,0x00, /* 00000480 "........" */ + 0x00,0xD0,0xFE,0xFF,0x03,0xD0,0xFE,0x00, /* 00000488 "........" */ + 0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x79, /* 00000490 ".......y" */ + 0x00,0x14,0x16,0x5F,0x50,0x52,0x54,0x00, /* 00000498 "..._PRT." */ + 0xA0,0x0A,0x50,0x49,0x43,0x44,0xA4,0x50, /* 000004A0 "..PICD.P" */ + 0x52,0x54,0x41,0xA4,0x50,0x52,0x54,0x50, /* 000004A8 "RTA.PRTP" */ + 0x08,0x50,0x52,0x54,0x50,0x12,0x49,0x36, /* 000004B0 ".PRTP.I6" */ + 0x3C,0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x01, /* 000004B8 "<......." */ + 0x00,0x00,0x4C,0x4E,0x4B,0x42,0x00,0x12, /* 000004C0 "..LNKB.." */ + 0x0D,0x04,0x0C,0xFF,0xFF,0x01,0x00,0x01, /* 000004C8 "........" */ + 0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E,0x04, /* 000004D0 "LNKC...." */ + 0x0C,0xFF,0xFF,0x01,0x00,0x0A,0x02,0x4C, /* 000004D8 ".......L" */ + 0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04,0x0C, /* 000004E0 "NKD....." */ + 0xFF,0xFF,0x01,0x00,0x0A,0x03,0x4C,0x4E, /* 000004E8 "......LN" */ + 0x4B,0x41,0x00,0x12,0x0D,0x04,0x0C,0xFF, /* 000004F0 "KA......" */ + 0xFF,0x02,0x00,0x00,0x4C,0x4E,0x4B,0x43, /* 000004F8 "....LNKC" */ + 0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x02, /* 00000500 "........" */ + 0x00,0x01,0x4C,0x4E,0x4B,0x44,0x00,0x12, /* 00000508 "..LNKD.." */ + 0x0E,0x04,0x0C,0xFF,0xFF,0x02,0x00,0x0A, /* 00000510 "........" */ + 0x02,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0E, /* 00000518 ".LNKA..." */ + 0x04,0x0C,0xFF,0xFF,0x02,0x00,0x0A,0x03, /* 00000520 "........" */ + 0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0D,0x04, /* 00000528 "LNKB...." */ + 0x0C,0xFF,0xFF,0x03,0x00,0x00,0x4C,0x4E, /* 00000530 "......LN" */ + 0x4B,0x44,0x00,0x12,0x0D,0x04,0x0C,0xFF, /* 00000538 "KD......" */ + 0xFF,0x03,0x00,0x01,0x4C,0x4E,0x4B,0x41, /* 00000540 "....LNKA" */ + 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x03, /* 00000548 "........" */ + 0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x42,0x00, /* 00000550 "...LNKB." */ + 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x03,0x00, /* 00000558 "........" */ + 0x0A,0x03,0x4C,0x4E,0x4B,0x43,0x00,0x12, /* 00000560 "..LNKC.." */ + 0x0D,0x04,0x0C,0xFF,0xFF,0x04,0x00,0x00, /* 00000568 "........" */ + 0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0D,0x04, /* 00000570 "LNKA...." */ + 0x0C,0xFF,0xFF,0x04,0x00,0x01,0x4C,0x4E, /* 00000578 "......LN" */ + 0x4B,0x42,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 00000580 "KB......" */ + 0xFF,0x04,0x00,0x0A,0x02,0x4C,0x4E,0x4B, /* 00000588 ".....LNK" */ + 0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 00000590 "C......." */ + 0x04,0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x44, /* 00000598 "....LNKD" */ + 0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x05, /* 000005A0 "........" */ + 0x00,0x00,0x4C,0x4E,0x4B,0x42,0x00,0x12, /* 000005A8 "..LNKB.." */ + 0x0D,0x04,0x0C,0xFF,0xFF,0x05,0x00,0x01, /* 000005B0 "........" */ + 0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E,0x04, /* 000005B8 "LNKC...." */ + 0x0C,0xFF,0xFF,0x05,0x00,0x0A,0x02,0x4C, /* 000005C0 ".......L" */ + 0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04,0x0C, /* 000005C8 "NKD....." */ + 0xFF,0xFF,0x05,0x00,0x0A,0x03,0x4C,0x4E, /* 000005D0 "......LN" */ + 0x4B,0x41,0x00,0x12,0x0D,0x04,0x0C,0xFF, /* 000005D8 "KA......" */ + 0xFF,0x06,0x00,0x00,0x4C,0x4E,0x4B,0x43, /* 000005E0 "....LNKC" */ + 0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x06, /* 000005E8 "........" */ + 0x00,0x01,0x4C,0x4E,0x4B,0x44,0x00,0x12, /* 000005F0 "..LNKD.." */ + 0x0E,0x04,0x0C,0xFF,0xFF,0x06,0x00,0x0A, /* 000005F8 "........" */ + 0x02,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0E, /* 00000600 ".LNKA..." */ + 0x04,0x0C,0xFF,0xFF,0x06,0x00,0x0A,0x03, /* 00000608 "........" */ + 0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0D,0x04, /* 00000610 "LNKB...." */ + 0x0C,0xFF,0xFF,0x07,0x00,0x00,0x4C,0x4E, /* 00000618 "......LN" */ + 0x4B,0x44,0x00,0x12,0x0D,0x04,0x0C,0xFF, /* 00000620 "KD......" */ + 0xFF,0x07,0x00,0x01,0x4C,0x4E,0x4B,0x41, /* 00000628 "....LNKA" */ + 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x07, /* 00000630 "........" */ + 0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x42,0x00, /* 00000638 "...LNKB." */ + 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x07,0x00, /* 00000640 "........" */ + 0x0A,0x03,0x4C,0x4E,0x4B,0x43,0x00,0x12, /* 00000648 "..LNKC.." */ + 0x0D,0x04,0x0C,0xFF,0xFF,0x08,0x00,0x00, /* 00000650 "........" */ + 0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0D,0x04, /* 00000658 "LNKA...." */ + 0x0C,0xFF,0xFF,0x08,0x00,0x01,0x4C,0x4E, /* 00000660 "......LN" */ + 0x4B,0x42,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 00000668 "KB......" */ + 0xFF,0x08,0x00,0x0A,0x02,0x4C,0x4E,0x4B, /* 00000670 ".....LNK" */ + 0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 00000678 "C......." */ + 0x08,0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x44, /* 00000680 "....LNKD" */ + 0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x09, /* 00000688 "........" */ + 0x00,0x00,0x4C,0x4E,0x4B,0x42,0x00,0x12, /* 00000690 "..LNKB.." */ + 0x0D,0x04,0x0C,0xFF,0xFF,0x09,0x00,0x01, /* 00000698 "........" */ + 0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E,0x04, /* 000006A0 "LNKC...." */ + 0x0C,0xFF,0xFF,0x09,0x00,0x0A,0x02,0x4C, /* 000006A8 ".......L" */ + 0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04,0x0C, /* 000006B0 "NKD....." */ + 0xFF,0xFF,0x09,0x00,0x0A,0x03,0x4C,0x4E, /* 000006B8 "......LN" */ + 0x4B,0x41,0x00,0x12,0x0D,0x04,0x0C,0xFF, /* 000006C0 "KA......" */ + 0xFF,0x0A,0x00,0x00,0x4C,0x4E,0x4B,0x43, /* 000006C8 "....LNKC" */ + 0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x0A, /* 000006D0 "........" */ + 0x00,0x01,0x4C,0x4E,0x4B,0x44,0x00,0x12, /* 000006D8 "..LNKD.." */ + 0x0E,0x04,0x0C,0xFF,0xFF,0x0A,0x00,0x0A, /* 000006E0 "........" */ + 0x02,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0E, /* 000006E8 ".LNKA..." */ + 0x04,0x0C,0xFF,0xFF,0x0A,0x00,0x0A,0x03, /* 000006F0 "........" */ + 0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0D,0x04, /* 000006F8 "LNKB...." */ + 0x0C,0xFF,0xFF,0x0B,0x00,0x00,0x4C,0x4E, /* 00000700 "......LN" */ + 0x4B,0x44,0x00,0x12,0x0D,0x04,0x0C,0xFF, /* 00000708 "KD......" */ + 0xFF,0x0B,0x00,0x01,0x4C,0x4E,0x4B,0x41, /* 00000710 "....LNKA" */ + 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x0B, /* 00000718 "........" */ + 0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x42,0x00, /* 00000720 "...LNKB." */ + 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x0B,0x00, /* 00000728 "........" */ + 0x0A,0x03,0x4C,0x4E,0x4B,0x43,0x00,0x12, /* 00000730 "..LNKC.." */ + 0x0D,0x04,0x0C,0xFF,0xFF,0x0C,0x00,0x00, /* 00000738 "........" */ + 0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0D,0x04, /* 00000740 "LNKA...." */ + 0x0C,0xFF,0xFF,0x0C,0x00,0x01,0x4C,0x4E, /* 00000748 "......LN" */ + 0x4B,0x42,0x00,0x12,0x0E,0x04,0x0C,0xFF, /* 00000750 "KB......" */ + 0xFF,0x0C,0x00,0x0A,0x02,0x4C,0x4E,0x4B, /* 00000758 ".....LNK" */ + 0x43,0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF, /* 00000760 "C......." */ + 0x0C,0x00,0x0A,0x03,0x4C,0x4E,0x4B,0x44, /* 00000768 "....LNKD" */ + 0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x0D, /* 00000770 "........" */ + 0x00,0x00,0x4C,0x4E,0x4B,0x42,0x00,0x12, /* 00000778 "..LNKB.." */ + 0x0D,0x04,0x0C,0xFF,0xFF,0x0D,0x00,0x01, /* 00000780 "........" */ + 0x4C,0x4E,0x4B,0x43,0x00,0x12,0x0E,0x04, /* 00000788 "LNKC...." */ + 0x0C,0xFF,0xFF,0x0D,0x00,0x0A,0x02,0x4C, /* 00000790 ".......L" */ + 0x4E,0x4B,0x44,0x00,0x12,0x0E,0x04,0x0C, /* 00000798 "NKD....." */ + 0xFF,0xFF,0x0D,0x00,0x0A,0x03,0x4C,0x4E, /* 000007A0 "......LN" */ + 0x4B,0x41,0x00,0x12,0x0D,0x04,0x0C,0xFF, /* 000007A8 "KA......" */ + 0xFF,0x0E,0x00,0x00,0x4C,0x4E,0x4B,0x43, /* 000007B0 "....LNKC" */ + 0x00,0x12,0x0D,0x04,0x0C,0xFF,0xFF,0x0E, /* 000007B8 "........" */ + 0x00,0x01,0x4C,0x4E,0x4B,0x44,0x00,0x12, /* 000007C0 "..LNKD.." */ + 0x0E,0x04,0x0C,0xFF,0xFF,0x0E,0x00,0x0A, /* 000007C8 "........" */ + 0x02,0x4C,0x4E,0x4B,0x41,0x00,0x12,0x0E, /* 000007D0 ".LNKA..." */ + 0x04,0x0C,0xFF,0xFF,0x0E,0x00,0x0A,0x03, /* 000007D8 "........" */ + 0x4C,0x4E,0x4B,0x42,0x00,0x12,0x0D,0x04, /* 000007E0 "LNKB...." */ + 0x0C,0xFF,0xFF,0x0F,0x00,0x00,0x4C,0x4E, /* 000007E8 "......LN" */ + 0x4B,0x44,0x00,0x12,0x0D,0x04,0x0C,0xFF, /* 000007F0 "KD......" */ + 0xFF,0x0F,0x00,0x01,0x4C,0x4E,0x4B,0x41, /* 000007F8 "....LNKA" */ + 0x00,0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x0F, /* 00000800 "........" */ + 0x00,0x0A,0x02,0x4C,0x4E,0x4B,0x42,0x00, /* 00000808 "...LNKB." */ + 0x12,0x0E,0x04,0x0C,0xFF,0xFF,0x0F,0x00, /* 00000810 "........" */ + 0x0A,0x03,0x4C,0x4E,0x4B,0x43,0x00,0x08, /* 00000818 "..LNKC.." */ + 0x50,0x52,0x54,0x41,0x12,0x41,0x2F,0x3C, /* 00000820 "PRTA.A/<" */ + 0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x01,0x00, /* 00000828 "........" */ + 0x00,0x00,0x0A,0x14,0x12,0x0B,0x04,0x0C, /* 00000830 "........" */ + 0xFF,0xFF,0x01,0x00,0x01,0x00,0x0A,0x15, /* 00000838 "........" */ + 0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x01,0x00, /* 00000840 "........" */ + 0x0A,0x02,0x00,0x0A,0x16,0x12,0x0C,0x04, /* 00000848 "........" */ + 0x0C,0xFF,0xFF,0x01,0x00,0x0A,0x03,0x00, /* 00000850 "........" */ + 0x0A,0x17,0x12,0x0B,0x04,0x0C,0xFF,0xFF, /* 00000858 "........" */ + 0x02,0x00,0x00,0x00,0x0A,0x18,0x12,0x0B, /* 00000860 "........" */ + 0x04,0x0C,0xFF,0xFF,0x02,0x00,0x01,0x00, /* 00000868 "........" */ + 0x0A,0x19,0x12,0x0C,0x04,0x0C,0xFF,0xFF, /* 00000870 "........" */ + 0x02,0x00,0x0A,0x02,0x00,0x0A,0x1A,0x12, /* 00000878 "........" */ + 0x0C,0x04,0x0C,0xFF,0xFF,0x02,0x00,0x0A, /* 00000880 "........" */ + 0x03,0x00,0x0A,0x1B,0x12,0x0B,0x04,0x0C, /* 00000888 "........" */ + 0xFF,0xFF,0x03,0x00,0x00,0x00,0x0A,0x1C, /* 00000890 "........" */ + 0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x03,0x00, /* 00000898 "........" */ + 0x01,0x00,0x0A,0x1D,0x12,0x0C,0x04,0x0C, /* 000008A0 "........" */ + 0xFF,0xFF,0x03,0x00,0x0A,0x02,0x00,0x0A, /* 000008A8 "........" */ + 0x1E,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x03, /* 000008B0 "........" */ + 0x00,0x0A,0x03,0x00,0x0A,0x1F,0x12,0x0B, /* 000008B8 "........" */ + 0x04,0x0C,0xFF,0xFF,0x04,0x00,0x00,0x00, /* 000008C0 "........" */ + 0x0A,0x20,0x12,0x0B,0x04,0x0C,0xFF,0xFF, /* 000008C8 ". ......" */ + 0x04,0x00,0x01,0x00,0x0A,0x21,0x12,0x0C, /* 000008D0 ".....!.." */ + 0x04,0x0C,0xFF,0xFF,0x04,0x00,0x0A,0x02, /* 000008D8 "........" */ + 0x00,0x0A,0x22,0x12,0x0C,0x04,0x0C,0xFF, /* 000008E0 ".."....." */ + 0xFF,0x04,0x00,0x0A,0x03,0x00,0x0A,0x23, /* 000008E8 ".......#" */ + 0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x05,0x00, /* 000008F0 "........" */ + 0x00,0x00,0x0A,0x24,0x12,0x0B,0x04,0x0C, /* 000008F8 "...$...." */ + 0xFF,0xFF,0x05,0x00,0x01,0x00,0x0A,0x25, /* 00000900 ".......%" */ + 0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x05,0x00, /* 00000908 "........" */ + 0x0A,0x02,0x00,0x0A,0x26,0x12,0x0C,0x04, /* 00000910 "....&..." */ + 0x0C,0xFF,0xFF,0x05,0x00,0x0A,0x03,0x00, /* 00000918 "........" */ + 0x0A,0x27,0x12,0x0B,0x04,0x0C,0xFF,0xFF, /* 00000920 ".'......" */ + 0x06,0x00,0x00,0x00,0x0A,0x28,0x12,0x0B, /* 00000928 ".....(.." */ + 0x04,0x0C,0xFF,0xFF,0x06,0x00,0x01,0x00, /* 00000930 "........" */ + 0x0A,0x29,0x12,0x0C,0x04,0x0C,0xFF,0xFF, /* 00000938 ".)......" */ + 0x06,0x00,0x0A,0x02,0x00,0x0A,0x2A,0x12, /* 00000940 "......*." */ + 0x0C,0x04,0x0C,0xFF,0xFF,0x06,0x00,0x0A, /* 00000948 "........" */ + 0x03,0x00,0x0A,0x2B,0x12,0x0B,0x04,0x0C, /* 00000950 "...+...." */ + 0xFF,0xFF,0x07,0x00,0x00,0x00,0x0A,0x2C, /* 00000958 ".......," */ + 0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x07,0x00, /* 00000960 "........" */ + 0x01,0x00,0x0A,0x2D,0x12,0x0C,0x04,0x0C, /* 00000968 "...-...." */ + 0xFF,0xFF,0x07,0x00,0x0A,0x02,0x00,0x0A, /* 00000970 "........" */ + 0x2E,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x07, /* 00000978 "........" */ + 0x00,0x0A,0x03,0x00,0x0A,0x2F,0x12,0x0B, /* 00000980 "...../.." */ + 0x04,0x0C,0xFF,0xFF,0x08,0x00,0x00,0x00, /* 00000988 "........" */ + 0x0A,0x11,0x12,0x0B,0x04,0x0C,0xFF,0xFF, /* 00000990 "........" */ + 0x08,0x00,0x01,0x00,0x0A,0x12,0x12,0x0C, /* 00000998 "........" */ + 0x04,0x0C,0xFF,0xFF,0x08,0x00,0x0A,0x02, /* 000009A0 "........" */ + 0x00,0x0A,0x13,0x12,0x0C,0x04,0x0C,0xFF, /* 000009A8 "........" */ + 0xFF,0x08,0x00,0x0A,0x03,0x00,0x0A,0x14, /* 000009B0 "........" */ + 0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x09,0x00, /* 000009B8 "........" */ + 0x00,0x00,0x0A,0x15,0x12,0x0B,0x04,0x0C, /* 000009C0 "........" */ + 0xFF,0xFF,0x09,0x00,0x01,0x00,0x0A,0x16, /* 000009C8 "........" */ + 0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x09,0x00, /* 000009D0 "........" */ + 0x0A,0x02,0x00,0x0A,0x17,0x12,0x0C,0x04, /* 000009D8 "........" */ + 0x0C,0xFF,0xFF,0x09,0x00,0x0A,0x03,0x00, /* 000009E0 "........" */ + 0x0A,0x18,0x12,0x0B,0x04,0x0C,0xFF,0xFF, /* 000009E8 "........" */ + 0x0A,0x00,0x00,0x00,0x0A,0x19,0x12,0x0B, /* 000009F0 "........" */ + 0x04,0x0C,0xFF,0xFF,0x0A,0x00,0x01,0x00, /* 000009F8 "........" */ + 0x0A,0x1A,0x12,0x0C,0x04,0x0C,0xFF,0xFF, /* 00000A00 "........" */ + 0x0A,0x00,0x0A,0x02,0x00,0x0A,0x1B,0x12, /* 00000A08 "........" */ + 0x0C,0x04,0x0C,0xFF,0xFF,0x0A,0x00,0x0A, /* 00000A10 "........" */ + 0x03,0x00,0x0A,0x1C,0x12,0x0B,0x04,0x0C, /* 00000A18 "........" */ + 0xFF,0xFF,0x0B,0x00,0x00,0x00,0x0A,0x1D, /* 00000A20 "........" */ + 0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x0B,0x00, /* 00000A28 "........" */ + 0x01,0x00,0x0A,0x1E,0x12,0x0C,0x04,0x0C, /* 00000A30 "........" */ + 0xFF,0xFF,0x0B,0x00,0x0A,0x02,0x00,0x0A, /* 00000A38 "........" */ + 0x1F,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x0B, /* 00000A40 "........" */ + 0x00,0x0A,0x03,0x00,0x0A,0x20,0x12,0x0B, /* 00000A48 "..... .." */ + 0x04,0x0C,0xFF,0xFF,0x0C,0x00,0x00,0x00, /* 00000A50 "........" */ + 0x0A,0x21,0x12,0x0B,0x04,0x0C,0xFF,0xFF, /* 00000A58 ".!......" */ + 0x0C,0x00,0x01,0x00,0x0A,0x22,0x12,0x0C, /* 00000A60 ".....".." */ + 0x04,0x0C,0xFF,0xFF,0x0C,0x00,0x0A,0x02, /* 00000A68 "........" */ + 0x00,0x0A,0x23,0x12,0x0C,0x04,0x0C,0xFF, /* 00000A70 "..#....." */ + 0xFF,0x0C,0x00,0x0A,0x03,0x00,0x0A,0x24, /* 00000A78 ".......$" */ + 0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x0D,0x00, /* 00000A80 "........" */ + 0x00,0x00,0x0A,0x25,0x12,0x0B,0x04,0x0C, /* 00000A88 "...%...." */ + 0xFF,0xFF,0x0D,0x00,0x01,0x00,0x0A,0x26, /* 00000A90 ".......&" */ + 0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x0D,0x00, /* 00000A98 "........" */ + 0x0A,0x02,0x00,0x0A,0x27,0x12,0x0C,0x04, /* 00000AA0 "....'..." */ + 0x0C,0xFF,0xFF,0x0D,0x00,0x0A,0x03,0x00, /* 00000AA8 "........" */ + 0x0A,0x28,0x12,0x0B,0x04,0x0C,0xFF,0xFF, /* 00000AB0 ".(......" */ + 0x0E,0x00,0x00,0x00,0x0A,0x29,0x12,0x0B, /* 00000AB8 ".....).." */ + 0x04,0x0C,0xFF,0xFF,0x0E,0x00,0x01,0x00, /* 00000AC0 "........" */ + 0x0A,0x2A,0x12,0x0C,0x04,0x0C,0xFF,0xFF, /* 00000AC8 ".*......" */ + 0x0E,0x00,0x0A,0x02,0x00,0x0A,0x2B,0x12, /* 00000AD0 "......+." */ + 0x0C,0x04,0x0C,0xFF,0xFF,0x0E,0x00,0x0A, /* 00000AD8 "........" */ + 0x03,0x00,0x0A,0x2C,0x12,0x0B,0x04,0x0C, /* 00000AE0 "...,...." */ + 0xFF,0xFF,0x0F,0x00,0x00,0x00,0x0A,0x2D, /* 00000AE8 ".......-" */ + 0x12,0x0B,0x04,0x0C,0xFF,0xFF,0x0F,0x00, /* 00000AF0 "........" */ + 0x01,0x00,0x0A,0x2E,0x12,0x0C,0x04,0x0C, /* 00000AF8 "........" */ + 0xFF,0xFF,0x0F,0x00,0x0A,0x02,0x00,0x0A, /* 00000B00 "........" */ + 0x2F,0x12,0x0C,0x04,0x0C,0xFF,0xFF,0x0F, /* 00000B08 "/......." */ + 0x00,0x0A,0x03,0x00,0x0A,0x10,0x5B,0x82, /* 00000B10 "......[." */ + 0x46,0x37,0x49,0x53,0x41,0x5F,0x08,0x5F, /* 00000B18 "F7ISA_._" */ + 0x41,0x44,0x52,0x0C,0x00,0x00,0x01,0x00, /* 00000B20 "ADR....." */ + 0x5B,0x80,0x50,0x49,0x52,0x51,0x02,0x0A, /* 00000B28 "[.PIRQ.." */ + 0x60,0x0A,0x04,0x10,0x2E,0x5C,0x00,0x5B, /* 00000B30 "`....\.[" */ + 0x81,0x29,0x5C,0x2F,0x04,0x5F,0x53,0x42, /* 00000B38 ".)\/._SB" */ + 0x5F,0x50,0x43,0x49,0x30,0x49,0x53,0x41, /* 00000B40 "_PCI0ISA" */ + 0x5F,0x50,0x49,0x52,0x51,0x01,0x50,0x49, /* 00000B48 "_PIRQ.PI" */ + 0x52,0x41,0x08,0x50,0x49,0x52,0x42,0x08, /* 00000B50 "RA.PIRB." */ + 0x50,0x49,0x52,0x43,0x08,0x50,0x49,0x52, /* 00000B58 "PIRC.PIR" */ + 0x44,0x08,0x5B,0x82,0x46,0x0B,0x53,0x59, /* 00000B60 "D.[.F.SY" */ + 0x53,0x52,0x08,0x5F,0x48,0x49,0x44,0x0C, /* 00000B68 "SR._HID." */ + 0x41,0xD0,0x0C,0x02,0x08,0x5F,0x55,0x49, /* 00000B70 "A...._UI" */ + 0x44,0x01,0x08,0x43,0x52,0x53,0x5F,0x11, /* 00000B78 "D..CRS_." */ + 0x4E,0x08,0x0A,0x8A,0x47,0x01,0x10,0x00, /* 00000B80 "N...G..." */ + 0x10,0x00,0x00,0x10,0x47,0x01,0x22,0x00, /* 00000B88 "....G."." */ + 0x22,0x00,0x00,0x0C,0x47,0x01,0x30,0x00, /* 00000B90 ""...G.0." */ + 0x30,0x00,0x00,0x10,0x47,0x01,0x44,0x00, /* 00000B98 "0...G.D." */ + 0x44,0x00,0x00,0x1C,0x47,0x01,0x62,0x00, /* 00000BA0 "D...G.b." */ + 0x62,0x00,0x00,0x02,0x47,0x01,0x65,0x00, /* 00000BA8 "b...G.e." */ + 0x65,0x00,0x00,0x0B,0x47,0x01,0x72,0x00, /* 00000BB0 "e...G.r." */ + 0x72,0x00,0x00,0x0E,0x47,0x01,0x80,0x00, /* 00000BB8 "r...G..." */ + 0x80,0x00,0x00,0x01,0x47,0x01,0x84,0x00, /* 00000BC0 "....G..." */ + 0x84,0x00,0x00,0x03,0x47,0x01,0x88,0x00, /* 00000BC8 "....G..." */ + 0x88,0x00,0x00,0x01,0x47,0x01,0x8C,0x00, /* 00000BD0 "....G..." */ + 0x8C,0x00,0x00,0x03,0x47,0x01,0x90,0x00, /* 00000BD8 "....G..." */ + 0x90,0x00,0x00,0x10,0x47,0x01,0xA2,0x00, /* 00000BE0 "....G..." */ + 0xA2,0x00,0x00,0x1C,0x47,0x01,0xE0,0x00, /* 00000BE8 "....G..." */ + 0xE0,0x00,0x00,0x10,0x47,0x01,0xA0,0x08, /* 00000BF0 "....G..." */ + 0xA0,0x08,0x00,0x04,0x47,0x01,0xC0,0x0C, /* 00000BF8 "....G..." */ + 0xC0,0x0C,0x00,0x10,0x47,0x01,0xD0,0x04, /* 00000C00 "....G..." */ + 0xD0,0x04,0x00,0x02,0x79,0x00,0x14,0x0B, /* 00000C08 "....y..." */ + 0x5F,0x43,0x52,0x53,0x00,0xA4,0x43,0x52, /* 00000C10 "_CRS..CR" */ + 0x53,0x5F,0x5B,0x82,0x2B,0x50,0x49,0x43, /* 00000C18 "S_[.+PIC" */ + 0x5F,0x08,0x5F,0x48,0x49,0x44,0x0B,0x41, /* 00000C20 "_._HID.A" */ + 0xD0,0x08,0x5F,0x43,0x52,0x53,0x11,0x18, /* 00000C28 ".._CRS.." */ + 0x0A,0x15,0x47,0x01,0x20,0x00,0x20,0x00, /* 00000C30 "..G. . ." */ + 0x01,0x02,0x47,0x01,0xA0,0x00,0xA0,0x00, /* 00000C38 "..G....." */ + 0x01,0x02,0x22,0x04,0x00,0x79,0x00,0x5B, /* 00000C40 ".."..y.[" */ + 0x82,0x47,0x05,0x44,0x4D,0x41,0x30,0x08, /* 00000C48 ".G.DMA0." */ + 0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x02, /* 00000C50 "_HID.A.." */ + 0x00,0x08,0x5F,0x43,0x52,0x53,0x11,0x41, /* 00000C58 ".._CRS.A" */ + 0x04,0x0A,0x3D,0x2A,0x10,0x04,0x47,0x01, /* 00000C60 "..=*..G." */ + 0x00,0x00,0x00,0x00,0x00,0x10,0x47,0x01, /* 00000C68 "......G." */ + 0x81,0x00,0x81,0x00,0x00,0x03,0x47,0x01, /* 00000C70 "......G." */ + 0x87,0x00,0x87,0x00,0x00,0x01,0x47,0x01, /* 00000C78 "......G." */ + 0x89,0x00,0x89,0x00,0x00,0x03,0x47,0x01, /* 00000C80 "......G." */ + 0x8F,0x00,0x8F,0x00,0x00,0x01,0x47,0x01, /* 00000C88 "......G." */ + 0xC0,0x00,0xC0,0x00,0x00,0x20,0x47,0x01, /* 00000C90 "..... G." */ + 0x80,0x04,0x80,0x04,0x00,0x10,0x79,0x00, /* 00000C98 "......y." */ + 0x5B,0x82,0x25,0x54,0x4D,0x52,0x5F,0x08, /* 00000CA0 "[.%TMR_." */ + 0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0,0x01, /* 00000CA8 "_HID.A.." */ + 0x00,0x08,0x5F,0x43,0x52,0x53,0x11,0x10, /* 00000CB0 ".._CRS.." */ + 0x0A,0x0D,0x47,0x01,0x40,0x00,0x40,0x00, /* 00000CB8 "..G.@.@." */ + 0x00,0x04,0x22,0x01,0x00,0x79,0x00,0x5B, /* 00000CC0 ".."..y.[" */ + 0x82,0x25,0x52,0x54,0x43,0x5F,0x08,0x5F, /* 00000CC8 ".%RTC_._" */ + 0x48,0x49,0x44,0x0C,0x41,0xD0,0x0B,0x00, /* 00000CD0 "HID.A..." */ + 0x08,0x5F,0x43,0x52,0x53,0x11,0x10,0x0A, /* 00000CD8 "._CRS..." */ + 0x0D,0x47,0x01,0x70,0x00,0x70,0x00,0x00, /* 00000CE0 ".G.p.p.." */ + 0x02,0x22,0x00,0x01,0x79,0x00,0x5B,0x82, /* 00000CE8 "."..y.[." */ + 0x22,0x53,0x50,0x4B,0x52,0x08,0x5F,0x48, /* 00000CF0 ""SPKR._H" */ + 0x49,0x44,0x0C,0x41,0xD0,0x08,0x00,0x08, /* 00000CF8 "ID.A...." */ + 0x5F,0x43,0x52,0x53,0x11,0x0D,0x0A,0x0A, /* 00000D00 "_CRS...." */ + 0x47,0x01,0x61,0x00,0x61,0x00,0x00,0x01, /* 00000D08 "G.a.a..." */ + 0x79,0x00,0x5B,0x82,0x31,0x50,0x53,0x32, /* 00000D10 "y.[.1PS2" */ + 0x4D,0x08,0x5F,0x48,0x49,0x44,0x0C,0x41, /* 00000D18 "M._HID.A" */ + 0xD0,0x0F,0x13,0x08,0x5F,0x43,0x49,0x44, /* 00000D20 "...._CID" */ + 0x0C,0x41,0xD0,0x0F,0x13,0x14,0x09,0x5F, /* 00000D28 ".A....._" */ + 0x53,0x54,0x41,0x00,0xA4,0x0A,0x0F,0x08, /* 00000D30 "STA....." */ + 0x5F,0x43,0x52,0x53,0x11,0x08,0x0A,0x05, /* 00000D38 "_CRS...." */ + 0x22,0x00,0x10,0x79,0x00,0x5B,0x82,0x42, /* 00000D40 ""..y.[.B" */ + 0x04,0x50,0x53,0x32,0x4B,0x08,0x5F,0x48, /* 00000D48 ".PS2K._H" */ + 0x49,0x44,0x0C,0x41,0xD0,0x03,0x03,0x08, /* 00000D50 "ID.A...." */ + 0x5F,0x43,0x49,0x44,0x0C,0x41,0xD0,0x03, /* 00000D58 "_CID.A.." */ + 0x0B,0x14,0x09,0x5F,0x53,0x54,0x41,0x00, /* 00000D60 "..._STA." */ + 0xA4,0x0A,0x0F,0x08,0x5F,0x43,0x52,0x53, /* 00000D68 "...._CRS" */ + 0x11,0x18,0x0A,0x15,0x47,0x01,0x60,0x00, /* 00000D70 "....G.`." */ + 0x60,0x00,0x00,0x01,0x47,0x01,0x64,0x00, /* 00000D78 "`...G.d." */ + 0x64,0x00,0x00,0x01,0x22,0x02,0x00,0x79, /* 00000D80 "d..."..y" */ + 0x00,0x5B,0x82,0x3A,0x46,0x44,0x43,0x30, /* 00000D88 ".[.:FDC0" */ + 0x08,0x5F,0x48,0x49,0x44,0x0C,0x41,0xD0, /* 00000D90 "._HID.A." */ + 0x07,0x00,0x14,0x09,0x5F,0x53,0x54,0x41, /* 00000D98 "...._STA" */ + 0x00,0xA4,0x0A,0x0F,0x08,0x5F,0x43,0x52, /* 00000DA0 "....._CR" */ + 0x53,0x11,0x1B,0x0A,0x18,0x47,0x01,0xF0, /* 00000DA8 "S....G.." */ + 0x03,0xF0,0x03,0x01,0x06,0x47,0x01,0xF7, /* 00000DB0 ".....G.." */ + 0x03,0xF7,0x03,0x01,0x01,0x22,0x40,0x00, /* 00000DB8 "....."@." */ + 0x2A,0x04,0x00,0x79,0x00,0x5B,0x82,0x46, /* 00000DC0 "*..y.[.F" */ + 0x04,0x55,0x41,0x52,0x31,0x08,0x5F,0x48, /* 00000DC8 ".UAR1._H" */ + 0x49,0x44,0x0C,0x41,0xD0,0x05,0x01,0x08, /* 00000DD0 "ID.A...." */ + 0x5F,0x55,0x49,0x44,0x01,0x14,0x19,0x5F, /* 00000DD8 "_UID..._" */ + 0x53,0x54,0x41,0x00,0xA0,0x0D,0x93,0x5E, /* 00000DE0 "STA....^" */ + 0x5E,0x5E,0x5E,0x55,0x41,0x52,0x31,0x00, /* 00000DE8 "^^^UAR1." */ + 0xA4,0x00,0xA1,0x04,0xA4,0x0A,0x0F,0x08, /* 00000DF0 "........" */ + 0x5F,0x43,0x52,0x53,0x11,0x10,0x0A,0x0D, /* 00000DF8 "_CRS...." */ + 0x47,0x01,0xF8,0x03,0xF8,0x03,0x08,0x08, /* 00000E00 "G......." */ + 0x22,0x10,0x00,0x79,0x00,0x5B,0x82,0x47, /* 00000E08 ""..y.[.G" */ + 0x04,0x55,0x41,0x52,0x32,0x08,0x5F,0x48, /* 00000E10 ".UAR2._H" */ + 0x49,0x44,0x0C,0x41,0xD0,0x05,0x01,0x08, /* 00000E18 "ID.A...." */ + 0x5F,0x55,0x49,0x44,0x0A,0x02,0x14,0x19, /* 00000E20 "_UID...." */ + 0x5F,0x53,0x54,0x41,0x00,0xA0,0x0D,0x93, /* 00000E28 "_STA...." */ + 0x5E,0x5E,0x5E,0x5E,0x55,0x41,0x52,0x32, /* 00000E30 "^^^^UAR2" */ + 0x00,0xA4,0x00,0xA1,0x04,0xA4,0x0A,0x0F, /* 00000E38 "........" */ + 0x08,0x5F,0x43,0x52,0x53,0x11,0x10,0x0A, /* 00000E40 "._CRS..." */ + 0x0D,0x47,0x01,0xF8,0x02,0xF8,0x02,0x08, /* 00000E48 ".G......" */ + 0x08,0x22,0x08,0x00,0x79,0x00,0x5B,0x82, /* 00000E50 "."..y.[." */ + 0x36,0x4C,0x54,0x50,0x31,0x08,0x5F,0x48, /* 00000E58 "6LTP1._H" */ + 0x49,0x44,0x0C,0x41,0xD0,0x04,0x00,0x08, /* 00000E60 "ID.A...." */ + 0x5F,0x55,0x49,0x44,0x0A,0x02,0x14,0x09, /* 00000E68 "_UID...." */ + 0x5F,0x53,0x54,0x41,0x00,0xA4,0x0A,0x0F, /* 00000E70 "_STA...." */ + 0x08,0x5F,0x43,0x52,0x53,0x11,0x10,0x0A, /* 00000E78 "._CRS..." */ + 0x0D,0x47,0x01,0x78,0x03,0x78,0x03,0x08, /* 00000E80 ".G.x.x.." */ + 0x08,0x22,0x80,0x00,0x79,0x00, }; int DsdtLen=sizeof(AmlCode); diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index 5c76e02650..fafe3e8534 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -127,7 +127,7 @@ LEGACY_CFG_TO_XENAPI_CFG = reverse_dict(XENAPI_CFG_TO_LEGACY_CFG) XENAPI_PLATFORM_CFG = [ 'acpi', 'apic', 'boot', 'device_model', 'loader', 'display', 'fda', 'fdb', 'keymap', 'isa', 'localtime', 'monitor', 'nographic', 'pae', 'rtc_timeoffset', 'serial', 'sdl', - 'soundhw','stdvga', 'usb', 'usbdevice', 'vnc', + 'soundhw','stdvga', 'usb', 'usbdevice', 'hpet', 'vnc', 'vncconsole', 'vncdisplay', 'vnclisten', 'timer_mode', 'vncpasswd', 'vncunused', 'xauthority', 'pci', 'vhpt', 'guest_os_type', 'hap'] diff --git a/tools/python/xen/xend/XendConstants.py b/tools/python/xen/xend/XendConstants.py index a99dbdc92f..bca3ee7dd1 100644 --- a/tools/python/xen/xend/XendConstants.py +++ b/tools/python/xen/xend/XendConstants.py @@ -47,6 +47,7 @@ HVM_PARAM_NVRAM_FD = 7 HVM_PARAM_VHPT_SIZE = 8 HVM_PARAM_BUFPIOREQ_PFN = 9 HVM_PARAM_TIMER_MODE = 10 +HVM_PARAM_HPET_ENABLED = 11 restart_modes = [ "restart", diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index f00ac38ce6..7c8e0975a4 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -1692,6 +1692,12 @@ class XendDomainInfo: xc.hvm_set_param(self.domid, HVM_PARAM_TIMER_MODE, long(timer_mode)) + # Optionally enable virtual HPET + hpet = self.info["platform"].get("hpet") + if hvm and hpet is not None: + xc.hvm_set_param(self.domid, HVM_PARAM_HPET_ENABLED, + long(hpet)) + # Set maximum number of vcpus in domain xc.domain_max_vcpus(self.domid, int(self.info['VCPUs_max'])) diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py index 1c508becd3..7a3d764c6b 100644 --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -198,6 +198,10 @@ gopts.var('pae', val='PAE', fn=set_int, default=1, use="Disable or enable PAE of HVM domain.") +gopts.var('hpet', val='HPET', + fn=set_int, default=0, + use="Enable virtual high-precision event timer.") + gopts.var('timer_mode', val='TIMER_MODE', fn=set_int, default=0, use="""Timer mode (0=delay virtual time when ticks are missed; @@ -740,7 +744,7 @@ def configure_hvm(config_image, vals): 'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'soundhw', 'vnc', 'vncdisplay', 'vncunused', 'vncconsole', 'vnclisten', 'sdl', 'display', 'xauthority', 'rtc_timeoffset', 'monitor', - 'acpi', 'apic', 'usb', 'usbdevice', 'keymap', 'pci', + 'acpi', 'apic', 'usb', 'usbdevice', 'keymap', 'pci', 'hpet', 'guest_os_type', 'hap'] for a in args: diff --git a/tools/python/xen/xm/xenapi_create.py b/tools/python/xen/xm/xenapi_create.py index 04abcc4e4e..9c16376955 100644 --- a/tools/python/xen/xm/xenapi_create.py +++ b/tools/python/xen/xm/xenapi_create.py @@ -818,7 +818,8 @@ class sxp2xml: def extract_platform(self, image, document): - platform_keys = ['acpi', 'apic', 'pae', 'vhpt', 'timer_mode', 'hap'] + platform_keys = ['acpi', 'apic', 'pae', 'vhpt', 'timer_mode', + 'hap', 'hpet'] def extract_platform_key(key): platform = document.createElement("platform") diff --git a/xen/arch/x86/hvm/hpet.c b/xen/arch/x86/hvm/hpet.c index f6845755a0..49ca998d37 100644 --- a/xen/arch/x86/hvm/hpet.c +++ b/xen/arch/x86/hvm/hpet.c @@ -353,7 +353,8 @@ static void hpet_write( static int hpet_range(struct vcpu *v, unsigned long addr) { - return ((addr >= HPET_BASE_ADDRESS) && + return (v->domain->arch.hvm_domain.params[HVM_PARAM_HPET_ENABLED] && + (addr >= HPET_BASE_ADDRESS) && (addr < (HPET_BASE_ADDRESS + HPET_MMAP_SIZE))); } diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 14c965cef9..0f543dac9c 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -232,6 +232,8 @@ int hvm_domain_initialise(struct domain *d) spin_lock_init(&d->arch.hvm_domain.irq_lock); spin_lock_init(&d->arch.hvm_domain.uc_lock); + d->arch.hvm_domain.params[HVM_PARAM_HPET_ENABLED] = 1; + hvm_init_cacheattr_region_list(d); rc = paging_enable(d, PG_refcounts|PG_translate|PG_external); diff --git a/xen/include/public/hvm/params.h b/xen/include/public/hvm/params.h index 486499816d..aad2196db3 100644 --- a/xen/include/public/hvm/params.h +++ b/xen/include/public/hvm/params.h @@ -81,6 +81,9 @@ #define HVMPTM_no_missed_ticks_pending 2 #define HVMPTM_one_missed_tick_pending 3 -#define HVM_NR_PARAMS 11 +/* Boolean: Enable virtual HPET (high-precision event timer)? (x86-only) */ +#define HVM_PARAM_HPET_ENABLED 11 + +#define HVM_NR_PARAMS 12 #endif /* __XEN_PUBLIC_HVM_PARAMS_H__ */ -- cgit v1.2.3 From 6193b2034d5adbd5ab0eac13326651108fe5e35b Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 11 Feb 2008 14:47:06 +0000 Subject: ioemu: cope with partial reads/writes when using the read()/write() syscall interfaces. Signed-off-by: Samuel Thibault --- tools/ioemu/block-raw.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/tools/ioemu/block-raw.c b/tools/ioemu/block-raw.c index 1ecf29cdb5..182d2ec55e 100644 --- a/tools/ioemu/block-raw.c +++ b/tools/ioemu/block-raw.c @@ -169,10 +169,16 @@ static int raw_pread(BlockDriverState *bs, int64_t offset, } s->lseek_err_cnt=0; - ret = read(s->fd, buf, count); - if (ret == count) - goto label__raw_read__success; + uint64_t done; + for (done = 0; done < count; done += ret) { + ret = read(s->fd, buf + done, count - done); + if (ret == -1) + goto label__raw_read__error; + } + ret = count; + goto label__raw_read__success; +label__raw_read__error: DEBUG_BLOCK_PRINT("raw_read(%d:%s, %" PRId64 ", %p, %d) [%" PRId64 "] read failed %d : %d = %s\n", s->fd, bs->filename, @@ -234,9 +240,16 @@ static int raw_pwrite(BlockDriverState *bs, int64_t offset, } s->lseek_err_cnt = 0; - ret = write(s->fd, buf, count); - if (ret == count) - goto label__raw_write__success; + uint64_t done; + for (done = 0; done < count; done += ret) { + ret = write(s->fd, buf + done, count - done); + if (ret == -1) + goto label__raw_write__error; + } + ret = count; + goto label__raw_write__success; + +label__raw_write__error: DEBUG_BLOCK_PRINT("raw_write(%d:%s, %" PRId64 ", %p, %d) [%" PRId64 "] write failed %d : %d = %s\n", s->fd, -- cgit v1.2.3 From 7a26ce5af33f4a32b456e51f59ab25b86b7eefc0 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 11 Feb 2008 14:47:19 +0000 Subject: ioemu: save 3MB of ioport tables (on 64bit machines) by keeping then initialized to NULL and check for it in the handlers. Signed-off-by: Samuel Thibault --- tools/ioemu/vl.c | 60 +++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index 82300c510d..7885fbe3c0 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -227,17 +227,29 @@ void default_ioport_writeb(void *opaque, uint32_t address, uint32_t data) uint32_t default_ioport_readw(void *opaque, uint32_t address) { uint32_t data; - data = ioport_read_table[0][address](ioport_opaque[address], address); + IOPortReadFunc *func = ioport_read_table[0][address]; + if (!func) + func = default_ioport_readb; + data = func(ioport_opaque[address], address); address = (address + 1) & (MAX_IOPORTS - 1); - data |= ioport_read_table[0][address](ioport_opaque[address], address) << 8; + func = ioport_read_table[0][address]; + if (!func) + func = default_ioport_readb; + data |= func(ioport_opaque[address], address) << 8; return data; } void default_ioport_writew(void *opaque, uint32_t address, uint32_t data) { - ioport_write_table[0][address](ioport_opaque[address], address, data & 0xff); + IOPortWriteFunc *func = ioport_write_table[0][address]; + if (!func) + func = default_ioport_writeb; + func(ioport_opaque[address], address, data & 0xff); address = (address + 1) & (MAX_IOPORTS - 1); - ioport_write_table[0][address](ioport_opaque[address], address, (data >> 8) & 0xff); + func = ioport_write_table[0][address]; + if (!func) + func = default_ioport_writeb; + func(ioport_opaque[address], address, (data >> 8) & 0xff); } uint32_t default_ioport_readl(void *opaque, uint32_t address) @@ -257,16 +269,6 @@ void default_ioport_writel(void *opaque, uint32_t address, uint32_t data) void init_ioports(void) { - int i; - - for(i = 0; i < MAX_IOPORTS; i++) { - ioport_read_table[0][i] = default_ioport_readb; - ioport_write_table[0][i] = default_ioport_writeb; - ioport_read_table[1][i] = default_ioport_readw; - ioport_write_table[1][i] = default_ioport_writew; - ioport_read_table[2][i] = default_ioport_readl; - ioport_write_table[2][i] = default_ioport_writel; - } } /* size is the word size in byte */ @@ -338,11 +340,14 @@ void isa_unassign_ioport(int start, int length) void cpu_outb(CPUState *env, int addr, int val) { + IOPortWriteFunc *func = ioport_write_table[0][addr]; + if (!func) + func = default_ioport_writeb; #ifdef DEBUG_IOPORT if (loglevel & CPU_LOG_IOPORT) fprintf(logfile, "outb: %04x %02x\n", addr, val); #endif - ioport_write_table[0][addr](ioport_opaque[addr], addr, val); + func(ioport_opaque[addr], addr, val); #ifdef USE_KQEMU if (env) env->last_io_time = cpu_get_time_fast(); @@ -351,11 +356,14 @@ void cpu_outb(CPUState *env, int addr, int val) void cpu_outw(CPUState *env, int addr, int val) { + IOPortWriteFunc *func = ioport_write_table[1][addr]; + if (!func) + func = default_ioport_writew; #ifdef DEBUG_IOPORT if (loglevel & CPU_LOG_IOPORT) fprintf(logfile, "outw: %04x %04x\n", addr, val); #endif - ioport_write_table[1][addr](ioport_opaque[addr], addr, val); + func(ioport_opaque[addr], addr, val); #ifdef USE_KQEMU if (env) env->last_io_time = cpu_get_time_fast(); @@ -364,11 +372,14 @@ void cpu_outw(CPUState *env, int addr, int val) void cpu_outl(CPUState *env, int addr, int val) { + IOPortWriteFunc *func = ioport_write_table[2][addr]; + if (!func) + func = default_ioport_writel; #ifdef DEBUG_IOPORT if (loglevel & CPU_LOG_IOPORT) fprintf(logfile, "outl: %04x %08x\n", addr, val); #endif - ioport_write_table[2][addr](ioport_opaque[addr], addr, val); + func(ioport_opaque[addr], addr, val); #ifdef USE_KQEMU if (env) env->last_io_time = cpu_get_time_fast(); @@ -378,7 +389,10 @@ void cpu_outl(CPUState *env, int addr, int val) int cpu_inb(CPUState *env, int addr) { int val; - val = ioport_read_table[0][addr](ioport_opaque[addr], addr); + IOPortReadFunc *func = ioport_read_table[0][addr]; + if (!func) + func = default_ioport_readb; + val = func(ioport_opaque[addr], addr); #ifdef DEBUG_IOPORT if (loglevel & CPU_LOG_IOPORT) fprintf(logfile, "inb : %04x %02x\n", addr, val); @@ -393,7 +407,10 @@ int cpu_inb(CPUState *env, int addr) int cpu_inw(CPUState *env, int addr) { int val; - val = ioport_read_table[1][addr](ioport_opaque[addr], addr); + IOPortReadFunc *func = ioport_read_table[1][addr]; + if (!func) + func = default_ioport_readw; + val = func(ioport_opaque[addr], addr); #ifdef DEBUG_IOPORT if (loglevel & CPU_LOG_IOPORT) fprintf(logfile, "inw : %04x %04x\n", addr, val); @@ -408,7 +425,10 @@ int cpu_inw(CPUState *env, int addr) int cpu_inl(CPUState *env, int addr) { int val; - val = ioport_read_table[2][addr](ioport_opaque[addr], addr); + IOPortReadFunc *func = ioport_read_table[2][addr]; + if (!func) + func = default_ioport_readl; + val = func(ioport_opaque[addr], addr); #ifdef DEBUG_IOPORT if (loglevel & CPU_LOG_IOPORT) fprintf(logfile, "inl : %04x %08x\n", addr, val); -- cgit v1.2.3 From c35e8672fbd86aca2422aece979cc2eae8ed3cdd Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 11 Feb 2008 14:50:50 +0000 Subject: xen-api: Add TOC and hyperlink cross reference to xen-api document Signed-off-by: Stefan Berger --- docs/xen-api/revision-history.tex | 7 +++++++ docs/xen-api/xenapi-coversheet.tex | 2 +- docs/xen-api/xenapi.tex | 5 +++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/xen-api/revision-history.tex b/docs/xen-api/revision-history.tex index 70ac17390f..d282adb106 100644 --- a/docs/xen-api/revision-history.tex +++ b/docs/xen-api/revision-history.tex @@ -23,5 +23,12 @@ \end{flushleft} \end{minipage}\\ \hline + 1.0.2 & 11th Feb. 08 & S. Berger & + \begin{minipage}[t]{7cm} + \begin{flushleft} + Added table of contents and hyperlink cross reference. + \end{flushleft} + \end{minipage}\\ + \hline \end{tabular} \end{center} \ No newline at end of file diff --git a/docs/xen-api/xenapi-coversheet.tex b/docs/xen-api/xenapi-coversheet.tex index bf9371f073..c35190acfe 100644 --- a/docs/xen-api/xenapi-coversheet.tex +++ b/docs/xen-api/xenapi-coversheet.tex @@ -17,7 +17,7 @@ \newcommand{\coversheetlogo}{xen.eps} %% Document date -\newcommand{\datestring}{25th January 2008} +\newcommand{\datestring}{11th February 2008} \newcommand{\releasestatement}{Stable Release} diff --git a/docs/xen-api/xenapi.tex b/docs/xen-api/xenapi.tex index f71689e377..902d9b2daf 100644 --- a/docs/xen-api/xenapi.tex +++ b/docs/xen-api/xenapi.tex @@ -17,6 +17,7 @@ \usepackage{graphics} \usepackage{longtable} \usepackage{fancyhdr} +\usepackage{hyperref} \setlength\topskip{0cm} \setlength\topmargin{0cm} @@ -35,6 +36,10 @@ % The revision history \include{revision-history} +% Table of contents +\tableofcontents + + % ... and off we go! \chapter{Introduction} -- cgit v1.2.3 From 283dddae870fc59c34dca7242a4988bf82a92c7a Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 11 Feb 2008 14:51:22 +0000 Subject: xen-api: Fix some errors in Xen-API's PBD class. Signed-off-by: Stefan Berger --- tools/python/xen/xend/XendPBD.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tools/python/xen/xend/XendPBD.py b/tools/python/xen/xend/XendPBD.py index 10d8c32b81..2187cd7850 100644 --- a/tools/python/xen/xend/XendPBD.py +++ b/tools/python/xen/xend/XendPBD.py @@ -20,6 +20,7 @@ import uuid from XendLogging import log from xen.xend.XendBase import XendBase from xen.xend import XendAPIStore +from xen.xend import uuid as genuuid class XendPBD(XendBase): """Physical block devices.""" @@ -39,8 +40,7 @@ class XendPBD(XendBase): return XendBase.getAttrRW() + attrRW def getAttrInst(self): - return ['uuid', - 'host', + return ['host', 'SR', 'device_config'] @@ -61,31 +61,31 @@ class XendPBD(XendBase): getFuncs = classmethod(getFuncs) def recreate(uuid, record): - pbd = XendPBD(uuid, record) + pbd = XendPBD(record, uuid) return uuid def create(cls, record): uuid = genuuid.createString() - pbd = XendPBD(uuid, record) - return uuid + pbd = XendPBD(record, uuid) + return uuid create = classmethod(create) - def __init__(self, uuid, record): + def __init__(self, record, uuid): XendBase.__init__(self, uuid, record) - this.currently_attached = True + self.currently_attached = True def get_host(self): - return this.host + return self.host def get_SR(self): - return this.SR + return self.SR def get_device_config(self): - return this.device_config + return self.device_config def get_currently_attached(self): - return this.currently_attached + return self.currently_attached def destroy(self): pass -- cgit v1.2.3 From 6abc7e7e8c16fcf4deb4819d8d96591739cb8dbd Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 11 Feb 2008 14:55:33 +0000 Subject: ioemu: Dynamic VNC colour depth. The qemu vnc server changes its internal colour depth based on the client request. This way just one colour conversion is done: the one in vga_template.h, from the guest colour depth and the vnc server internal colour depth. This patch is meant to remove this colour conversion to improve performances. It accomplishes the goal making the qemu internal colour depth always the same as the guest colour depth. The basic idea is that the vnc client is the one that should do the colour conversion, if necessary. In general it should accept the pixel format suggested by the server during the initial negotiation. This behaviour can be set in most vnc clients (vncviewer included). If the guest changes colour depth, the qemu vnc server changes colour depth too and notifies the client. The problem is that the vnc protocol doesn't provide a message from the server to the client to ask for a colour depth change. So what I am doing is either: 1) quietly starting to do the conversion on vnc server (not gaining any performance here); 2) closing the vnc connection with the client, so the client can reconnect and choose the new pixel format. By default I am doing 1), however the second choice can be enabled passing the -vnc-switch-bpp command line option. In order to do the colour conversion on the vnc server I had to improve the colour conversion code already in place because it only supported conversions from 32 bpp. The patch adds colour conversion code that support conversions from any resolution to any resolution. A last note: to get most out of this patch it is best to set Windows to 16 bit colour depth, because the 24 bit mode is 24 bit depth and 24 bpp, meaning no alpha channel. The vnc protocol doesn't support 24 bpp, only 32 bpp, so this conversion is unavoidable. From: Stefano Stabellini Signed-off-by: Keir Fraser --- tools/ioemu/console.c | 6 +- tools/ioemu/hw/vga.c | 14 ++- tools/ioemu/sdl.c | 1 + tools/ioemu/vl.c | 10 ++ tools/ioemu/vl.h | 3 + tools/ioemu/vnc.c | 241 ++++++++++++++++++++++++++++++++++------------- tools/ioemu/vnchextile.h | 12 +-- 7 files changed, 207 insertions(+), 80 deletions(-) diff --git a/tools/ioemu/console.c b/tools/ioemu/console.c index 634e3d85d0..dc904f6574 100644 --- a/tools/ioemu/console.c +++ b/tools/ioemu/console.c @@ -169,16 +169,12 @@ static unsigned int vga_get_color(DisplayState *ds, unsigned int rgba) unsigned int r, g, b, color; switch(ds->depth) { -#if 0 case 8: r = (rgba >> 16) & 0xff; g = (rgba >> 8) & 0xff; b = (rgba) & 0xff; - color = (rgb_to_index[r] * 6 * 6) + - (rgb_to_index[g] * 6) + - (rgb_to_index[b]); + color = ((r >> 5) << 5 | (g >> 5) << 2 | (b >> 6)); break; -#endif case 15: r = (rgba >> 16) & 0xff; g = (rgba >> 8) & 0xff; diff --git a/tools/ioemu/hw/vga.c b/tools/ioemu/hw/vga.c index 17538bbddc..4e2f9525a7 100644 --- a/tools/ioemu/hw/vga.c +++ b/tools/ioemu/hw/vga.c @@ -1071,7 +1071,7 @@ static const uint8_t cursor_glyph[32 * 4] = { */ static void vga_draw_text(VGAState *s, int full_update) { - int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr; + int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr, depth; int cx_min, cx_max, linesize, x_incr; uint32_t offset, fgcol, bgcol, v, cursor_offset; uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr; @@ -1134,6 +1134,11 @@ static void vga_draw_text(VGAState *s, int full_update) return; } + depth = s->get_bpp(s); + if (depth == 24) + depth = 32; + if (s->ds->dpy_colourdepth != NULL && s->ds->depth != depth) + s->ds->dpy_colourdepth(s->ds, depth); if (width != s->last_width || height != s->last_height || cw != s->last_cw || cheight != s->last_ch) { s->last_scr_width = width * cw; @@ -1477,7 +1482,7 @@ void check_sse2(void) */ static void vga_draw_graphic(VGAState *s, int full_update) { - int y1, y, update, linesize, y_start, double_scan, mask; + int y1, y, update, linesize, y_start, double_scan, mask, depth; int width, height, shift_control, line_offset, bwidth; ram_addr_t page0, page1; int disp_width, multi_scan, multi_run; @@ -1551,6 +1556,11 @@ static void vga_draw_graphic(VGAState *s, int full_update) } vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)]; + depth = s->get_bpp(s); + if (depth == 24) + depth = 32; + if (s->ds->dpy_colourdepth != NULL && s->ds->depth != depth) + s->ds->dpy_colourdepth(s->ds, depth); if (disp_width != s->last_width || height != s->last_height) { dpy_resize(s->ds, disp_width, height); diff --git a/tools/ioemu/sdl.c b/tools/ioemu/sdl.c index d2af24752b..4d09469858 100644 --- a/tools/ioemu/sdl.c +++ b/tools/ioemu/sdl.c @@ -508,6 +508,7 @@ void sdl_display_init(DisplayState *ds, int full_screen) ds->dpy_update = sdl_update; ds->dpy_resize = sdl_resize; ds->dpy_refresh = sdl_refresh; + ds->dpy_colourdepth = NULL; sdl_resize(ds, 640, 400); sdl_update_caption(); diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index 7885fbe3c0..01dfef8555 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -147,6 +147,7 @@ static DisplayState display_state; int nographic; int vncviewer; int vncunused; +int vncswitchbpp; const char* keyboard_layout = NULL; int64_t ticks_per_sec; char *boot_device = NULL; @@ -4420,6 +4421,7 @@ void dumb_display_init(DisplayState *ds) ds->depth = 0; ds->dpy_update = dumb_update; ds->dpy_resize = dumb_resize; + ds->dpy_colourdepth = NULL; ds->dpy_refresh = dumb_refresh; } @@ -6533,6 +6535,7 @@ void help(void) "-vnc display start a VNC server on display\n" "-vncviewer start a vncviewer process for this domain\n" "-vncunused bind the VNC server to an unused port\n" + "-vnc-switch-bpp VNC server closes connections when the guest OS changes colour depth\n" #ifndef NO_DAEMONIZE "-daemonize daemonize QEMU after initializing\n" #endif @@ -6634,6 +6637,7 @@ enum { QEMU_OPTION_acpi, QEMU_OPTION_vncviewer, QEMU_OPTION_vncunused, + QEMU_OPTION_vncswitchbpp, QEMU_OPTION_pci, }; @@ -6717,6 +6721,7 @@ const QEMUOption qemu_options[] = { { "vnc", HAS_ARG, QEMU_OPTION_vnc }, { "vncviewer", 0, QEMU_OPTION_vncviewer }, { "vncunused", 0, QEMU_OPTION_vncunused }, + { "vnc-switch-bpp", 0, QEMU_OPTION_vncswitchbpp }, /* temporary options */ { "usb", 0, QEMU_OPTION_usb }, @@ -7130,6 +7135,7 @@ int main(int argc, char **argv) nographic = 0; vncviewer = 0; vncunused = 0; + vncswitchbpp = 0; kernel_filename = NULL; kernel_cmdline = ""; #ifndef CONFIG_DM @@ -7560,6 +7566,9 @@ int main(int argc, char **argv) case QEMU_OPTION_vncunused: vncunused++; break; + case QEMU_OPTION_vncswitchbpp: + vncswitchbpp++; + break; case QEMU_OPTION_pci: direct_pci = optarg; break; @@ -7784,6 +7793,7 @@ int main(int argc, char **argv) } else if (vnc_display != NULL || vncunused != 0) { int vnc_display_port; char password[20]; + ds->switchbpp = vncswitchbpp; vnc_display_init(ds); xenstore_read_vncpasswd(domid, password, sizeof(password)); vnc_display_password(ds, password); diff --git a/tools/ioemu/vl.h b/tools/ioemu/vl.h index 9d78cd25d9..04d04845c5 100644 --- a/tools/ioemu/vl.h +++ b/tools/ioemu/vl.h @@ -912,8 +912,11 @@ struct DisplayState { int height; void *opaque; + int switchbpp; + void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h); void (*dpy_resize)(struct DisplayState *s, int w, int h); + void (*dpy_colourdepth)(struct DisplayState *s, int depth); void (*dpy_refresh)(struct DisplayState *s); void (*dpy_copy)(struct DisplayState *s, int src_x, int src_y, int dst_x, int dst_y, int w, int h); }; diff --git a/tools/ioemu/vnc.c b/tools/ioemu/vnc.c index df83f51650..7b6e633f7a 100644 --- a/tools/ioemu/vnc.c +++ b/tools/ioemu/vnc.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "vl.h" #include "qemu_socket.h" #include @@ -85,8 +86,8 @@ typedef void VncWritePixels(VncState *vs, void *data, int size); typedef void VncSendHextileTile(VncState *vs, int x, int y, int w, int h, - uint32_t *last_bg, - uint32_t *last_fg, + void *last_bg, + void *last_fg, int *has_bg, int *has_fg); #if 0 @@ -187,9 +188,9 @@ struct VncState VncWritePixels *write_pixels; VncSendHextileTile *send_hextile_tile; int pix_bpp, pix_big_endian; - int red_shift, red_max, red_shift1; - int green_shift, green_max, green_shift1; - int blue_shift, blue_max, blue_shift1; + int red_shift, red_max, red_shift1, red_max1; + int green_shift, green_max, green_shift1, green_max1; + int blue_shift, blue_max, blue_shift1, blue_max1; VncReadEvent *read_handler; size_t read_handler_expect; @@ -379,54 +380,67 @@ static void vnc_write_pixels_copy(VncState *vs, void *pixels, int size) /* slowest but generic code. */ static void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v) { - unsigned int r, g, b; + uint8_t r, g, b; - r = (v >> vs->red_shift1) & vs->red_max; - g = (v >> vs->green_shift1) & vs->green_max; - b = (v >> vs->blue_shift1) & vs->blue_max; - v = (r << vs->red_shift) | - (g << vs->green_shift) | - (b << vs->blue_shift); + r = ((v >> vs->red_shift1) & vs->red_max1) * (vs->red_max + 1) / (vs->red_max1 + 1); + g = ((v >> vs->green_shift1) & vs->green_max1) * (vs->green_max + 1) / (vs->green_max1 + 1); + b = ((v >> vs->blue_shift1) & vs->blue_max1) * (vs->blue_max + 1) / (vs->blue_max1 + 1); switch(vs->pix_bpp) { case 1: - buf[0] = v; + buf[0] = (r << vs->red_shift) | (g << vs->green_shift) | (b << vs->blue_shift); break; case 2: + { + uint16_t *p = (uint16_t *) buf; + *p = (r << vs->red_shift) | (g << vs->green_shift) | (b << vs->blue_shift); if (vs->pix_big_endian) { - buf[0] = v >> 8; - buf[1] = v; - } else { - buf[1] = v >> 8; - buf[0] = v; + *p = htons(*p); } + } break; default: case 4: + { + uint32_t *p = (uint32_t *) buf; + *p = (r << vs->red_shift) | (g << vs->green_shift) | (b << vs->blue_shift); if (vs->pix_big_endian) { - buf[0] = v >> 24; - buf[1] = v >> 16; - buf[2] = v >> 8; - buf[3] = v; - } else { - buf[3] = v >> 24; - buf[2] = v >> 16; - buf[1] = v >> 8; - buf[0] = v; + *p = htonl(*p); } break; } + } } static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size) { - uint32_t *pixels = pixels1; uint8_t buf[4]; - int n, i; - n = size >> 2; - for(i = 0; i < n; i++) { - vnc_convert_pixel(vs, buf, pixels[i]); - vnc_write(vs, buf, vs->pix_bpp); + if (vs->depth == 4) { + uint32_t *pixels = pixels1; + int n, i; + n = size >> 2; + for(i = 0; i < n; i++) { + vnc_convert_pixel(vs, buf, pixels[i]); + vnc_write(vs, buf, vs->pix_bpp); + } + } else if (vs->depth == 2) { + uint16_t *pixels = pixels1; + int n, i; + n = size >> 1; + for(i = 0; i < n; i++) { + vnc_convert_pixel(vs, buf, pixels[i]); + vnc_write(vs, buf, vs->pix_bpp); + } + } else if (vs->depth == 1) { + uint8_t *pixels = pixels1; + int n, i; + n = size; + for(i = 0; i < n; i++) { + vnc_convert_pixel(vs, buf, pixels[i]); + vnc_write(vs, buf, vs->pix_bpp); + } + } else { + fprintf(stderr, "vnc_write_pixels_generic: VncState color depth not supported\n"); } } @@ -462,6 +476,18 @@ static void hextile_enc_cord(uint8_t *ptr, int x, int y, int w, int h) #include "vnchextile.h" #undef BPP +#define GENERIC +#define BPP 8 +#include "vnchextile.h" +#undef BPP +#undef GENERIC + +#define GENERIC +#define BPP 16 +#include "vnchextile.h" +#undef BPP +#undef GENERIC + #define GENERIC #define BPP 32 #include "vnchextile.h" @@ -472,18 +498,22 @@ static void send_framebuffer_update_hextile(VncState *vs, int x, int y, int w, i { int i, j; int has_fg, has_bg; - uint32_t last_fg32, last_bg32; + void *last_fg, *last_bg; vnc_framebuffer_update(vs, x, y, w, h, 5); + last_fg = (void *) malloc(vs->depth); + last_bg = (void *) malloc(vs->depth); has_fg = has_bg = 0; for (j = y; j < (y + h); j += 16) { for (i = x; i < (x + w); i += 16) { vs->send_hextile_tile(vs, i, j, MIN(16, x + w - i), MIN(16, y + h - j), - &last_bg32, &last_fg32, &has_bg, &has_fg); + last_bg, last_fg, &has_bg, &has_fg); } } + free(last_fg); + free(last_bg); } static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h) @@ -1306,17 +1336,6 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings) check_pointer_type_change(vs, kbd_mouse_is_absolute()); } -static int compute_nbits(unsigned int val) -{ - int n; - n = 0; - while (val != 0) { - n++; - val >>= 1; - } - return n; -} - static void set_pixel_format(VncState *vs, int bits_per_pixel, int depth, int big_endian_flag, int true_color_flag, @@ -1335,23 +1354,24 @@ static void set_pixel_format(VncState *vs, vnc_client_error(vs); return; } - if (bits_per_pixel == 32 && + if (bits_per_pixel == 32 && + bits_per_pixel == vs->depth * 8 && host_big_endian_flag == big_endian_flag && red_max == 0xff && green_max == 0xff && blue_max == 0xff && red_shift == 16 && green_shift == 8 && blue_shift == 0) { - vs->depth = 4; vs->write_pixels = vnc_write_pixels_copy; vs->send_hextile_tile = send_hextile_tile_32; } else - if (bits_per_pixel == 16 && + if (bits_per_pixel == 16 && + bits_per_pixel == vs->depth * 8 && host_big_endian_flag == big_endian_flag && red_max == 31 && green_max == 63 && blue_max == 31 && red_shift == 11 && green_shift == 5 && blue_shift == 0) { - vs->depth = 2; vs->write_pixels = vnc_write_pixels_copy; vs->send_hextile_tile = send_hextile_tile_16; } else if (bits_per_pixel == 8 && + bits_per_pixel == vs->depth * 8 && red_max == 7 && green_max == 7 && blue_max == 3 && red_shift == 5 && green_shift == 2 && blue_shift == 0) { vs->depth = 1; @@ -1364,28 +1384,111 @@ static void set_pixel_format(VncState *vs, bits_per_pixel != 16 && bits_per_pixel != 32) goto fail; - vs->depth = 4; - vs->red_shift = red_shift; - vs->red_max = red_max; - vs->red_shift1 = 24 - compute_nbits(red_max); - vs->green_shift = green_shift; - vs->green_max = green_max; - vs->green_shift1 = 16 - compute_nbits(green_max); - vs->blue_shift = blue_shift; - vs->blue_max = blue_max; - vs->blue_shift1 = 8 - compute_nbits(blue_max); - vs->pix_bpp = bits_per_pixel / 8; + if (vs->depth == 4) { + vs->send_hextile_tile = send_hextile_tile_generic_32; + } else if (vs->depth == 2) { + vs->send_hextile_tile = send_hextile_tile_generic_16; + } else { + vs->send_hextile_tile = send_hextile_tile_generic_8; + } + vs->pix_big_endian = big_endian_flag; vs->write_pixels = vnc_write_pixels_generic; - vs->send_hextile_tile = send_hextile_tile_generic; } - - vnc_dpy_resize(vs->ds, vs->ds->width, vs->ds->height); + + vs->red_shift = red_shift; + vs->red_max = red_max; + vs->green_shift = green_shift; + vs->green_max = green_max; + vs->blue_shift = blue_shift; + vs->blue_max = blue_max; + vs->pix_bpp = bits_per_pixel / 8; vga_hw_invalidate(); vga_hw_update(); } +static void vnc_dpy_colourdepth(DisplayState *ds, int depth) +{ + int host_big_endian_flag; + struct VncState *vs; + + if (!depth) return; + +#ifdef WORDS_BIGENDIAN + host_big_endian_flag = 1; +#else + host_big_endian_flag = 0; +#endif + vs = ds->opaque; + + switch (depth) { + case 8: + vs->depth = depth / 8; + vs->red_max1 = 7; + vs->green_max1 = 7; + vs->blue_max1 = 3; + vs->red_shift1 = 5; + vs->green_shift1 = 2; + vs->blue_shift1 = 0; + break; + case 16: + vs->depth = depth / 8; + vs->red_max1 = 31; + vs->green_max1 = 63; + vs->blue_max1 = 31; + vs->red_shift1 = 11; + vs->green_shift1 = 5; + vs->blue_shift1 = 0; + break; + case 32: + vs->depth = 4; + vs->red_max1 = 255; + vs->green_max1 = 255; + vs->blue_max1 = 255; + vs->red_shift1 = 16; + vs->green_shift1 = 8; + vs->blue_shift1 = 0; + break; + default: + return; + } + if (ds->switchbpp) { + vnc_client_error(vs); + } else { + if (vs->pix_bpp == 4 && vs->depth == 4 && + host_big_endian_flag == vs->pix_big_endian && + vs->red_max == 0xff && vs->green_max == 0xff && vs->blue_max == 0xff && + vs->red_shift == 16 && vs->green_shift == 8 && vs->blue_shift == 0) { + vs->write_pixels = vnc_write_pixels_copy; + vs->send_hextile_tile = send_hextile_tile_32; + } else if (vs->pix_bpp == 2 && vs->depth == 2 && + host_big_endian_flag == vs->pix_big_endian && + vs->red_max == 31 && vs->green_max == 63 && vs->blue_max == 31 && + vs->red_shift == 11 && vs->green_shift == 5 && vs->blue_shift == 0) { + vs->write_pixels = vnc_write_pixels_copy; + vs->send_hextile_tile = send_hextile_tile_16; + } else if (vs->pix_bpp == 1 && vs->depth == 1 && + host_big_endian_flag == vs->pix_big_endian && + vs->red_max == 7 && vs->green_max == 7 && vs->blue_max == 3 && + vs->red_shift == 5 && vs->green_shift == 2 && vs->blue_shift == 0) { + vs->write_pixels = vnc_write_pixels_copy; + vs->send_hextile_tile = send_hextile_tile_8; + } else { + if (vs->depth == 4) { + vs->send_hextile_tile = send_hextile_tile_generic_32; + } else if (vs->depth == 2) { + vs->send_hextile_tile = send_hextile_tile_generic_16; + } else { + vs->send_hextile_tile = send_hextile_tile_generic_8; + } + vs->write_pixels = vnc_write_pixels_generic; + } + } + + vnc_dpy_resize(ds, ds->width, ds->height); +} + static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len) { int i; @@ -1483,7 +1586,9 @@ static int protocol_client_init(VncState *vs, uint8_t *data, size_t len) vnc_write_u16(vs, vs->ds->height); vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */ - vnc_write_u8(vs, vs->depth * 8); /* depth */ + if (vs->depth == 4) vnc_write_u8(vs, 24); /* depth */ + else vnc_write_u8(vs, vs->depth * 8); /* depth */ + #ifdef WORDS_BIGENDIAN vnc_write_u8(vs, 1); /* big-endian-flag */ #else @@ -2160,7 +2265,6 @@ void vnc_display_init(DisplayState *ds) vs->lsock = -1; vs->csock = -1; - vs->depth = 4; vs->last_x = -1; vs->last_y = -1; @@ -2177,9 +2281,12 @@ void vnc_display_init(DisplayState *ds) vs->ds->data = NULL; vs->ds->dpy_update = vnc_dpy_update; vs->ds->dpy_resize = vnc_dpy_resize; + vs->ds->dpy_colourdepth = vnc_dpy_colourdepth; vs->ds->dpy_refresh = vnc_dpy_refresh; - vnc_dpy_resize(vs->ds, 640, 400); + vs->ds->width = 640; + vs->ds->height = 400; + vnc_dpy_colourdepth(vs->ds, 32); } #if CONFIG_VNC_TLS diff --git a/tools/ioemu/vnchextile.h b/tools/ioemu/vnchextile.h index 3d894cd574..29b74840f5 100644 --- a/tools/ioemu/vnchextile.h +++ b/tools/ioemu/vnchextile.h @@ -2,29 +2,29 @@ #define CONCAT(a, b) CONCAT_I(a, b) #define pixel_t CONCAT(uint, CONCAT(BPP, _t)) #ifdef GENERIC -#define NAME generic +#define NAME CONCAT(generic_, BPP) #else #define NAME BPP #endif static void CONCAT(send_hextile_tile_, NAME)(VncState *vs, int x, int y, int w, int h, - uint32_t *last_bg32, - uint32_t *last_fg32, + void *last_bg_, + void *last_fg_, int *has_bg, int *has_fg) { uint8_t *row = (vs->ds->data + y * vs->ds->linesize + x * vs->depth); pixel_t *irow = (pixel_t *)row; int j, i; - pixel_t *last_bg = (pixel_t *)last_bg32; - pixel_t *last_fg = (pixel_t *)last_fg32; + pixel_t *last_bg = (pixel_t *)last_bg_; + pixel_t *last_fg = (pixel_t *)last_fg_; pixel_t bg = 0; pixel_t fg = 0; int n_colors = 0; int bg_count = 0; int fg_count = 0; int flags = 0; - uint8_t data[(sizeof(pixel_t) + 2) * 16 * 16]; + uint8_t data[(vs->pix_bpp + 2) * 16 * 16]; int n_data = 0; int n_subtiles = 0; -- cgit v1.2.3 From f029add7ef8d5a4d474263a3a83f84fd7873aca1 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Mon, 11 Feb 2008 15:59:49 +0000 Subject: Rendezvous selected cpus in softirq (stop_machine). This is similar to stop_machine_run stub from Linux, to pull selected cpus in rendezvous point and the do some batch work under a safe environment. Current one usage is from S3 path, where individual cpu is pulled down with related online footprints being cleared. It's dangerous to have other cpus checking clobbered data structure in the middle, such as cpu_online_map, cpu_sibling_map, etc. Signed-off-by: Kevin Tian Signed-off-by: Keir Fraser --- xen/arch/x86/cpu/mtrr/main.c | 2 - xen/arch/x86/domain.c | 3 +- xen/arch/x86/smpboot.c | 25 ++++-- xen/common/Makefile | 1 + xen/common/stop_machine.c | 168 +++++++++++++++++++++++++++++++++++++++++ xen/include/asm-x86/smp.h | 3 +- xen/include/xen/smp.h | 17 +++++ xen/include/xen/softirq.h | 3 +- xen/include/xen/stop_machine.h | 30 ++++++++ 9 files changed, 239 insertions(+), 13 deletions(-) create mode 100644 xen/common/stop_machine.c create mode 100644 xen/include/xen/stop_machine.h diff --git a/xen/arch/x86/cpu/mtrr/main.c b/xen/arch/x86/cpu/mtrr/main.c index 4881055d1a..2a606f0320 100644 --- a/xen/arch/x86/cpu/mtrr/main.c +++ b/xen/arch/x86/cpu/mtrr/main.c @@ -46,8 +46,6 @@ #define DEFINE_MUTEX(_m) DEFINE_SPINLOCK(_m) #define mutex_lock(_m) spin_lock(_m) #define mutex_unlock(_m) spin_unlock(_m) -#define lock_cpu_hotplug() ((void)0) -#define unlock_cpu_hotplug() ((void)0) #define dump_stack() ((void)0) #define get_cpu() smp_processor_id() #define put_cpu() do {} while(0) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 9d0537a9f9..25bc2c7148 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -82,7 +82,6 @@ static void default_idle(void) static void play_dead(void) { - __cpu_disable(); /* This must be done before dead CPU ack */ cpu_exit_clear(); hvm_cpu_down(); @@ -101,7 +100,7 @@ void idle_loop(void) { for ( ; ; ) { - if (cpu_is_offline(smp_processor_id())) + if ( cpu_is_offline(smp_processor_id()) ) play_dead(); page_scrub_schedule_work(); default_idle(); diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c index 32668e9455..914ec62689 100644 --- a/xen/arch/x86/smpboot.c +++ b/xen/arch/x86/smpboot.c @@ -54,6 +54,7 @@ #include #include #include +#include #define set_kernel_exec(x, y) (0) #define setup_trampoline() (bootsym_phys(trampoline_realmode_entry)) @@ -1208,6 +1209,15 @@ int __cpu_disable(void) if (cpu == 0) return -EBUSY; + /* + * Only S3 is using this path, and thus idle vcpus are running on all + * APs when we are called. To support full cpu hotplug, other + * notification mechanisms should be introduced (e.g., migrate vcpus + * off this physical cpu before rendezvous point). + */ + if (!is_idle_vcpu(current)) + return -EINVAL; + local_irq_disable(); clear_local_APIC(); /* Allow any queued timer interrupts to get serviced */ @@ -1244,6 +1254,11 @@ void __cpu_die(unsigned int cpu) printk(KERN_ERR "CPU %u didn't die...\n", cpu); } +static int take_cpu_down(void *unused) +{ + return __cpu_disable(); +} + /* * XXX: One important thing missed here is to migrate vcpus * from dead cpu to other online ones and then put whole @@ -1269,7 +1284,6 @@ void __cpu_die(unsigned int cpu) int cpu_down(unsigned int cpu) { int err = 0; - cpumask_t mask; spin_lock(&cpu_add_remove_lock); if (num_online_cpus() == 1) { @@ -1283,11 +1297,10 @@ int cpu_down(unsigned int cpu) } printk("Prepare to bring CPU%d down...\n", cpu); - /* Send notification to remote idle vcpu */ - cpus_clear(mask); - cpu_set(cpu, mask); - per_cpu(cpu_state, cpu) = CPU_DYING; - smp_send_event_check_mask(mask); + + err = __stop_machine_run(take_cpu_down, NULL, cpu); + if ( err < 0 ) + goto out; __cpu_die(cpu); diff --git a/xen/common/Makefile b/xen/common/Makefile index 1bf38310bf..631ac384bd 100644 --- a/xen/common/Makefile +++ b/xen/common/Makefile @@ -16,6 +16,7 @@ obj-y += sched_sedf.o obj-y += schedule.o obj-y += shutdown.o obj-y += softirq.o +obj-y += stop_machine.o obj-y += string.o obj-y += symbols.o obj-y += sysctl.o diff --git a/xen/common/stop_machine.c b/xen/common/stop_machine.c new file mode 100644 index 0000000000..b109167ef7 --- /dev/null +++ b/xen/common/stop_machine.c @@ -0,0 +1,168 @@ +/****************************************************************************** + * common/stop_machine.c + * + * Facilities to put whole machine in a safe 'stop' state + * + * Copyright 2005 Rusty Russell rusty@rustcorp.com.au IBM Corporation + * Copyright 2008 Kevin Tian , Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +enum stopmachine_state { + STOPMACHINE_START, + STOPMACHINE_PREPARE, + STOPMACHINE_DISABLE_IRQ, + STOPMACHINE_INVOKE, + STOPMACHINE_EXIT +}; + +struct stopmachine_data { + unsigned int nr_cpus; + + enum stopmachine_state state; + atomic_t done; + + unsigned int fn_cpu; + int fn_result; + int (*fn)(void *); + void *fn_data; +}; + +static struct stopmachine_data stopmachine_data; +static DEFINE_SPINLOCK(stopmachine_lock); + +static void stopmachine_set_state(enum stopmachine_state state) +{ + atomic_set(&stopmachine_data.done, 0); + smp_wmb(); + stopmachine_data.state = state; + while ( atomic_read(&stopmachine_data.done) != stopmachine_data.nr_cpus ) + cpu_relax(); +} + +int __stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu) +{ + cpumask_t allbutself; + unsigned int i, nr_cpus; + int ret; + + BUG_ON(!local_irq_is_enabled()); + + allbutself = cpu_online_map; + cpu_clear(smp_processor_id(), allbutself); + nr_cpus = cpus_weight(allbutself); + + if ( nr_cpus == 0 ) + { + BUG_ON(cpu != smp_processor_id()); + return (*fn)(data); + } + + /* Note: We shouldn't spin on lock when it's held by others since others + * is expecting this cpus to enter softirq context. Or else deadlock + * is caused. + */ + if ( !spin_trylock(&stopmachine_lock) ) + return -EBUSY; + + stopmachine_data.fn = fn; + stopmachine_data.fn_data = data; + stopmachine_data.nr_cpus = nr_cpus; + stopmachine_data.fn_cpu = cpu; + atomic_set(&stopmachine_data.done, 0); + stopmachine_data.state = STOPMACHINE_START; + + smp_wmb(); + + for_each_cpu_mask ( i, allbutself ) + cpu_raise_softirq(i, STOPMACHINE_SOFTIRQ); + + stopmachine_set_state(STOPMACHINE_PREPARE); + + local_irq_disable(); + stopmachine_set_state(STOPMACHINE_DISABLE_IRQ); + + if ( cpu == smp_processor_id() ) + stopmachine_data.fn_result = (*fn)(data); + stopmachine_set_state(STOPMACHINE_INVOKE); + ret = stopmachine_data.fn_result; + + stopmachine_set_state(STOPMACHINE_EXIT); + local_irq_enable(); + + spin_unlock(&stopmachine_lock); + + return ret; +} + +int stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu) +{ + int ret; + + lock_cpu_hotplug(); + ret = __stop_machine_run(fn, data, cpu); + unlock_cpu_hotplug(); + + return ret; +} + +static void stopmachine_softirq(void) +{ + enum stopmachine_state state = STOPMACHINE_START; + + smp_mb(); + + while ( state != STOPMACHINE_EXIT ) + { + while ( stopmachine_data.state == state ) + cpu_relax(); + + state = stopmachine_data.state; + switch ( state ) + { + case STOPMACHINE_DISABLE_IRQ: + local_irq_disable(); + break; + case STOPMACHINE_INVOKE: + if ( stopmachine_data.fn_cpu == smp_processor_id() ) + stopmachine_data.fn_result = + stopmachine_data.fn(stopmachine_data.fn_data); + break; + default: + break; + } + + smp_mb(); + atomic_inc(&stopmachine_data.done); + } + + local_irq_enable(); +} + +static int __init cpu_stopmachine_init(void) +{ + open_softirq(STOPMACHINE_SOFTIRQ, stopmachine_softirq); + return 0; +} +__initcall(cpu_stopmachine_init); diff --git a/xen/include/asm-x86/smp.h b/xen/include/asm-x86/smp.h index 55b8cf7705..cf5159603d 100644 --- a/xen/include/asm-x86/smp.h +++ b/xen/include/asm-x86/smp.h @@ -51,12 +51,11 @@ extern u8 x86_cpu_to_apicid[]; /* State of each CPU. */ #define CPU_ONLINE 0x0002 /* CPU is up */ -#define CPU_DYING 0x0003 /* CPU is requested to die */ #define CPU_DEAD 0x0004 /* CPU is dead */ DECLARE_PER_CPU(int, cpu_state); #ifdef CONFIG_HOTPLUG_CPU -#define cpu_is_offline(cpu) unlikely(per_cpu(cpu_state,cpu) == CPU_DYING) +#define cpu_is_offline(cpu) unlikely(!cpu_online(cpu)) extern int cpu_down(unsigned int cpu); extern int cpu_up(unsigned int cpu); extern void cpu_exit_clear(void); diff --git a/xen/include/xen/smp.h b/xen/include/xen/smp.h index c02ecd4dc3..3e7de77ec8 100644 --- a/xen/include/xen/smp.h +++ b/xen/include/xen/smp.h @@ -112,4 +112,21 @@ static inline int on_each_cpu( #define smp_processor_id() raw_smp_processor_id() +#ifdef CONFIG_HOTPLUG_CPU +extern spinlock_t cpu_add_remove_lock; +/* + * FIXME: need a better lock mechanism when real cpu hotplug is later + * supported, since spinlock may cause dead lock: + * cpu0: in stop_machine with lock held. Wait for cpu1 to respond + * to stop request + * cpu1: spin loop on lock upon cpu hotplug request from guest, + * without chance to handle softirq + * ... + */ +#define lock_cpu_hotplug() spin_lock(&cpu_add_remove_lock); +#define unlock_cpu_hotplug() spin_unlock(&cpu_add_remove_lock); +#else +#define lock_cpu_hotplug() do { } while ( 0 ) +#define unlock_cpu_hotplug() do { } while ( 0 ) +#endif #endif diff --git a/xen/include/xen/softirq.h b/xen/include/xen/softirq.h index 9a66e0fb03..7734b3374d 100644 --- a/xen/include/xen/softirq.h +++ b/xen/include/xen/softirq.h @@ -10,8 +10,9 @@ #define PAGE_SCRUB_SOFTIRQ 5 #define TRACE_SOFTIRQ 6 #define RCU_SOFTIRQ 7 +#define STOPMACHINE_SOFTIRQ 8 -#define NR_COMMON_SOFTIRQS 8 +#define NR_COMMON_SOFTIRQS 9 #include diff --git a/xen/include/xen/stop_machine.h b/xen/include/xen/stop_machine.h new file mode 100644 index 0000000000..f379f6705a --- /dev/null +++ b/xen/include/xen/stop_machine.h @@ -0,0 +1,30 @@ +#ifndef __XEN_STOP_MACHINE_H__ +#define __XEN_STOP_MACHINE_H__ + +/** + * stop_machine_run: freeze the machine on all CPUs and run this function + * @fn: the function to run + * @data: the data ptr for the @fn() + * @cpu: the cpu to run @fn() on (or any, if @cpu == NR_CPUS). + * + * Description: This causes every other cpu to enter a safe point, with + * each of which disables interrupts, and finally interrupts are disabled + * on the current CPU. The result is that none is holding a spinlock + * or inside any other preempt-disabled region when @fn() runs. + * + * This can be thought of as a very heavy write lock, equivalent to + * grabbing every spinlock in the kernel. */ +int stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu); + +/** + * __stop_machine_run: freeze the machine on all CPUs and run this function + * @fn: the function to run + * @data: the data ptr for the @fn + * @cpu: the cpu to run @fn on (or any, if @cpu == NR_CPUS. + * + * Description: This is a special version of the above, without explicit + * lock acquisition. Used by hotplug cpu. + */ +int __stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu); + +#endif /* __XEN_STOP_MACHINE_H__ */ -- cgit v1.2.3 From 2bba474f8f2ce5e16919f1c98219237fbbbb3520 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Tue, 12 Feb 2008 10:16:20 +0000 Subject: Add timestamp option to xenconsoled Similar to the --log option, --timestamp or -t takes: - none : No timestamping - hv : Timestamp hypervisor logs - guest: Timestamp guest logs - all : Timestamp guest and hypervisor logs From: Cole Robinson Signed-off-by: Keir Fraser --- tools/console/daemon/io.c | 90 ++++++++++++++++++++++++++++++++++++++++----- tools/console/daemon/main.c | 20 +++++++++- 2 files changed, 99 insertions(+), 11 deletions(-) diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c index 735a77b0e6..52df19ed34 100644 --- a/tools/console/daemon/io.c +++ b/tools/console/daemon/io.c @@ -60,6 +60,8 @@ extern int log_reload; extern int log_guest; extern int log_hv; +extern int log_time_hv; +extern int log_time_guest; extern char *log_dir; static int log_hv_fd = -1; @@ -99,6 +101,50 @@ struct domain static struct domain *dom_head; +static int write_all(int fd, const char* buf, size_t len) +{ + while (len) { + ssize_t ret = write(fd, buf, len); + if (ret == -1 && errno == EINTR) + continue; + if (ret <= 0) + return -1; + len -= ret; + buf += ret; + } + + return 0; +} + +static int write_with_timestamp(int fd, const char *data, size_t sz) +{ + char buf[sz+1]; + char ts[32]; + time_t now = time(NULL); + const struct tm *tmnow = localtime(&now); + size_t tslen = strftime(ts, sizeof(ts), "[%d-%m-%Y %H:%M:%S] ", tmnow); + + memcpy(buf, data, sz); + while (sz > 0 && buf[sz-1] == '\r') + sz--; // Don't print trailing \r's + if (sz > 0 && buf[sz-1] != '\n') + buf[sz++] = '\n'; // Force ending newline + data = buf; + + while (sz > 0) { + const char *nl = strchr(data, '\n') + 1; + size_t towrite = nl - data; + if (write_all(fd, ts, tslen) < 0) + return -1; + if (write_all(fd, data, towrite)) + return -1; + sz -= towrite; + data = nl; + } + + return 0; +} + static void buffer_append(struct domain *dom) { struct buffer *buffer = &dom->buffer; @@ -135,10 +181,13 @@ static void buffer_append(struct domain *dom) * and handle_tty_write will stop being called. */ if (dom->log_fd != -1) { - int len = write(dom->log_fd, - buffer->data + buffer->size - size, - size); - if (len < 0) + int logret; + if (log_time_guest) { + logret = write_with_timestamp(dom->log_fd, buffer->data + buffer->size - size, size); + } else { + logret = write_all(dom->log_fd, buffer->data + buffer->size - size, size); + } + if (logret < 0) dolog(LOG_ERR, "Write to log failed on domain %d: %d (%s)\n", dom->domid, errno, strerror(errno)); } @@ -195,6 +244,15 @@ static int create_hv_log(void) if (fd == -1) dolog(LOG_ERR, "Failed to open log %s: %d (%s)", logfile, errno, strerror(errno)); + if (fd != -1 && log_time_hv) { + if (write_with_timestamp(fd, "Logfile Opened", + strlen("Logfile Opened")) < 0) { + dolog(LOG_ERR, "Failed to log opening timestamp " + "in %s: %d (%s)", logfile, errno, + strerror(errno)); + return -1; + } + } return fd; } @@ -229,6 +287,15 @@ static int create_domain_log(struct domain *dom) if (fd == -1) dolog(LOG_ERR, "Failed to open log %s: %d (%s)", logfile, errno, strerror(errno)); + if (fd != -1 && log_time_guest) { + if (write_with_timestamp(fd, "Logfile Opened", + strlen("Logfile Opened")) < 0) { + dolog(LOG_ERR, "Failed to log opening timestamp " + "in %s: %d (%s)", logfile, errno, + strerror(errno)); + return -1; + } + } return fd; } @@ -817,11 +884,16 @@ static void handle_hv_logs(void) if ((port = xc_evtchn_pending(xce_handle)) == -1) return; - if (xc_readconsolering(xc_handle, &bufptr, &size, 0, 1, &index) == 0) { - int len = write(log_hv_fd, buffer, size); - if (len < 0) - dolog(LOG_ERR, "Failed to write hypervisor log: %d (%s)", - errno, strerror(errno)); + if (xc_readconsolering(xc_handle, &bufptr, &size, 0, 1, &index) == 0 && size > 0) { + int logret; + if (log_time_guest) + logret = write_with_timestamp(log_hv_fd, buffer, size); + else + logret = write_all(log_hv_fd, buffer, size); + + if (logret < 0) + dolog(LOG_ERR, "Failed to write hypervisor log: " + "%d (%s)", errno, strerror(errno)); } (void)xc_evtchn_unmask(xce_handle, port); diff --git a/tools/console/daemon/main.c b/tools/console/daemon/main.c index ea0648f400..c66642ff46 100644 --- a/tools/console/daemon/main.c +++ b/tools/console/daemon/main.c @@ -35,6 +35,8 @@ int log_reload = 0; int log_guest = 0; int log_hv = 0; +int log_time_hv = 0; +int log_time_guest = 0; char *log_dir = NULL; static void handle_hup(int sig) @@ -44,7 +46,7 @@ static void handle_hup(int sig) static void usage(char *name) { - printf("Usage: %s [-h] [-V] [-v] [-i] [--log=none|guest|hv|all] [--log-dir=DIR] [--pid-file=PATH]\n", name); + printf("Usage: %s [-h] [-V] [-v] [-i] [--log=none|guest|hv|all] [--log-dir=DIR] [--pid-file=PATH] [-t, --timestamp=none|guest|hv|all]\n", name); } static void version(char *name) @@ -54,7 +56,7 @@ static void version(char *name) int main(int argc, char **argv) { - const char *sopts = "hVvi"; + const char *sopts = "hVvit:"; struct option lopts[] = { { "help", 0, 0, 'h' }, { "version", 0, 0, 'V' }, @@ -63,6 +65,7 @@ int main(int argc, char **argv) { "log", 1, 0, 'l' }, { "log-dir", 1, 0, 'r' }, { "pid-file", 1, 0, 'p' }, + { "timestamp", 1, 0, 't' }, { 0 }, }; bool is_interactive = false; @@ -103,6 +106,19 @@ int main(int argc, char **argv) case 'p': pidfile = strdup(optarg); break; + case 't': + if (!strcmp(optarg, "all")) { + log_time_hv = 1; + log_time_guest = 1; + } else if (!strcmp(optarg, "hv")) { + log_time_hv = 1; + } else if (!strcmp(optarg, "guest")) { + log_time_guest = 1; + } else if (!strcmp(optarg, "none")) { + log_time_guest = 0; + log_time_hv = 0; + } + break; case '?': fprintf(stderr, "Try `%s --help' for more information\n", -- cgit v1.2.3 From 5c22e77bb7a925056a111a73ce7ea3c3c5491ca9 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Tue, 12 Feb 2008 10:19:12 +0000 Subject: xend: Remove redundant check of maximum memory size. Currently, a wrong value of maximum memory size is checked by _safe_set_memory() and _memory_sanity_check(). Signed-off-by: Masaki Kanno --- tools/python/xen/xend/XendDomainInfo.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 7c8e0975a4..c1cb6aa998 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -707,9 +707,6 @@ class XendDomainInfo: log.debug("Setting memory maximum of domain %s (%s) to %d MiB.", self.info['name_label'], str(self.domid), limit) - if limit <= 0: - raise XendError('Invalid memory size') - MiB = 1024 * 1024 self._safe_set_memory('memory_static_max', limit * MiB) -- cgit v1.2.3 From b3a389fdfc3a1fe19fd7094b0180e97d49c186dd Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Tue, 12 Feb 2008 10:57:49 +0000 Subject: device-dm: Use SIGHUP before SIGKILL Make qemu unblock SIGHUP and make sure the default handler is in place. Have the domain killer send SIGHUP to the device-model script, allow the script 10s to clean up, and if still not dead, send SIGKILL. Signed-off-by: Samuel Thibault --- tools/ioemu/vl.c | 6 ++++-- tools/python/xen/xend/image.py | 17 ++++++++++++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index 01dfef8555..452bfcc555 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -7928,11 +7928,13 @@ int main(int argc, char **argv) } #endif - /* Unblock SIGTERM, which may have been blocked by the caller */ + /* Unblock SIGTERM and SIGHUP, which may have been blocked by the caller */ + signal(SIGHUP, SIG_DFL); sigemptyset(&set); sigaddset(&set, SIGTERM); + sigaddset(&set, SIGHUP); if (sigprocmask(SIG_UNBLOCK, &set, NULL) == -1) - fprintf(stderr, "Failed to unblock SIGTERM\n"); + fprintf(stderr, "Failed to unblock SIGTERM and SIGHUP\n"); main_loop(); quit_timers(); diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py index 4ceb36194f..069cde7dbe 100644 --- a/tools/python/xen/xend/image.py +++ b/tools/python/xen/xend/image.py @@ -335,16 +335,27 @@ class ImageHandler: return if self.pid: try: - os.kill(self.pid, signal.SIGKILL) + os.kill(self.pid, signal.SIGHUP) except OSError, exn: log.exception(exn) try: - os.waitpid(self.pid, 0) + # Try to reap the child every 100ms for 10s. Then SIGKILL it. + for i in xrange(100): + (p, rv) = os.waitpid(self.pid, os.WNOHANG) + if p == self.pid: + break + time.sleep(0.1) + else: + log.warning("DeviceModel %d took more than 10s " + "to terminate: sending SIGKILL" % self.pid) + os.kill(self.pid, signal.SIGKILL) + os.waitpid(self.pid, 0) except OSError, exn: # This is expected if Xend has been restarted within the # life of this domain. In this case, we can kill the process, # but we can't wait for it because it's not our child. - pass + # We just make really sure it's going away (SIGKILL) first. + os.kill(self.pid, signal.SIGKILL) self.pid = None state = xstransact.Remove("/local/domain/0/device-model/%i" % self.vm.getDomid()) -- cgit v1.2.3 From 67bfbd67d1311a1a590b47e568a07622d4492873 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Tue, 12 Feb 2008 11:37:45 +0000 Subject: libxenctrl headers should not pollute macro namespace with mb/rmb/wmb. Instead add a xen_ prefix. Modify Xen's public headers to expect the prefixed names instead of bare mb/rmb/wmb, but gate this expectation on a bump of __XEN_INTERFACE_VERSION__. Signed-off-by: Keir Fraser --- tools/blktap/drivers/tapdisk.c | 2 +- tools/console/daemon/io.c | 8 ++++---- tools/fs-back/fs-backend.c | 4 ++-- tools/ioemu/hw/xen_console.c | 8 ++++---- tools/ioemu/hw/xenfb.c | 8 ++++---- tools/ioemu/target-i386-dm/helper2.c | 6 +++--- tools/libxc/xenctrl.h | 25 ++++++++++++------------- tools/xenmon/xenbaked.c | 4 ++-- tools/xenstore/xenstored_domain.c | 8 ++++---- tools/xentrace/xentrace.c | 6 +++--- xen/include/public/io/ring.h | 24 ++++++++++++++++-------- xen/include/public/xen-compat.h | 2 +- 12 files changed, 56 insertions(+), 49 deletions(-) diff --git a/tools/blktap/drivers/tapdisk.c b/tools/blktap/drivers/tapdisk.c index 993e09b155..75f06c701c 100644 --- a/tools/blktap/drivers/tapdisk.c +++ b/tools/blktap/drivers/tapdisk.c @@ -641,7 +641,7 @@ static void get_io_request(struct td_state *s) if (!run) return; /*We have received signal to close*/ rp = info->fe_ring.sring->req_prod; - rmb(); + xen_rmb(); for (j = info->fe_ring.req_cons; j != rp; j++) { int done = 0, start_seg = 0; diff --git a/tools/console/daemon/io.c b/tools/console/daemon/io.c index 52df19ed34..9573333c08 100644 --- a/tools/console/daemon/io.c +++ b/tools/console/daemon/io.c @@ -153,7 +153,7 @@ static void buffer_append(struct domain *dom) cons = intf->out_cons; prod = intf->out_prod; - mb(); + xen_mb(); size = prod - cons; if ((size == 0) || (size > sizeof(intf->out))) @@ -172,7 +172,7 @@ static void buffer_append(struct domain *dom) buffer->data[buffer->size++] = intf->out[ MASK_XENCONS_IDX(cons++, intf->out)]; - mb(); + xen_mb(); intf->out_cons = cons; xc_evtchn_notify(dom->xce_handle, dom->local_port); @@ -750,7 +750,7 @@ static int ring_free_bytes(struct domain *dom) cons = intf->in_cons; prod = intf->in_prod; - mb(); + xen_mb(); space = prod - cons; if (space > sizeof(intf->in)) @@ -797,7 +797,7 @@ static void handle_tty_read(struct domain *dom) intf->in[MASK_XENCONS_IDX(prod++, intf->in)] = msg[i]; } - wmb(); + xen_wmb(); intf->in_prod = prod; xc_evtchn_notify(dom->xce_handle, dom->local_port); } else { diff --git a/tools/fs-back/fs-backend.c b/tools/fs-back/fs-backend.c index 634d5fa31e..fd5ba2b46b 100644 --- a/tools/fs-back/fs-backend.c +++ b/tools/fs-back/fs-backend.c @@ -140,8 +140,8 @@ void* handle_mount(void *data) handle_aio_events(mount); moretodo: rp = mount->ring.sring->req_prod; - rmb(); /* Ensure we see queued requests up to 'rp'. */ - + xen_rmb(); /* Ensure we see queued requests up to 'rp'. */ + while ((cons = mount->ring.req_cons) != rp) { int i; diff --git a/tools/ioemu/hw/xen_console.c b/tools/ioemu/hw/xen_console.c index 76aca8f3ee..44f8bcca48 100644 --- a/tools/ioemu/hw/xen_console.c +++ b/tools/ioemu/hw/xen_console.c @@ -75,7 +75,7 @@ static void buffer_append(struct domain *dom) cons = intf->out_cons; prod = intf->out_prod; - mb(); + xen_mb(); size = prod - cons; if ((size == 0) || (size > sizeof(intf->out))) @@ -94,7 +94,7 @@ static void buffer_append(struct domain *dom) buffer->data[buffer->size++] = intf->out[ MASK_XENCONS_IDX(cons++, intf->out)]; - mb(); + xen_mb(); intf->out_cons = cons; xc_evtchn_notify(dom->xce_handle, dom->local_port); @@ -289,7 +289,7 @@ static int ring_free_bytes(struct domain *dom) cons = intf->in_cons; prod = intf->in_prod; - mb(); + xen_mb(); space = prod - cons; if (space > sizeof(intf->in)) @@ -322,7 +322,7 @@ static void xencons_receive(void *opaque, const uint8_t *buf, int len) intf->in[MASK_XENCONS_IDX(prod++, intf->in)] = buf[i]; } - wmb(); + xen_wmb(); intf->in_prod = prod; xc_evtchn_notify(dom->xce_handle, dom->local_port); } diff --git a/tools/ioemu/hw/xenfb.c b/tools/ioemu/hw/xenfb.c index f0d7f7936e..5418986178 100644 --- a/tools/ioemu/hw/xenfb.c +++ b/tools/ioemu/hw/xenfb.c @@ -485,7 +485,7 @@ static void xenfb_on_fb_event(struct xenfb *xenfb) prod = page->out_prod; if (prod == page->out_cons) return; - rmb(); /* ensure we see ring contents up to prod */ + xen_rmb(); /* ensure we see ring contents up to prod */ for (cons = page->out_cons; cons != prod; cons++) { union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons); int x, y, w, h; @@ -512,7 +512,7 @@ static void xenfb_on_fb_event(struct xenfb *xenfb) break; } } - mb(); /* ensure we're done with ring contents */ + xen_mb(); /* ensure we're done with ring contents */ page->out_cons = cons; xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port); } @@ -571,9 +571,9 @@ static int xenfb_kbd_event(struct xenfb *xenfb, return -1; } - mb(); /* ensure ring space available */ + xen_mb(); /* ensure ring space available */ XENKBD_IN_RING_REF(page, prod) = *event; - wmb(); /* ensure ring contents visible */ + xen_wmb(); /* ensure ring contents visible */ page->in_prod = prod + 1; return xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port); } diff --git a/tools/ioemu/target-i386-dm/helper2.c b/tools/ioemu/target-i386-dm/helper2.c index d45ac7a999..4896b11ab8 100644 --- a/tools/ioemu/target-i386-dm/helper2.c +++ b/tools/ioemu/target-i386-dm/helper2.c @@ -218,7 +218,7 @@ static ioreq_t *__cpu_get_ioreq(int vcpu) return NULL; } - rmb(); /* see IOREQ_READY /then/ read contents of ioreq */ + xen_rmb(); /* see IOREQ_READY /then/ read contents of ioreq */ req->state = STATE_IOREQ_INPROCESS; return req; @@ -568,7 +568,7 @@ void __handle_buffered_iopage(CPUState *env) __handle_ioreq(env, &req); - mb(); + xen_mb(); buffered_io_page->read_pointer += qw ? 2 : 1; } } @@ -603,7 +603,7 @@ void cpu_handle_ioreq(void *opaque) return; } - wmb(); /* Update ioreq contents /then/ update state. */ + xen_wmb(); /* Update ioreq contents /then/ update state. */ /* * We do this before we send the response so that the tools diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index b9e9abd249..afc80a36df 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -43,22 +43,21 @@ */ #if defined(__i386__) -#define mb() __asm__ __volatile__ ( "lock; addl $0,0(%%esp)" : : : "memory" ) -#define rmb() __asm__ __volatile__ ( "lock; addl $0,0(%%esp)" : : : "memory" ) -#define wmb() __asm__ __volatile__ ( "" : : : "memory") +#define xen_mb() asm volatile ( "lock; addl $0,0(%%esp)" : : : "memory" ) +#define xen_rmb() asm volatile ( "lock; addl $0,0(%%esp)" : : : "memory" ) +#define xen_wmb() asm volatile ( "" : : : "memory") #elif defined(__x86_64__) -#define mb() __asm__ __volatile__ ( "mfence" : : : "memory") -#define rmb() __asm__ __volatile__ ( "lfence" : : : "memory") -#define wmb() __asm__ __volatile__ ( "" : : : "memory") +#define xen_mb() asm volatile ( "mfence" : : : "memory") +#define xen_rmb() asm volatile ( "lfence" : : : "memory") +#define xen_wmb() asm volatile ( "" : : : "memory") #elif defined(__ia64__) -#define mb() __asm__ __volatile__ ("mf" ::: "memory") -#define rmb() __asm__ __volatile__ ("mf" ::: "memory") -#define wmb() __asm__ __volatile__ ("mf" ::: "memory") +#define xen_mb() asm volatile ("mf" ::: "memory") +#define xen_rmb() asm volatile ("mf" ::: "memory") +#define xen_wmb() asm volatile ("mf" ::: "memory") #elif defined(__powerpc__) -/* XXX loosen these up later */ -#define mb() __asm__ __volatile__ ("sync" : : : "memory") -#define rmb() __asm__ __volatile__ ("sync" : : : "memory") /* lwsync? */ -#define wmb() __asm__ __volatile__ ("sync" : : : "memory") /* eieio? */ +#define xen_mb() asm volatile ("sync" : : : "memory") +#define xen_rmb() asm volatile ("sync" : : : "memory") /* lwsync? */ +#define xen_wmb() asm volatile ("sync" : : : "memory") /* eieio? */ #else #error "Define barriers" #endif diff --git a/tools/xenmon/xenbaked.c b/tools/xenmon/xenbaked.c index 728f14b753..32ca9f36c3 100644 --- a/tools/xenmon/xenbaked.c +++ b/tools/xenmon/xenbaked.c @@ -511,10 +511,10 @@ int monitor_tbufs(void) { while ( meta[i]->cons != meta[i]->prod ) { - rmb(); /* read prod, then read item. */ + xen_rmb(); /* read prod, then read item. */ rec_size = process_record( i, (struct t_rec *)(data[i] + meta[i]->cons % data_size)); - mb(); /* read item, then update cons. */ + xen_mb(); /* read item, then update cons. */ meta[i]->cons += rec_size; } } diff --git a/tools/xenstore/xenstored_domain.c b/tools/xenstore/xenstored_domain.c index 2cc9881eb4..d1d59f9f6f 100644 --- a/tools/xenstore/xenstored_domain.c +++ b/tools/xenstore/xenstored_domain.c @@ -112,7 +112,7 @@ static int writechn(struct connection *conn, /* Must read indexes once, and before anything else, and verified. */ cons = intf->rsp_cons; prod = intf->rsp_prod; - mb(); + xen_mb(); if (!check_indexes(cons, prod)) { errno = EIO; @@ -124,7 +124,7 @@ static int writechn(struct connection *conn, len = avail; memcpy(dest, data, len); - mb(); + xen_mb(); intf->rsp_prod += len; xc_evtchn_notify(xce_handle, conn->domain->port); @@ -142,7 +142,7 @@ static int readchn(struct connection *conn, void *data, unsigned int len) /* Must read indexes once, and before anything else, and verified. */ cons = intf->req_cons; prod = intf->req_prod; - mb(); + xen_mb(); if (!check_indexes(cons, prod)) { errno = EIO; @@ -154,7 +154,7 @@ static int readchn(struct connection *conn, void *data, unsigned int len) len = avail; memcpy(data, src, len); - mb(); + xen_mb(); intf->req_cons += len; xc_evtchn_notify(xce_handle, conn->domain->port); diff --git a/tools/xentrace/xentrace.c b/tools/xentrace/xentrace.c index 0879576645..7f394d2af0 100644 --- a/tools/xentrace/xentrace.c +++ b/tools/xentrace/xentrace.c @@ -384,8 +384,8 @@ int monitor_tbufs(int outfd) /* Read window information only once. */ cons = meta[i]->cons; prod = meta[i]->prod; - rmb(); /* read prod, then read item. */ - + xen_rmb(); /* read prod, then read item. */ + if ( cons == prod ) continue; @@ -428,7 +428,7 @@ int monitor_tbufs(int outfd) outfd); } - mb(); /* read buffer, then update cons. */ + xen_mb(); /* read buffer, then update cons. */ meta[i]->cons = prod; } diff --git a/xen/include/public/io/ring.h b/xen/include/public/io/ring.h index 355eba5545..6ce1d0d485 100644 --- a/xen/include/public/io/ring.h +++ b/xen/include/public/io/ring.h @@ -27,6 +27,14 @@ #ifndef __XEN_PUBLIC_IO_RING_H__ #define __XEN_PUBLIC_IO_RING_H__ +#include "../xen-compat.h" + +#if __XEN_INTERFACE_VERSION__ < 0x00030208 +#define xen_mb() mb() +#define xen_rmb() rmb() +#define xen_wmb() wmb() +#endif + typedef unsigned int RING_IDX; /* Round a 32-bit unsigned constant down to the nearest power of two. */ @@ -211,12 +219,12 @@ typedef struct __name##_back_ring __name##_back_ring_t (((_cons) - (_r)->rsp_prod_pvt) >= RING_SIZE(_r)) #define RING_PUSH_REQUESTS(_r) do { \ - wmb(); /* back sees requests /before/ updated producer index */ \ + xen_wmb(); /* back sees requests /before/ updated producer index */ \ (_r)->sring->req_prod = (_r)->req_prod_pvt; \ } while (0) #define RING_PUSH_RESPONSES(_r) do { \ - wmb(); /* front sees responses /before/ updated producer index */ \ + xen_wmb(); /* front sees resps /before/ updated producer index */ \ (_r)->sring->rsp_prod = (_r)->rsp_prod_pvt; \ } while (0) @@ -253,9 +261,9 @@ typedef struct __name##_back_ring __name##_back_ring_t #define RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(_r, _notify) do { \ RING_IDX __old = (_r)->sring->req_prod; \ RING_IDX __new = (_r)->req_prod_pvt; \ - wmb(); /* back sees requests /before/ updated producer index */ \ + xen_wmb(); /* back sees requests /before/ updated producer index */ \ (_r)->sring->req_prod = __new; \ - mb(); /* back sees new requests /before/ we check req_event */ \ + xen_mb(); /* back sees new requests /before/ we check req_event */ \ (_notify) = ((RING_IDX)(__new - (_r)->sring->req_event) < \ (RING_IDX)(__new - __old)); \ } while (0) @@ -263,9 +271,9 @@ typedef struct __name##_back_ring __name##_back_ring_t #define RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(_r, _notify) do { \ RING_IDX __old = (_r)->sring->rsp_prod; \ RING_IDX __new = (_r)->rsp_prod_pvt; \ - wmb(); /* front sees responses /before/ updated producer index */ \ + xen_wmb(); /* front sees resps /before/ updated producer index */ \ (_r)->sring->rsp_prod = __new; \ - mb(); /* front sees new responses /before/ we check rsp_event */ \ + xen_mb(); /* front sees new resps /before/ we check rsp_event */ \ (_notify) = ((RING_IDX)(__new - (_r)->sring->rsp_event) < \ (RING_IDX)(__new - __old)); \ } while (0) @@ -274,7 +282,7 @@ typedef struct __name##_back_ring __name##_back_ring_t (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r); \ if (_work_to_do) break; \ (_r)->sring->req_event = (_r)->req_cons + 1; \ - mb(); \ + xen_mb(); \ (_work_to_do) = RING_HAS_UNCONSUMED_REQUESTS(_r); \ } while (0) @@ -282,7 +290,7 @@ typedef struct __name##_back_ring __name##_back_ring_t (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \ if (_work_to_do) break; \ (_r)->sring->rsp_event = (_r)->rsp_cons + 1; \ - mb(); \ + xen_mb(); \ (_work_to_do) = RING_HAS_UNCONSUMED_RESPONSES(_r); \ } while (0) diff --git a/xen/include/public/xen-compat.h b/xen/include/public/xen-compat.h index c9f369f0e9..c2894990cd 100644 --- a/xen/include/public/xen-compat.h +++ b/xen/include/public/xen-compat.h @@ -27,7 +27,7 @@ #ifndef __XEN_PUBLIC_XEN_COMPAT_H__ #define __XEN_PUBLIC_XEN_COMPAT_H__ -#define __XEN_LATEST_INTERFACE_VERSION__ 0x00030207 +#define __XEN_LATEST_INTERFACE_VERSION__ 0x00030208 #if defined(__XEN__) || defined(__XEN_TOOLS__) /* Xen is built with matching headers and implements the latest interface. */ -- cgit v1.2.3 From 0243b256d6187ea610174531607366945e489605 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Tue, 12 Feb 2008 14:35:39 +0000 Subject: Add stubdomain support. See stubdom/README for usage details. - Move PAGE_SIZE and STACK_SIZE into __PAGE_SIZE and __STACK_SIZE in arch_limits.h so as to permit getting them from there without pulling all the internal Mini-OS defines. - Setup a xen-elf cross-compilation environment in stubdom/cross-root - Add a POSIX layer on top of Mini-OS by linking against the newlib C library and lwIP, and implementing the Unixish part in mini-os/lib/sys.c - Cross-compile zlib and libpci too. - Add an xs.h-compatible layer on top of Mini-OS' xenbus. - Cross-compile libxc with an additional xc_minios.c and a few things disabled. - Cross-compile ioemu with an additional block-vbd, but without sound, tpm and other details. A few hacks are needed: - Align ide and scsi buffers at least on sector size to permit direct transmission to the block backend. While we are at it, just page-align it to possibly save a segment. Also, limit the scsi buffer size because of limitations of the block paravirtualization protocol. - Allocate big tables dynamically rather that letting them go to bss: when Mini-OS gets installed in memory, bss is not lazily allocated, and doing so during Mini-OS is unnecessarily trick while we can simply use malloc. - Had to change the Mini-OS compilation somehow, so as to export Mini-OS compilation flags to the Makefiles of libxc and ioemu. Signed-off-by: Samuel Thibault --- .hgignore | 11 + Config.mk | 8 + extras/mini-os/Config.mk | 76 ++ extras/mini-os/Makefile | 81 +-- extras/mini-os/arch/ia64/Makefile | 4 +- extras/mini-os/arch/ia64/minios-ia64.lds | 12 + extras/mini-os/arch/ia64/mm.c | 8 + extras/mini-os/arch/x86/Makefile | 3 +- extras/mini-os/arch/x86/arch.mk | 8 +- extras/mini-os/arch/x86/minios-x86_32.lds | 12 + extras/mini-os/arch/x86/minios-x86_64.lds | 12 + extras/mini-os/arch/x86/mm.c | 17 + extras/mini-os/arch/x86/x86_32.S | 6 +- extras/mini-os/arch/x86/x86_64.S | 6 +- extras/mini-os/blkfront.c | 46 +- extras/mini-os/include/arch/cc.h | 7 + extras/mini-os/include/byteswap.h | 22 + extras/mini-os/include/console.h | 3 + extras/mini-os/include/errno.h | 7 + extras/mini-os/include/fcntl.h | 3 + extras/mini-os/include/fs.h | 1 + extras/mini-os/include/ia64/arch_limits.h | 12 + extras/mini-os/include/ia64/arch_mm.h | 4 +- extras/mini-os/include/ia64/page.h | 6 +- extras/mini-os/include/lib.h | 59 ++ extras/mini-os/include/linux/types.h | 5 + extras/mini-os/include/mm.h | 8 + extras/mini-os/include/netfront.h | 4 + extras/mini-os/include/posix/dirent.h | 24 + extras/mini-os/include/posix/limits.h | 9 + extras/mini-os/include/posix/netdb.h | 9 + extras/mini-os/include/posix/netinet/in.h | 7 + extras/mini-os/include/posix/netinet/tcp.h | 6 + extras/mini-os/include/posix/pthread.h | 19 + extras/mini-os/include/posix/stdlib.h | 8 + extras/mini-os/include/posix/strings.h | 8 + extras/mini-os/include/posix/sys/ioctl.h | 16 + extras/mini-os/include/posix/sys/mman.h | 19 + extras/mini-os/include/posix/sys/select.h | 7 + extras/mini-os/include/posix/sys/socket.h | 31 + extras/mini-os/include/posix/termios.h | 87 +++ extras/mini-os/include/posix/time.h | 10 + extras/mini-os/include/posix/unistd.h | 12 + extras/mini-os/include/sched.h | 3 + extras/mini-os/include/sys/time.h | 4 + extras/mini-os/include/time.h | 11 +- extras/mini-os/include/x86/arch_limits.h | 20 + extras/mini-os/include/x86/arch_mm.h | 22 +- extras/mini-os/include/x86/arch_sched.h | 4 +- extras/mini-os/include/x86/arch_spinlock.h | 1 + extras/mini-os/include/x86/os.h | 1 + extras/mini-os/lib/sys.c | 1083 ++++++++++++++++++++++++++++ extras/mini-os/lib/xs.c | 187 +++++ extras/mini-os/main-caml.c | 42 ++ extras/mini-os/main.c | 167 +++++ extras/mini-os/minios.mk | 13 +- extras/mini-os/mm.c | 23 + extras/mini-os/netfront.c | 98 ++- extras/mini-os/sched.c | 44 ++ stubdom/Makefile | 256 +++++++ stubdom/README | 41 ++ stubdom/caml/Makefile | 18 + stubdom/caml/hello.ml | 4 + stubdom/libpci.config.h | 5 + stubdom/libpci.config.mak | 2 + stubdom/stubdom-dm | 97 +++ tools/ioemu/Makefile.target | 42 +- tools/ioemu/aes.c | 2 + tools/ioemu/block-vbd.c | 341 +++++++++ tools/ioemu/block.c | 3 + tools/ioemu/configure | 22 +- tools/ioemu/exec-all.h | 4 + tools/ioemu/hw/ide.c | 4 +- tools/ioemu/hw/scsi-disk.c | 8 +- tools/ioemu/hw/xen_machine_fv.c | 3 + tools/ioemu/vl.c | 65 +- tools/ioemu/vl.h | 3 + tools/ioemu/vnc.c | 19 +- tools/ioemu/xenstore.c | 19 +- tools/libxc/Makefile | 23 +- tools/libxc/ia64/Makefile | 2 + tools/libxc/xc_minios.c | 313 ++++++++ 82 files changed, 3612 insertions(+), 130 deletions(-) create mode 100644 extras/mini-os/Config.mk create mode 100644 extras/mini-os/include/byteswap.h create mode 100644 extras/mini-os/include/ia64/arch_limits.h create mode 100644 extras/mini-os/include/linux/types.h create mode 100644 extras/mini-os/include/posix/dirent.h create mode 100644 extras/mini-os/include/posix/limits.h create mode 100644 extras/mini-os/include/posix/netdb.h create mode 100644 extras/mini-os/include/posix/netinet/in.h create mode 100644 extras/mini-os/include/posix/netinet/tcp.h create mode 100644 extras/mini-os/include/posix/pthread.h create mode 100644 extras/mini-os/include/posix/stdlib.h create mode 100644 extras/mini-os/include/posix/strings.h create mode 100644 extras/mini-os/include/posix/sys/ioctl.h create mode 100644 extras/mini-os/include/posix/sys/mman.h create mode 100644 extras/mini-os/include/posix/sys/select.h create mode 100644 extras/mini-os/include/posix/sys/socket.h create mode 100644 extras/mini-os/include/posix/termios.h create mode 100644 extras/mini-os/include/posix/time.h create mode 100644 extras/mini-os/include/posix/unistd.h create mode 100644 extras/mini-os/include/x86/arch_limits.h create mode 100644 extras/mini-os/lib/sys.c create mode 100644 extras/mini-os/lib/xs.c create mode 100644 extras/mini-os/main-caml.c create mode 100644 extras/mini-os/main.c create mode 100644 stubdom/Makefile create mode 100644 stubdom/README create mode 100644 stubdom/caml/Makefile create mode 100644 stubdom/caml/hello.ml create mode 100644 stubdom/libpci.config.h create mode 100644 stubdom/libpci.config.mak create mode 100644 stubdom/stubdom-dm create mode 100644 tools/ioemu/block-vbd.c create mode 100644 tools/libxc/xc_minios.c diff --git a/.hgignore b/.hgignore index 4063f19caa..f6affe953a 100644 --- a/.hgignore +++ b/.hgignore @@ -80,6 +80,17 @@ ^pristine-.*$ ^ref-.*$ ^tmp-.*$ +^stubdom/binutils.*$ +^stubdom/cross-root.*$ +^stubdom/gcc.*$ +^stubdom/include.*$ +^stubdom/ioemu.*$ +^stubdom/libxc.*$ +^stubdom/lwip.*$ +^stubdom/mini-os.*$ +^stubdom/newlib.*$ +^stubdom/pciutils.*$ +^stubdom/zlib.*$ ^tools/.*/TAGS$ ^tools/.*/build/lib.*/.*\.py$ ^tools/blktap/Makefile\.smh$ diff --git a/Config.mk b/Config.mk index 5715debf9b..771d1fbfbc 100644 --- a/Config.mk +++ b/Config.mk @@ -28,6 +28,14 @@ DESTDIR ?= / include $(XEN_ROOT)/config/$(XEN_OS).mk include $(XEN_ROOT)/config/$(XEN_TARGET_ARCH).mk +ifeq ($(stubdom),y) +include $(XEN_ROOT)/extras/mini-os/Config.mk +CFLAGS += $(DEF_CFLAGS) $(ARCH_CFLAGS) +CPPFLAGS += $(DEF_CPPFLAGS) $(ARCH_CPPFLAGS) $(extra_incl) +ASFLAGS += $(DEF_ASFLAGS) $(ARCH_ASFLAGS) +LDFLAGS += $(DEF_LDFLAGS) $(ARCH_LDFLAGS) +endif + ifneq ($(EXTRA_PREFIX),) EXTRA_INCLUDES += $(EXTRA_PREFIX)/include EXTRA_LIB += $(EXTRA_PREFIX)/$(LIBLEAFDIR) diff --git a/extras/mini-os/Config.mk b/extras/mini-os/Config.mk new file mode 100644 index 0000000000..e38fae99cb --- /dev/null +++ b/extras/mini-os/Config.mk @@ -0,0 +1,76 @@ +# Set mini-os root path, used in mini-os.mk. +MINI-OS_ROOT=$(XEN_ROOT)/extras/mini-os +export MINI-OS_ROOT + +ifeq ($(XEN_TARGET_ARCH),x86_32) +export pae ?= y +endif +libc = $(stubdom) + +XEN_INTERFACE_VERSION := 0x00030205 +export XEN_INTERFACE_VERSION + +# 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 $(XEN_TARGET_ARCH) -> for ia64, ... +ifeq ($(findstring x86_,$(XEN_TARGET_ARCH)),x86_) +TARGET_ARCH_FAM = x86 +else +TARGET_ARCH_FAM = $(XEN_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_DIR +export TARGET_ARCH_FAM +export XEN_TARGET_X86_PAE + +# This is used for architecture specific links. +# This can be overwritten from arch specific rules. +ARCH_LINKS = + +# The path pointing to the architecture specific header files. +ARCH_INC := $(TARGET_ARCH_FAM) + +# For possible special header directories. +# This can be overwritten from arch specific rules. +EXTRA_INC = $(ARCH_INC) + +# Include the architecture family's special makerules. +# This must be before include minios.mk! +include $(MINI-OS_ROOT)/$(TARGET_ARCH_DIR)/arch.mk + +extra_incl := $(foreach dir,$(EXTRA_INC),-I$(MINI-OS_ROOT)/include/$(dir)) + +DEF_CPPFLAGS += -I$(MINI-OS_ROOT)/include + +ifeq ($(stubdom),y) +DEF_CPPFLAGS += -DCONFIG_STUBDOM +endif + +ifeq ($(libc),y) +DEF_CPPFLAGS += -DHAVE_LIBC +DEF_CPPFLAGS += -I$(MINI-OS_ROOT)/include/posix +DEF_CPPFLAGS += -I$(XEN_ROOT)/tools/xenstore +endif + +ifneq ($(LWIPDIR),) +lwip=y +DEF_CPPFLAGS += -DHAVE_LWIP +DEF_CPPFLAGS += -I$(LWIPDIR)/src/include +DEF_CPPFLAGS += -I$(LWIPDIR)/src/include/ipv4 +endif + +ifneq ($(QEMUDIR),) +qemu=y +endif + +ifneq ($(CAMLDIR),) +caml=y +endif + +ifeq ($(pae),y) +DEF_CPPFLAGS += -DCONFIG_X86_PAE +endif diff --git a/extras/mini-os/Makefile b/extras/mini-os/Makefile index a008143cf0..4811f0dbfd 100644 --- a/extras/mini-os/Makefile +++ b/extras/mini-os/Makefile @@ -4,54 +4,11 @@ # Makefile and a arch.mk. # -XEN_ROOT = ../.. +export XEN_ROOT = ../.. include $(XEN_ROOT)/Config.mk -XEN_INTERFACE_VERSION := 0x00030205 -export XEN_INTERFACE_VERSION - -# Set TARGET_ARCH -override TARGET_ARCH := $(XEN_TARGET_ARCH) - -# Set mini-os root path, used in mini-os.mk. -MINI-OS_ROOT=$(PWD) -export MINI-OS_ROOT - -# 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 -export XEN_TARGET_X86_PAE - -# 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 = - -# Include the architecture family's special makerules. -# This must be before include minios.mk! -include $(TARGET_ARCH_DIR)/arch.mk - -ifneq ($(LWIPDIR),) -lwip=y -DEF_CFLAGS += -DHAVE_LWIP -DEF_CFLAGS += -I$(LWIPDIR)/src/include -DEF_CFLAGS += -I$(LWIPDIR)/src/include/ipv4 +ifneq ($(stubdom),y) +include Config.mk endif # Include common mini-os makerules. @@ -63,7 +20,7 @@ include minios.mk # Define some default flags for linking. LDLIBS := LDARCHLIB := -L$(TARGET_ARCH_DIR) -l$(ARCH_LIB_NAME) -LDFLAGS_FINAL := -T $(TARGET_ARCH_DIR)/minios-$(TARGET_ARCH).lds +LDFLAGS_FINAL := -T $(TARGET_ARCH_DIR)/minios-$(XEN_TARGET_ARCH).lds # Prefix for global API names. All other symbols are localised before # linking with EXTRA_OBJS. @@ -112,14 +69,38 @@ lwip.a: $(LWO) $(AR) cqs $@ $^ OBJS += lwip.a +endif + +OBJS := $(filter-out lwip%.o $(LWO), $(OBJS)) -OBJS := $(filter-out $(LWO), $(OBJS)) +ifeq ($(caml),y) +CAMLLIB = $(shell ocamlc -where) +OBJS += $(CAMLDIR)/caml.o +OBJS += $(CAMLLIB)/libasmrun.a +CFLAGS += -I$(CAMLLIB) +LDLIBS += -lm else -OBJS := $(filter-out daytime.o lwip%.o, $(OBJS)) +OBJS := $(filter-out main-caml.o, $(OBJS)) +endif + +ifeq ($(qemu),y) +OBJS += $(QEMUDIR)/i386-dm-stubdom/qemu.a $(QEMUDIR)/i386-dm-stubdom/libqemu.a +CFLAGS += -DCONFIG_QEMU +endif + +ifeq ($(libc),y) +LDLIBS += -L$(XEN_ROOT)/stubdom/libxc -lxenctrl -lxenguest +LDLIBS += -lpci +LDLIBS += -lz +LDLIBS += -lc +endif + +ifneq ($(caml)-$(qemu)-$(lwip),--y) +OBJS := $(filter-out daytime.o, $(OBJS)) endif $(TARGET): links $(OBJS) arch_lib - $(LD) -r $(LDFLAGS) $(HEAD_OBJ) $(OBJS) $(LDARCHLIB) -o $@.o + $(LD) -r $(LDFLAGS) $(HEAD_OBJ) $(OBJS) $(LDARCHLIB) $(LDLIBS) -o $@.o $(OBJCOPY) -w -G $(GLOBAL_PREFIX)* -G _start $@.o $@.o $(LD) $(LDFLAGS) $(LDFLAGS_FINAL) $@.o $(EXTRA_OBJS) -o $@ gzip -f -9 -c $@ >$@.gz diff --git a/extras/mini-os/arch/ia64/Makefile b/extras/mini-os/arch/ia64/Makefile index fb5ca9fb72..6e46aa67ef 100644 --- a/extras/mini-os/arch/ia64/Makefile +++ b/extras/mini-os/arch/ia64/Makefile @@ -5,6 +5,8 @@ XEN_ROOT = ../../../.. include $(XEN_ROOT)/Config.mk +include ../../Config.mk + include arch.mk include ../../minios.mk @@ -41,7 +43,7 @@ ARCH_OBJS += __divdi3.o GEN_OFF_SRC := gen_off.c GEN_OFF_ASM := gen_off.s -GEN_OFF_H := $(ARCH_INC)/offsets.h +GEN_OFF_H := $(MINI-OS_ROOT)/include/$(ARCH_INC)/offsets.h all: $(ARCH_LIB) diff --git a/extras/mini-os/arch/ia64/minios-ia64.lds b/extras/mini-os/arch/ia64/minios-ia64.lds index 70435de11e..96911aa3fd 100644 --- a/extras/mini-os/arch/ia64/minios-ia64.lds +++ b/extras/mini-os/arch/ia64/minios-ia64.lds @@ -40,6 +40,18 @@ SECTIONS .rodata.str1.8 : AT(ADDR(.rodata.str1.8) - (((5<<(61))+0x100000000) - (1 << 20))) { *(.rodata.str1.8) } + /* newlib initialization functions */ + . = ALIGN(64 / 8); + PROVIDE (__preinit_array_start = .); + .preinit_array : { *(.preinit_array) } + PROVIDE (__preinit_array_end = .); + PROVIDE (__init_array_start = .); + .init_array : { *(.init_array) } + PROVIDE (__init_array_end = .); + PROVIDE (__fini_array_start = .); + .fini_array : { *(.fini_array) } + PROVIDE (__fini_array_end = .); + .IA_64.unwind_info : AT(ADDR(.IA_64.unwind_info) - (((5<<(61))+0x100000000) - (1 << 20))) { *(.IA_64.unwind_info) } diff --git a/extras/mini-os/arch/ia64/mm.c b/extras/mini-os/arch/ia64/mm.c index f557730257..f2291f918c 100644 --- a/extras/mini-os/arch/ia64/mm.c +++ b/extras/mini-os/arch/ia64/mm.c @@ -43,6 +43,14 @@ extern uint64_t _text[], _etext[], _end[], kstack[], phys_start[]; uint64_t kernstart, kernend, kernsize, kernpstart, kernpend; +#ifdef HAVE_LIBC +uint8_t _heap[512 * 1024]; +unsigned long heap = (unsigned long)_heap, + brk = (unsigned long)_heap, + heap_mapped = (unsigned long)_heap + sizeof(_heap), + heap_end = (unsigned long)_heap + sizeof(_heap); +#endif + /* Print the available memory chunks. */ static void print_phys_avail(void) diff --git a/extras/mini-os/arch/x86/Makefile b/extras/mini-os/arch/x86/Makefile index 22cfe82811..21f0958f6a 100644 --- a/extras/mini-os/arch/x86/Makefile +++ b/extras/mini-os/arch/x86/Makefile @@ -5,13 +5,14 @@ XEN_ROOT = ../../../.. include $(XEN_ROOT)/Config.mk +include ../../Config.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 +# Sources here are all *.c *.S without $(XEN_TARGET_ARCH).S # This is handled in $(HEAD_ARCH_OBJ) ARCH_SRCS := $(wildcard *.c) diff --git a/extras/mini-os/arch/x86/arch.mk b/extras/mini-os/arch/x86/arch.mk index dd6bfe0b8d..1680362789 100644 --- a/extras/mini-os/arch/x86/arch.mk +++ b/extras/mini-os/arch/x86/arch.mk @@ -3,11 +3,11 @@ # (including x86_32, x86_32y and x86_64). # -ifeq ($(TARGET_ARCH),x86_32) +ifeq ($(XEN_TARGET_ARCH),x86_32) ARCH_CFLAGS := -m32 -march=i686 ARCH_LDFLAGS := -m elf_i386 ARCH_ASFLAGS := -m32 -EXTRA_INC += $(TARGET_ARCH_FAM)/$(TARGET_ARCH) +EXTRA_INC += $(TARGET_ARCH_FAM)/$(XEN_TARGET_ARCH) EXTRA_SRC += arch/$(EXTRA_INC) ifeq ($(XEN_TARGET_X86_PAE),y) @@ -16,12 +16,12 @@ ARCH_ASFLAGS += -DCONFIG_X86_PAE=1 endif endif -ifeq ($(TARGET_ARCH),x86_64) +ifeq ($(XEN_TARGET_ARCH),x86_64) ARCH_CFLAGS := -m64 -mno-red-zone -fno-reorder-blocks ARCH_CFLAGS += -fno-asynchronous-unwind-tables ARCH_ASFLAGS := -m64 ARCH_LDFLAGS := -m elf_x86_64 -EXTRA_INC += $(TARGET_ARCH_FAM)/$(TARGET_ARCH) +EXTRA_INC += $(TARGET_ARCH_FAM)/$(XEN_TARGET_ARCH) EXTRA_SRC += arch/$(EXTRA_INC) endif diff --git a/extras/mini-os/arch/x86/minios-x86_32.lds b/extras/mini-os/arch/x86/minios-x86_32.lds index 08ebe14328..df5301944f 100644 --- a/extras/mini-os/arch/x86/minios-x86_32.lds +++ b/extras/mini-os/arch/x86/minios-x86_32.lds @@ -16,6 +16,18 @@ SECTIONS . = ALIGN(4096); _erodata = .; + /* newlib initialization functions */ + . = ALIGN(32 / 8); + PROVIDE (__preinit_array_start = .); + .preinit_array : { *(.preinit_array) } + PROVIDE (__preinit_array_end = .); + PROVIDE (__init_array_start = .); + .init_array : { *(.init_array) } + PROVIDE (__init_array_end = .); + PROVIDE (__fini_array_start = .); + .fini_array : { *(.fini_array) } + PROVIDE (__fini_array_end = .); + .data : { /* Data */ *(.data) CONSTRUCTORS diff --git a/extras/mini-os/arch/x86/minios-x86_64.lds b/extras/mini-os/arch/x86/minios-x86_64.lds index 345c38640c..f93800236b 100644 --- a/extras/mini-os/arch/x86/minios-x86_64.lds +++ b/extras/mini-os/arch/x86/minios-x86_64.lds @@ -16,6 +16,18 @@ SECTIONS . = ALIGN(4096); _erodata = .; + /* newlib initialization functions */ + . = ALIGN(64 / 8); + PROVIDE (__preinit_array_start = .); + .preinit_array : { *(.preinit_array) } + PROVIDE (__preinit_array_end = .); + PROVIDE (__init_array_start = .); + .init_array : { *(.init_array) } + PROVIDE (__init_array_end = .); + PROVIDE (__fini_array_start = .); + .fini_array : { *(.fini_array) } + PROVIDE (__fini_array_end = .); + .data : { /* Data */ *(.data) CONSTRUCTORS diff --git a/extras/mini-os/arch/x86/mm.c b/extras/mini-os/arch/x86/mm.c index 082527d098..dd556e4741 100644 --- a/extras/mini-os/arch/x86/mm.c +++ b/extras/mini-os/arch/x86/mm.c @@ -448,6 +448,15 @@ static unsigned long demand_map_area_start; #define DEMAND_MAP_PAGES ((2ULL << 30) / PAGE_SIZE) #endif +#ifdef HAVE_LIBC +unsigned long heap, brk, heap_mapped, heap_end; +#ifdef __x86_64__ +#define HEAP_PAGES ((128ULL << 30) / PAGE_SIZE) +#else +#define HEAP_PAGES ((1ULL << 30) / PAGE_SIZE) +#endif +#endif + void arch_init_demand_mapping_area(unsigned long cur_pfn) { cur_pfn++; @@ -455,6 +464,14 @@ void arch_init_demand_mapping_area(unsigned long cur_pfn) demand_map_area_start = (unsigned long) pfn_to_virt(cur_pfn); cur_pfn += DEMAND_MAP_PAGES; printk("Demand map pfns at %lx-%lx.\n", demand_map_area_start, pfn_to_virt(cur_pfn)); + +#ifdef HAVE_LIBC + cur_pfn++; + heap_mapped = brk = heap = (unsigned long) pfn_to_virt(cur_pfn); + cur_pfn += HEAP_PAGES; + heap_end = (unsigned long) pfn_to_virt(cur_pfn); + printk("Heap resides at %lx-%lx.\n", brk, heap_end); +#endif } #define MAP_BATCH ((STACK_SIZE / 2) / sizeof(mmu_update_t)) diff --git a/extras/mini-os/arch/x86/x86_32.S b/extras/mini-os/arch/x86/x86_32.S index 4b9a337c08..7f01851f0c 100644 --- a/extras/mini-os/arch/x86/x86_32.S +++ b/extras/mini-os/arch/x86/x86_32.S @@ -1,5 +1,5 @@ #include -#include +#include #include .section __xen_guest @@ -22,12 +22,12 @@ _start: cld lss stack_start,%esp - andl $(~(STACK_SIZE-1)), %esp + andl $(~(__STACK_SIZE-1)), %esp push %esi call start_kernel stack_start: - .long stack+(2*STACK_SIZE), __KERNEL_SS + .long stack+(2*__STACK_SIZE), __KERNEL_SS /* Unpleasant -- the PTE that maps this page is actually overwritten */ /* to map the real shared-info page! :-) */ diff --git a/extras/mini-os/arch/x86/x86_64.S b/extras/mini-os/arch/x86/x86_64.S index fae2ae4cf5..c7a797db90 100644 --- a/extras/mini-os/arch/x86/x86_64.S +++ b/extras/mini-os/arch/x86/x86_64.S @@ -1,5 +1,5 @@ #include -#include +#include #include .section __xen_guest @@ -19,12 +19,12 @@ _start: cld movq stack_start(%rip),%rsp - andq $(~(STACK_SIZE-1)), %rsp + andq $(~(__STACK_SIZE-1)), %rsp movq %rsi,%rdi call start_kernel stack_start: - .quad stack+(2*STACK_SIZE) + .quad stack+(2*__STACK_SIZE) /* Unpleasant -- the PTE that maps this page is actually overwritten */ /* to map the real shared-info page! :-) */ diff --git a/extras/mini-os/blkfront.c b/extras/mini-os/blkfront.c index 881efd3055..b83d5af345 100644 --- a/extras/mini-os/blkfront.c +++ b/extras/mini-os/blkfront.c @@ -15,6 +15,10 @@ #include #include +#ifndef HAVE_LIBC +#define strtoul simple_strtoul +#endif + /* Note: we generally don't need to disable IRQs since we hardly do anything in * the interrupt handler. */ @@ -49,6 +53,10 @@ struct blkfront_dev { int mode; int barrier; int flush; + +#ifdef HAVE_LIBC + int fd; +#endif }; static inline int xenblk_rxidx(RING_IDX idx) @@ -58,6 +66,12 @@ static inline int xenblk_rxidx(RING_IDX idx) void blkfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data) { +#ifdef HAVE_LIBC + struct blkfront_dev *dev = data; + int fd = dev->fd; + + files[fd].read = 1; +#endif wake_up(&blkfront_queue); } @@ -148,7 +162,7 @@ done: printk("backend at %s\n", dev->backend); - dev->handle = simple_strtoul(strrchr(nodename, '/')+1, NULL, 0); + dev->handle = strtoul(strrchr(nodename, '/')+1, NULL, 0); { char path[strlen(dev->backend) + 1 + 19 + 1]; @@ -322,12 +336,16 @@ moretodo: { rsp = RING_GET_RESPONSE(&dev->ring, cons); + if (rsp->status != BLKIF_RSP_OKAY) + printk("block error %d for op %d\n", rsp->status, rsp->operation); + switch (rsp->operation) { case BLKIF_OP_READ: case BLKIF_OP_WRITE: { struct blkfront_aiocb *aiocbp = (void*) (uintptr_t) rsp->id; int j; + for (j = 0; j < aiocbp->n; j++) gnttab_end_access(aiocbp->gref[j]); @@ -365,6 +383,12 @@ static void blkfront_push_operation(struct blkfront_dev *dev, uint8_t op) i = dev->ring.req_prod_pvt; req = RING_GET_REQUEST(&dev->ring, i); req->operation = op; + req->nr_segments = 0; + req->handle = dev->handle; + /* Not used */ + req->id = 0; + /* Not needed anyway, but the backend will check it */ + req->sector_number = 0; dev->ring.req_prod_pvt = i + 1; wmb(); RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&dev->ring, notify); @@ -375,11 +399,13 @@ void blkfront_sync(struct blkfront_dev *dev) { unsigned long flags; - if (dev->barrier == 1) - blkfront_push_operation(dev, BLKIF_OP_WRITE_BARRIER); + if (dev->mode == O_RDWR) { + if (dev->barrier == 1) + blkfront_push_operation(dev, BLKIF_OP_WRITE_BARRIER); - if (dev->flush == 1) - blkfront_push_operation(dev, BLKIF_OP_FLUSH_DISKCACHE); + if (dev->flush == 1) + blkfront_push_operation(dev, BLKIF_OP_FLUSH_DISKCACHE); + } /* Note: This won't finish if another thread enqueues requests. */ local_irq_save(flags); @@ -397,3 +423,13 @@ void blkfront_sync(struct blkfront_dev *dev) remove_waiter(w); local_irq_restore(flags); } + +#ifdef HAVE_LIBC +int blkfront_open(struct blkfront_dev *dev) +{ + dev->fd = alloc_fd(FTYPE_BLK); + printk("blk_open(%s) -> %d\n", dev->nodename, dev->fd); + files[dev->fd].blk.dev = dev; + return dev->fd; +} +#endif diff --git a/extras/mini-os/include/arch/cc.h b/extras/mini-os/include/arch/cc.h index 70191f0b30..e9a258d8bf 100644 --- a/extras/mini-os/include/arch/cc.h +++ b/extras/mini-os/include/arch/cc.h @@ -54,7 +54,14 @@ extern void lwip_die(char *fmt, ...); #include /* Not required by the docs, but needed for network-order calculations */ +#ifdef HAVE_LIBC +#include +#ifndef BIG_ENDIAN +#error endian.h does not define byte order +#endif +#else #include +#endif #include #define S16_F PRIi16 diff --git a/extras/mini-os/include/byteswap.h b/extras/mini-os/include/byteswap.h new file mode 100644 index 0000000000..7c4ffe393c --- /dev/null +++ b/extras/mini-os/include/byteswap.h @@ -0,0 +1,22 @@ +#ifndef _BYTESWAP_H_ +#define _BYTESWAP_H_ + +/* Unfortunately not provided by newlib. */ +#define bswap_16(x) \ + ((((x) & 0xff00) >> 8) | (((x) & 0xff) << 8)) + +#define bswap_32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +#define bswap_64(x) \ + ((((x) & 0xff00000000000000ULL) >> 56) | \ + (((x) & 0x00ff000000000000ULL) >> 40) | \ + (((x) & 0x0000ff0000000000ULL) >> 24) | \ + (((x) & 0x000000ff00000000ULL) >> 8) | \ + (((x) & 0x00000000ff000000ULL) << 8) | \ + (((x) & 0x0000000000ff0000ULL) << 24) | \ + (((x) & 0x000000000000ff00ULL) << 40) | \ + (((x) & 0x00000000000000ffULL) << 56)) + +#endif /* _BYTESWAP_H */ diff --git a/extras/mini-os/include/console.h b/extras/mini-os/include/console.h index 6ee04f1316..9ace8dfcb1 100644 --- a/extras/mini-os/include/console.h +++ b/extras/mini-os/include/console.h @@ -36,7 +36,9 @@ #ifndef _LIB_CONSOLE_H_ #define _LIB_CONSOLE_H_ +#include #include +#include void print(int direct, const char *fmt, va_list args); void printk(const char *fmt, ...); @@ -48,5 +50,6 @@ void xencons_rx(char *buf, unsigned len, struct pt_regs *regs); void xencons_tx(void); void init_console(void); +void console_print(char *data, int length); #endif /* _LIB_CONSOLE_H_ */ diff --git a/extras/mini-os/include/errno.h b/extras/mini-os/include/errno.h index 262ab3e0b4..2829420dd7 100644 --- a/extras/mini-os/include/errno.h +++ b/extras/mini-os/include/errno.h @@ -107,4 +107,11 @@ #define EOWNERDEAD 130 /* Owner died */ #define ENOTRECOVERABLE 131 /* State not recoverable */ +#ifdef HAVE_LIBC +#include +extern int errno; +#define ERRNO +#define errno (get_current()->reent._errno) +#endif + #endif diff --git a/extras/mini-os/include/fcntl.h b/extras/mini-os/include/fcntl.h index 64020795ab..34a6484d35 100644 --- a/extras/mini-os/include/fcntl.h +++ b/extras/mini-os/include/fcntl.h @@ -86,4 +86,7 @@ struct flock64 { #define F_LINUX_SPECIFIC_BASE 1024 */ + +int open(const char *path, int flags, ...); +int fcntl(int fd, int cmd, ...); #endif diff --git a/extras/mini-os/include/fs.h b/extras/mini-os/include/fs.h index 1555a5adcc..4c822dfb20 100644 --- a/extras/mini-os/include/fs.h +++ b/extras/mini-os/include/fs.h @@ -22,6 +22,7 @@ struct fs_import struct semaphore reqs_sem; /* Accounts requests resource */ }; +extern struct fs_import *fs_import; void init_fs_frontend(void); diff --git a/extras/mini-os/include/ia64/arch_limits.h b/extras/mini-os/include/ia64/arch_limits.h new file mode 100644 index 0000000000..c7bb9b6573 --- /dev/null +++ b/extras/mini-os/include/ia64/arch_limits.h @@ -0,0 +1,12 @@ + +#ifndef __ARCH_LIMITS_H__ +#define __ARCH_LIMITS_H__ + +/* Commonly 16K pages are used. */ +#define __PAGE_SHIFT 14 /* 16K pages */ +#define __PAGE_SIZE (1<<(__PAGE_SHIFT)) + +#define __STACK_SIZE_PAGE_ORDER 2 +#define __STACK_SIZE (__PAGE_SIZE * (1 << __STACK_SIZE_PAGE_ORDER)) + +#endif /* __ARCH_LIMITS_H__ */ diff --git a/extras/mini-os/include/ia64/arch_mm.h b/extras/mini-os/include/ia64/arch_mm.h index 2a8e1c82a6..adc1da6d0f 100644 --- a/extras/mini-os/include/ia64/arch_mm.h +++ b/extras/mini-os/include/ia64/arch_mm.h @@ -35,11 +35,9 @@ #define virt_to_mfn(x) virt_to_pfn(x) #define virtual_to_mfn(x) (ia64_tpa((uint64_t)(x)) >> PAGE_SHIFT) -#define STACK_SIZE_PAGE_ORDER 1 -#define STACK_SIZE (PAGE_SIZE * (1 << STACK_SIZE_PAGE_ORDER)) - #define map_frames(f, n) map_frames_ex(f, n, 1, 0, 1, DOMID_SELF, 0, 0) /* TODO */ #define map_zero(n, a) map_frames_ex(NULL, n, 0, 0, a, DOMID_SELF, 0, 0) +#define do_map_zero(start, n) ((void)0) #endif /* __ARCH_MM_H__ */ diff --git a/extras/mini-os/include/ia64/page.h b/extras/mini-os/include/ia64/page.h index 714227f172..67be0a555d 100644 --- a/extras/mini-os/include/ia64/page.h +++ b/extras/mini-os/include/ia64/page.h @@ -43,9 +43,9 @@ /* The efi-pal page size for text and data. */ #define PAL_TR_PAGE_SIZE PTE_PS_1M -/* Commonly 16K pages are used. */ -#define PAGE_SHIFT 14 /* 16K pages */ -#define PAGE_SIZE (1<<(PAGE_SHIFT)) +#include "arch_limits.h" +#define PAGE_SHIFT __PAGE_SHIFT +#define PAGE_SIZE __PAGE_SIZE #define PAGE_MASK (~(PAGE_SIZE-1)) #define KSTACK_PAGES 4 /* 4 pages for the kernel stack + bsp */ diff --git a/extras/mini-os/include/lib.h b/extras/mini-os/include/lib.h index efe096bdba..2ddb8d07c8 100644 --- a/extras/mini-os/include/lib.h +++ b/extras/mini-os/include/lib.h @@ -57,6 +57,8 @@ #include #include +#include +#include #ifdef HAVE_LIBC #include @@ -103,6 +105,8 @@ char *strdup(const char *s); int rand(void); +#include + #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) struct kvec { @@ -126,4 +130,59 @@ do { \ /* Consistency check as much as possible. */ void sanity_check(void); +#ifdef HAVE_LIBC +enum fd_type { + FTYPE_NONE = 0, + FTYPE_CONSOLE, + FTYPE_FILE, + FTYPE_XENBUS, + FTYPE_EVTCHN, + FTYPE_SOCKET, + FTYPE_TAP, + FTYPE_BLK, +}; + +#define MAX_EVTCHN_PORTS 16 + +extern struct file { + enum fd_type type; + union { + struct { + /* lwIP fd */ + int fd; + } socket; + struct { + /* FS import fd */ + int fd; + off_t offset; + } file; + struct { + /* To each event channel FD is associated a series of ports which + * wakes select for this FD. */ + struct { + evtchn_port_t port; + volatile unsigned long pending; + int bound; + } ports[MAX_EVTCHN_PORTS]; + } evtchn; + struct { + struct netfront_dev *dev; + } tap; + struct { + struct blkfront_dev *dev; + } blk; + struct { + /* To each xenbus FD is associated a queue of watch events for this + * FD. */ + struct xenbus_event *volatile events; + } xenbus; + }; + volatile int read; /* maybe available for read */ +} files[]; + +int alloc_fd(enum fd_type type); +void close_all_files(void); +extern struct thread *main_thread; +#endif + #endif /* _LIB_H_ */ diff --git a/extras/mini-os/include/linux/types.h b/extras/mini-os/include/linux/types.h new file mode 100644 index 0000000000..f153ce8e42 --- /dev/null +++ b/extras/mini-os/include/linux/types.h @@ -0,0 +1,5 @@ +#ifndef _LINUX_TYPES_H_ +#define _LINUX_TYPES_H_ +#include +typedef u64 __u64; +#endif /* _LINUX_TYPES_H_ */ diff --git a/extras/mini-os/include/mm.h b/extras/mini-os/include/mm.h index 4319fa2640..8396ec6b31 100644 --- a/extras/mini-os/include/mm.h +++ b/extras/mini-os/include/mm.h @@ -36,8 +36,13 @@ #endif #include + +#include #include +#define STACK_SIZE_PAGE_ORDER __STACK_SIZE_PAGE_ORDER +#define STACK_SIZE __STACK_SIZE + void init_mm(void); unsigned long alloc_pages(int order); @@ -61,5 +66,8 @@ void arch_init_p2m(unsigned long max_pfn_p); void *map_frames_ex(unsigned long *f, unsigned long n, unsigned long stride, unsigned long increment, unsigned long alignment, domid_t id, int may_fail, unsigned long prot); +#ifdef HAVE_LIBC +extern unsigned long heap, brk, heap_mapped, heap_end; +#endif #endif /* _MM_H_ */ diff --git a/extras/mini-os/include/netfront.h b/extras/mini-os/include/netfront.h index 5c8ec9c4fa..acfc91944b 100644 --- a/extras/mini-os/include/netfront.h +++ b/extras/mini-os/include/netfront.h @@ -6,6 +6,10 @@ struct netfront_dev; struct netfront_dev *init_netfront(char *nodename, void (*netif_rx)(unsigned char *data, int len), unsigned char rawmac[6]); void netfront_xmit(struct netfront_dev *dev, unsigned char* data,int len); void shutdown_netfront(struct netfront_dev *dev); +#ifdef HAVE_LIBC +int netfront_tap_open(char *nodename); +ssize_t netfront_receive(struct netfront_dev *dev, unsigned char *data, size_t len); +#endif extern struct wait_queue_head netfront_queue; diff --git a/extras/mini-os/include/posix/dirent.h b/extras/mini-os/include/posix/dirent.h new file mode 100644 index 0000000000..56b1d67258 --- /dev/null +++ b/extras/mini-os/include/posix/dirent.h @@ -0,0 +1,24 @@ +#ifndef _POSIX_DIRENT_H +#define _POSIX_DIRENT_H + +#include + +struct dirent { + char *d_name; +}; + +typedef struct { + struct dirent dirent; + char *name; + int32_t offset; + char **entries; + int32_t curentry; + int32_t nbentries; + int has_more; +} DIR; + +DIR *opendir(const char *name); +struct dirent *readdir(DIR *dir); +int closedir(DIR *dir); + +#endif /* _POSIX_DIRENT_H */ diff --git a/extras/mini-os/include/posix/limits.h b/extras/mini-os/include/posix/limits.h new file mode 100644 index 0000000000..ba800e33d2 --- /dev/null +++ b/extras/mini-os/include/posix/limits.h @@ -0,0 +1,9 @@ +#ifndef _POSIX_LIMITS_H +#define _POSIX_LIMITS_H + +#include_next +#include + +#define PATH_MAX __PAGE_SIZE + +#endif /* _POSIX_LIMITS_H */ diff --git a/extras/mini-os/include/posix/netdb.h b/extras/mini-os/include/posix/netdb.h new file mode 100644 index 0000000000..8f76a95b76 --- /dev/null +++ b/extras/mini-os/include/posix/netdb.h @@ -0,0 +1,9 @@ +#ifndef _POSIX_NETDB_H_ +#define _POSIX_NETDB_H_ + +struct hostent { + char *h_addr; +}; +#define gethostbyname(buf) NULL + +#endif /* _POSIX_NETDB_H_ */ diff --git a/extras/mini-os/include/posix/netinet/in.h b/extras/mini-os/include/posix/netinet/in.h new file mode 100644 index 0000000000..cc1a91076d --- /dev/null +++ b/extras/mini-os/include/posix/netinet/in.h @@ -0,0 +1,7 @@ +#ifndef _POSIX_SYS_IN_H_ +#define _POSIX_SYS_IN_H_ + +#include +#include + +#endif /* _POSIX_SYS_IN_H_ */ diff --git a/extras/mini-os/include/posix/netinet/tcp.h b/extras/mini-os/include/posix/netinet/tcp.h new file mode 100644 index 0000000000..3e3b060467 --- /dev/null +++ b/extras/mini-os/include/posix/netinet/tcp.h @@ -0,0 +1,6 @@ +#ifndef _POSIX_SYS_TCP_H_ +#define _POSIX_SYS_TCP_H_ + +#include + +#endif /* _POSIX_SYS_TCP_H_ */ diff --git a/extras/mini-os/include/posix/pthread.h b/extras/mini-os/include/posix/pthread.h new file mode 100644 index 0000000000..7e62001e3a --- /dev/null +++ b/extras/mini-os/include/posix/pthread.h @@ -0,0 +1,19 @@ +#ifndef _POSIX_PTHREAD_H +#define _POSIX_PTHREAD_H + +/* Let's be single-threaded for now. */ + +typedef void *pthread_key_t; +typedef struct {} pthread_mutex_t, pthread_once_t; +#define PTHREAD_MUTEX_INITIALIZER {} +#define PTHREAD_ONCE_INIT {} +static inline int pthread_mutex_lock(pthread_mutex_t *mutex) { return 0; } +static inline int pthread_mutex_unlock(pthread_mutex_t *mutex) { return 0; } +static inline int pthread_key_create(pthread_key_t *key, void (*destr_function)(void*)) { *key = NULL; return 0; } +static inline int pthread_setspecific(pthread_key_t *key, const void *pointer) { *key = (void*) pointer; return 0; } +static inline void *pthread_getspecific(pthread_key_t *key) { return *key; } +static inline int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) { init_routine(); return 0; } + +#define __thread + +#endif /* _POSIX_PTHREAD_H */ diff --git a/extras/mini-os/include/posix/stdlib.h b/extras/mini-os/include/posix/stdlib.h new file mode 100644 index 0000000000..53e6289635 --- /dev/null +++ b/extras/mini-os/include/posix/stdlib.h @@ -0,0 +1,8 @@ +#ifndef _POSIX_STDLIB_H +#define _POSIX_STDLIB_H + +#include_next + +#define realpath(p,r) strcpy(r,p) + +#endif /* _POSIX_STDLIB_H */ diff --git a/extras/mini-os/include/posix/strings.h b/extras/mini-os/include/posix/strings.h new file mode 100644 index 0000000000..8619ba2865 --- /dev/null +++ b/extras/mini-os/include/posix/strings.h @@ -0,0 +1,8 @@ +#ifndef _POSIX_STRINGS_H +#define _POSIX_STRINGS_H + +#include + +#define bzero(ptr, size) (memset((ptr), '\0', (size)), (void) 0) + +#endif /* _POSIX_STRINGS_H */ diff --git a/extras/mini-os/include/posix/sys/ioctl.h b/extras/mini-os/include/posix/sys/ioctl.h new file mode 100644 index 0000000000..ecf3080d5a --- /dev/null +++ b/extras/mini-os/include/posix/sys/ioctl.h @@ -0,0 +1,16 @@ +#ifndef _POSIX_SYS_IOCTL_H +#define _POSIX_SYS_IOCTL_H + +int ioctl(int fd, int request, ...); + +#define _IOC_NONE 0 +#define _IOC_WRITE 1 +#define _IOC_READ 2 + +#define _IOC(rw, class, n, size) \ + (((rw ) << 30) | \ + ((class) << 22) | \ + ((n ) << 14) | \ + ((size ) << 0)) + +#endif /* _POSIX_SYS_IOCTL_H */ diff --git a/extras/mini-os/include/posix/sys/mman.h b/extras/mini-os/include/posix/sys/mman.h new file mode 100644 index 0000000000..318d574877 --- /dev/null +++ b/extras/mini-os/include/posix/sys/mman.h @@ -0,0 +1,19 @@ +#ifndef _POSIX_SYS_MMAN_H +#define _POSIX_SYS_MMAN_H + +#define PROT_READ 0x1 +#define PROT_WRITE 0x2 +#define PROT_EXEC 0x4 + +#define MAP_SHARED 0x01 +#define MAP_PRIVATE 0x02 +#define MAP_ANON 0x20 + +#define MAP_FAILED ((void*)0) + +void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset); +int munmap(void *start, size_t length); +#define munlock(addr, len) ((void)addr, (void)len, 0) +#define mlock(addr, len) ((void)addr, (void)len, 0) + +#endif /* _POSIX_SYS_MMAN_H */ diff --git a/extras/mini-os/include/posix/sys/select.h b/extras/mini-os/include/posix/sys/select.h new file mode 100644 index 0000000000..5132c51224 --- /dev/null +++ b/extras/mini-os/include/posix/sys/select.h @@ -0,0 +1,7 @@ +#ifndef _POSIX_SELECT_H +#define _POSIX_SELECT_H + +#include +int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); + +#endif /* _POSIX_SELECT_H */ diff --git a/extras/mini-os/include/posix/sys/socket.h b/extras/mini-os/include/posix/sys/socket.h new file mode 100644 index 0000000000..7c039a2f03 --- /dev/null +++ b/extras/mini-os/include/posix/sys/socket.h @@ -0,0 +1,31 @@ +#ifndef _POSIX_SYS_SOCKET_H_ +#define _POSIX_SYS_SOCKET_H_ + +#include +#include + +int accept(int s, struct sockaddr *addr, socklen_t *addrlen); +int bind(int s, struct sockaddr *name, socklen_t namelen); +int shutdown(int s, int how); +int getpeername (int s, struct sockaddr *name, socklen_t *namelen); +int getsockname (int s, struct sockaddr *name, socklen_t *namelen); +int getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen); +int setsockopt (int s, int level, int optname, const void *optval, socklen_t optlen); +int close(int s); +int connect(int s, struct sockaddr *name, socklen_t namelen); +int listen(int s, int backlog); +int recv(int s, void *mem, int len, unsigned int flags); +//int read(int s, void *mem, int len); +int recvfrom(int s, void *mem, int len, unsigned int flags, + struct sockaddr *from, socklen_t *fromlen); +int send(int s, void *dataptr, int size, unsigned int flags); +int sendto(int s, void *dataptr, int size, unsigned int flags, + struct sockaddr *to, socklen_t tolen); +int socket(int domain, int type, int protocol); +//int write(int s, void *dataptr, int size); +int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, + struct timeval *timeout); +//int ioctl(int s, long cmd, void *argp); +int getsockname(int s, struct sockaddr *name, socklen_t *namelen); + +#endif /* _POSIX_SYS_SOCKET_H_ */ diff --git a/extras/mini-os/include/posix/termios.h b/extras/mini-os/include/posix/termios.h new file mode 100644 index 0000000000..a57aee4556 --- /dev/null +++ b/extras/mini-os/include/posix/termios.h @@ -0,0 +1,87 @@ +#ifndef _POSIX_TERMIOS_H +#define _POSIX_TERMIOS_H + +#define NCC 32 + +struct termios { + unsigned long c_iflag; + unsigned long c_oflag; + unsigned long c_lflag; + unsigned long c_cflag; + unsigned char c_cc[NCC]; +}; + +/* modem lines */ +#define TIOCM_DTR 0x002 +#define TIOCM_RTS 0x004 +#define TIOCM_CTS 0x020 +#define TIOCM_CAR 0x040 +#define TIOCM_RI 0x080 +#define TIOCM_DSR 0x100 + +/* c_iflag */ +#define IGNBRK 0x00000001 +#define BRKINT 0x00000002 +#define IGNPAR 0x00000004 +#define PARMRK 0x00000008 +#define INPCK 0x00000010 +#define ISTRIP 0x00000020 +#define INLCR 0x00000040 +#define IGNCR 0x00000080 +#define ICRNL 0x00000100 +#define IUCLC 0x00000200 +#define IXON 0x00000400 +#define IXANY 0x00000800 +#define IXOFF 0x00001000 +#define IMAXBEL 0x00002000 +#define IUTF8 0x00004000 + +/* c_oflag */ +#define OPOST 0x00000001 +#define OLCUC 0x00000002 +#define ONLCR 0x00000004 +#define OCRNL 0x00000008 +#define ONOCR 0x00000010 +#define ONLRET 0x00000020 +#define OFILL 0x00000040 +#define OFDEL 0x00000080 + +/* c_lflag */ +#define ISIG 0x00000001 +#define ICANON 0x00000002 +#define XCASE 0x00000004 +#define ECHO 0x00000008 +#define ECHOE 0x00000010 +#define ECHOK 0x00000020 +#define ECHONL 0x00000040 +#define NOFLSH 0x00000080 +#define TOSTOP 0x00000100 +#define ECHOCTL 0x00000200 +#define ECHOPRT 0x00000400 +#define ECHOKE 0x00000800 +#define FLUSHO 0x00002000 +#define PENDIN 0x00004000 +#define IEXTEN 0x00008000 + +/* c_cflag */ +#define CSIZE 0x00000030 +#define CS8 0x00000030 +#define CSTOPB 0x00000040 +#define CREAD 0x00000080 +#define PARENB 0x00000100 +#define PARODD 0x00000200 +#define HUPCL 0x00000400 +#define CLOCAL 0x00000800 + +/* c_cc */ +#define VTIME 5 +#define VMIN 6 + +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 + +int tcsetattr(int fildes, int action, const struct termios *tios); +int tcgetattr(int fildes, struct termios *tios); + +#endif /* _POSIX_TERMIOS_H */ diff --git a/extras/mini-os/include/posix/time.h b/extras/mini-os/include/posix/time.h new file mode 100644 index 0000000000..4f457cb5ad --- /dev/null +++ b/extras/mini-os/include/posix/time.h @@ -0,0 +1,10 @@ +#ifndef _POSIX_TIME_H +#define _POSIX_TIME_H + +#include +#define CLOCK_MONOTONIC 2 +#include_next + +int nanosleep(const struct timespec *req, struct timespec *rem); + +#endif /* _POSIX_TIME_H */ diff --git a/extras/mini-os/include/posix/unistd.h b/extras/mini-os/include/posix/unistd.h new file mode 100644 index 0000000000..0cd9396ec9 --- /dev/null +++ b/extras/mini-os/include/posix/unistd.h @@ -0,0 +1,12 @@ +#ifndef _POSIX_UNISTD_H +#define _POSIX_UNISTD_H + +#include_next +#include +#include + +#define getpagesize() __PAGE_SIZE + +int ftruncate(int fd, off_t length); + +#endif /* _POSIX_UNISTD_H */ diff --git a/extras/mini-os/include/sched.h b/extras/mini-os/include/sched.h index a3d2022b8a..ba0d4e3df9 100644 --- a/extras/mini-os/include/sched.h +++ b/extras/mini-os/include/sched.h @@ -19,6 +19,9 @@ struct thread struct list_head thread_list; u32 flags; s_time_t wakeup_time; +#ifdef HAVE_LIBC + struct _reent reent; +#endif }; extern struct thread *idle_thread; diff --git a/extras/mini-os/include/sys/time.h b/extras/mini-os/include/sys/time.h index 87887c27d1..d6623a4e77 100644 --- a/extras/mini-os/include/sys/time.h +++ b/extras/mini-os/include/sys/time.h @@ -20,6 +20,9 @@ #ifndef _MINIOS_SYS_TIME_H_ #define _MINIOS_SYS_TIME_H_ +#ifdef HAVE_LIBC +#include_next +#else struct timespec { time_t tv_sec; long tv_nsec; @@ -34,5 +37,6 @@ struct timeval { }; int gettimeofday(struct timeval *tv, void *tz); +#endif #endif /* _MINIOS_SYS_TIME_H_ */ diff --git a/extras/mini-os/include/time.h b/extras/mini-os/include/time.h index 914f2fcff2..e28bf171d7 100644 --- a/extras/mini-os/include/time.h +++ b/extras/mini-os/include/time.h @@ -17,8 +17,9 @@ **************************************************************************** */ -#ifndef _TIME_H_ -#define _TIME_H_ +#ifndef _MINIOS_TIME_H_ +#define _MINIOS_TIME_H_ +#include /* * System Time @@ -44,8 +45,12 @@ typedef s64 s_time_t; /* wall clock time */ typedef long time_t; typedef long suseconds_t; + #include +#ifdef HAVE_LIBC +#include_next +#endif /* prototypes */ void init_time(void); @@ -54,4 +59,4 @@ s_time_t get_v_time(void); u64 monotonic_clock(void); void block_domain(s_time_t until); -#endif /* _TIME_H_ */ +#endif /* _MINIOS_TIME_H_ */ diff --git a/extras/mini-os/include/x86/arch_limits.h b/extras/mini-os/include/x86/arch_limits.h new file mode 100644 index 0000000000..7f0351c67f --- /dev/null +++ b/extras/mini-os/include/x86/arch_limits.h @@ -0,0 +1,20 @@ + +#ifndef __ARCH_LIMITS_H__ +#define __ARCH_LIMITS_H__ + +#define __PAGE_SHIFT 12 + +#ifdef __ASSEMBLY__ +#define __PAGE_SIZE (1 << __PAGE_SHIFT) +#else +#ifndef CONFIG_X86_PAE +#define __PAGE_SIZE (1UL << __PAGE_SHIFT) +#else +#define __PAGE_SIZE (1ULL << __PAGE_SHIFT) +#endif +#endif + +#define __STACK_SIZE_PAGE_ORDER 4 +#define __STACK_SIZE (__PAGE_SIZE * (1 << __STACK_SIZE_PAGE_ORDER)) + +#endif /* __ARCH_LIMITS_H__ */ diff --git a/extras/mini-os/include/x86/arch_mm.h b/extras/mini-os/include/x86/arch_mm.h index c5e106e6da..7ad8bc14be 100644 --- a/extras/mini-os/include/x86/arch_mm.h +++ b/extras/mini-os/include/x86/arch_mm.h @@ -157,16 +157,9 @@ typedef unsigned long pgentry_t; #define L4_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER) #endif /* __i386__ || __x86_64__ */ -#ifdef __ASSEMBLY__ -#define PAGE_SIZE (1 << L1_PAGETABLE_SHIFT) -#else -#ifndef CONFIG_X86_PAE -#define PAGE_SIZE (1UL << L1_PAGETABLE_SHIFT) -#else -#define PAGE_SIZE (1ULL << L1_PAGETABLE_SHIFT) -#endif -#endif -#define PAGE_SHIFT L1_PAGETABLE_SHIFT +#include "arch_limits.h" +#define PAGE_SIZE __PAGE_SIZE +#define PAGE_SHIFT __PAGE_SHIFT #define PAGE_MASK (~(PAGE_SIZE-1)) #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> L1_PAGETABLE_SHIFT) @@ -177,9 +170,6 @@ typedef unsigned long pgentry_t; /* to align the pointer to the (next) page boundary */ #define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) -#define STACK_SIZE_PAGE_ORDER 1 -#define STACK_SIZE (PAGE_SIZE * (1 << STACK_SIZE_PAGE_ORDER)) - #ifndef __ASSEMBLY__ /* Definitions for machine and pseudophysical addresses. */ #ifdef CONFIG_X86_PAE @@ -257,5 +247,11 @@ static __inline__ paddr_t machine_to_phys(maddr_t machine) #define map_frames(f, n) map_frames_ex(f, n, 1, 0, 1, DOMID_SELF, 0, L1_PROT) #define map_zero(n, a) map_frames_ex(&mfn_zero, n, 0, 0, a, DOMID_SELF, 0, L1_PROT_RO) +#ifndef __ASSEMBLY__ +void do_map_frames(unsigned long addr, + unsigned long *f, unsigned long n, unsigned long stride, + unsigned long increment, domid_t id, int may_fail, unsigned long prot); +#endif +#define do_map_zero(start, n) do_map_frames(start, &mfn_zero, n, 0, 0, DOMID_SELF, 0, L1_PROT_RO) #endif /* _ARCH_MM_H_ */ diff --git a/extras/mini-os/include/x86/arch_sched.h b/extras/mini-os/include/x86/arch_sched.h index 877440762e..d80323cd37 100644 --- a/extras/mini-os/include/x86/arch_sched.h +++ b/extras/mini-os/include/x86/arch_sched.h @@ -2,7 +2,7 @@ #ifndef __ARCH_SCHED_H__ #define __ARCH_SCHED_H__ -#include +#include static inline struct thread* get_current(void) { @@ -12,7 +12,7 @@ static inline struct thread* get_current(void) #else register unsigned long sp asm("rsp"); #endif - current = (void *)(unsigned long)(sp & ~(STACK_SIZE-1)); + current = (void *)(unsigned long)(sp & ~(__STACK_SIZE-1)); return *current; } diff --git a/extras/mini-os/include/x86/arch_spinlock.h b/extras/mini-os/include/x86/arch_spinlock.h index a181ed3c92..b711fe473c 100644 --- a/extras/mini-os/include/x86/arch_spinlock.h +++ b/extras/mini-os/include/x86/arch_spinlock.h @@ -4,6 +4,7 @@ #define __ARCH_ASM_SPINLOCK_H #include +#include "os.h" #define ARCH_SPIN_LOCK_UNLOCKED (spinlock_t) { 1 } diff --git a/extras/mini-os/include/x86/os.h b/extras/mini-os/include/x86/os.h index 7a4433b3f9..7217d0b3ca 100644 --- a/extras/mini-os/include/x86/os.h +++ b/extras/mini-os/include/x86/os.h @@ -563,6 +563,7 @@ static __inline__ int synch_var_test_bit(int nr, volatile void * addr) synch_var_test_bit((nr),(addr))) +#undef ADDR #endif /* not assembly */ #endif /* _OS_H_ */ diff --git a/extras/mini-os/lib/sys.c b/extras/mini-os/lib/sys.c new file mode 100644 index 0000000000..f71e6966bd --- /dev/null +++ b/extras/mini-os/lib/sys.c @@ -0,0 +1,1083 @@ +/* + * POSIX-compatible libc layer + * + * Samuel Thibault , October 2007 + * + * Provides the UNIXish part of the standard libc function. + * + * Relatively straight-forward: just multiplex the file descriptor operations + * among the various file types (console, FS, network, ...) + */ + +//#define LIBC_VERBOSE +//#define LIBC_DEBUG + +#ifdef LIBC_DEBUG +#define DEBUG(fmt,...) printk(fmt, ##__VA_ARGS__) +#else +#define DEBUG(fmt,...) +#endif + +#ifdef HAVE_LIBC +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define debug(fmt, ...) \ + +#define print_unsupported(fmt, ...) \ + printk("Unsupported function "fmt" called in Mini-OS kernel\n", ## __VA_ARGS__); + +/* Crash on function call */ +#define unsupported_function_crash(function) \ + int __unsup_##function(void) asm(#function); \ + int __unsup_##function(void) \ + { \ + print_unsupported(#function); \ + do_exit(); \ + } + +/* Log and err out on function call */ +#define unsupported_function_log(type, function, ret) \ + type __unsup_##function(void) asm(#function); \ + type __unsup_##function(void) \ + { \ + print_unsupported(#function); \ + errno = ENOSYS; \ + return ret; \ + } + +/* Err out on function call */ +#define unsupported_function(type, function, ret) \ + type __unsup_##function(void) asm(#function); \ + type __unsup_##function(void) \ + { \ + errno = ENOSYS; \ + return ret; \ + } + +#define NOFILE 32 +extern int xc_evtchn_close(int fd); + +pthread_mutex_t fd_lock = PTHREAD_MUTEX_INITIALIZER; +struct file files[NOFILE] = { + { .type = FTYPE_CONSOLE }, /* stdin */ + { .type = FTYPE_CONSOLE }, /* stdout */ + { .type = FTYPE_CONSOLE }, /* stderr */ +}; + +DECLARE_WAIT_QUEUE_HEAD(event_queue); + +int alloc_fd(enum fd_type type) +{ + int i; + pthread_mutex_lock(&fd_lock); + for (i=0; i 0; i--) + if (files[i].type != FTYPE_NONE) + close(i); + pthread_mutex_unlock(&fd_lock); +} + +int dup2(int oldfd, int newfd) +{ + pthread_mutex_lock(&fd_lock); + if (files[newfd].type != FTYPE_NONE) + close(newfd); + // XXX: this is a bit bogus, as we are supposed to share the offset etc + files[newfd] = files[oldfd]; + pthread_mutex_unlock(&fd_lock); + return 0; +} + +pid_t getpid(void) +{ + return 1; +} + +pid_t getppid(void) +{ + return 1; +} + +pid_t setsid(void) +{ + return 1; +} + +char *getcwd(char *buf, size_t size) +{ + snprintf(buf, size, "/"); + return buf; +} + +#define LOG_PATH "/var/log/" + +int mkdir(const char *pathname, mode_t mode) +{ + int ret; + ret = fs_create(fs_import, (char *) pathname, 1, mode); + if (ret < 0) { + errno = EIO; + return -1; + } + return 0; +} + +int open(const char *pathname, int flags, ...) +{ + int fs_fd, fd; + /* Ugly, but fine. */ + if (!strncmp(pathname,LOG_PATH,strlen(LOG_PATH))) { + fd = alloc_fd(FTYPE_CONSOLE); + printk("open(%s) -> %d\n", pathname, fd); + return fd; + } + printk("open(%s)", pathname); + fs_fd = fs_open(fs_import, (void *) pathname); + if (fs_fd < 0) { + errno = EIO; + return -1; + } + fd = alloc_fd(FTYPE_FILE); + printk("-> %d\n", fd); + files[fd].file.fd = fs_fd; + files[fd].file.offset = 0; + return fd; +} +#if defined(__x86_64__) || defined(__ia64__) +__typeof__(open) open64 __attribute__((__alias__("open"))); +#endif + +int isatty(int fd) +{ + return files[fd].type == FTYPE_CONSOLE; +} + +int read(int fd, void *buf, size_t nbytes) +{ + switch (files[fd].type) { + case FTYPE_CONSOLE: + return 0; + case FTYPE_FILE: { + ssize_t ret; + if (nbytes > PAGE_SIZE) + nbytes = PAGE_SIZE; + ret = fs_read(fs_import, files[fd].file.fd, buf, nbytes, files[fd].file.offset); + if (ret > 0) { + files[fd].file.offset += ret; + return ret; + } else if (ret < 0) { + errno = EIO; + return -1; + } + return 0; + } + case FTYPE_SOCKET: + return lwip_read(files[fd].socket.fd, buf, nbytes); + case FTYPE_TAP: { + ssize_t ret; + ret = netfront_receive(files[fd].tap.dev, buf, nbytes); + if (ret <= 0) { + errno = EAGAIN; + return -1; + } + return ret; + } + case FTYPE_NONE: + case FTYPE_XENBUS: + case FTYPE_EVTCHN: + case FTYPE_BLK: + break; + } + printk("read(%d): Bad descriptor\n", fd); + errno = EBADF; + return -1; +} + +int write(int fd, const void *buf, size_t nbytes) +{ + switch (files[fd].type) { + case FTYPE_CONSOLE: + console_print((char *)buf, nbytes); + return nbytes; + case FTYPE_FILE: { + ssize_t ret; + if (nbytes > PAGE_SIZE) + nbytes = PAGE_SIZE; + ret = fs_write(fs_import, files[fd].file.fd, (void *) buf, nbytes, files[fd].file.offset); + if (ret > 0) { + files[fd].file.offset += ret; + return ret; + } else if (ret < 0) { + errno = EIO; + return -1; + } + return 0; + } + case FTYPE_SOCKET: + return lwip_write(files[fd].socket.fd, (void*) buf, nbytes); + case FTYPE_TAP: + netfront_xmit(files[fd].tap.dev, (void*) buf, nbytes); + return nbytes; + case FTYPE_NONE: + case FTYPE_XENBUS: + case FTYPE_EVTCHN: + case FTYPE_BLK: + break; + } + printk("write(%d): Bad descriptor\n", fd); + errno = EBADF; + return -1; +} + +off_t lseek(int fd, off_t offset, int whence) +{ + if (files[fd].type != FTYPE_FILE) { + errno = ESPIPE; + return (off_t) -1; + } + switch (whence) { + case SEEK_SET: + files[fd].file.offset = offset; + break; + case SEEK_CUR: + files[fd].file.offset += offset; + break; + case SEEK_END: { + struct stat st; + int ret; + ret = fstat(fd, &st); + if (ret) + return -1; + files[fd].file.offset = st.st_size + offset; + break; + } + default: + errno = EINVAL; + return -1; + } + return files[fd].file.offset; +} +#if defined(__x86_64__) || defined(__ia64__) +__typeof__(lseek) lseek64 __attribute__((__alias__("lseek"))); +#endif + +int fsync(int fd) { + switch (files[fd].type) { + case FTYPE_FILE: { + int ret; + ret = fs_sync(fs_import, files[fd].file.fd); + if (ret < 0) { + errno = EIO; + return -1; + } + return 0; + } + case FTYPE_NONE: + case FTYPE_CONSOLE: + case FTYPE_SOCKET: + case FTYPE_XENBUS: + case FTYPE_EVTCHN: + case FTYPE_TAP: + case FTYPE_BLK: + break; + } + printk("fsync(%d): Bad descriptor\n", fd); + errno = EBADF; + return -1; +} + +int close(int fd) +{ + printk("close(%d)\n", fd); + switch (files[fd].type) { + case FTYPE_CONSOLE: + files[fd].type = FTYPE_NONE; + return 0; + case FTYPE_FILE: { + int ret = fs_close(fs_import, files[fd].file.fd); + files[fd].type = FTYPE_NONE; + if (ret < 0) { + errno = EIO; + return -1; + } + return 0; + } + case FTYPE_XENBUS: + xs_daemon_close((void*)(intptr_t) fd); + return 0; + case FTYPE_SOCKET: { + int res = lwip_close(files[fd].socket.fd); + files[fd].type = FTYPE_NONE; + return res; + } + case FTYPE_EVTCHN: + xc_evtchn_close(fd); + return 0; + case FTYPE_TAP: + shutdown_netfront(files[fd].tap.dev); + files[fd].type = FTYPE_NONE; + return 0; + case FTYPE_BLK: + shutdown_blkfront(files[fd].blk.dev); + files[fd].type = FTYPE_NONE; + return 0; + case FTYPE_NONE: + break; + } + printk("close(%d): Bad descriptor\n", fd); + errno = EBADF; + return -1; +} + +static void init_stat(struct stat *buf) +{ + memset(buf, 0, sizeof(*buf)); + buf->st_dev = 0; + buf->st_ino = 0; + buf->st_nlink = 1; + buf->st_rdev = 0; + buf->st_blksize = 4096; + buf->st_blocks = 0; +} + +static void stat_from_fs(struct stat *buf, struct fsif_stat_response *stat) +{ + buf->st_mode = stat->stat_mode; + buf->st_uid = stat->stat_uid; + buf->st_gid = stat->stat_gid; + buf->st_size = stat->stat_size; + buf->st_atime = stat->stat_atime; + buf->st_mtime = stat->stat_mtime; + buf->st_ctime = stat->stat_ctime; +} + +int stat(const char *path, struct stat *buf) +{ + struct fsif_stat_response stat; + int ret; + int fs_fd; + printk("stat(%s)\n", path); + fs_fd = fs_open(fs_import, (char*) path); + if (fs_fd < 0) { + errno = EIO; + ret = -1; + goto out; + } + ret = fs_stat(fs_import, fs_fd, &stat); + if (ret < 0) { + errno = EIO; + ret = -1; + goto outfd; + } + init_stat(buf); + stat_from_fs(buf, &stat); + ret = 0; + +outfd: + fs_close(fs_import, fs_fd); +out: + return ret; +} + +int fstat(int fd, struct stat *buf) +{ + init_stat(buf); + switch (files[fd].type) { + case FTYPE_CONSOLE: + case FTYPE_SOCKET: { + buf->st_mode = (files[fd].type == FTYPE_CONSOLE?S_IFCHR:S_IFSOCK) | S_IRUSR|S_IWUSR; + buf->st_uid = 0; + buf->st_gid = 0; + buf->st_size = 0; + buf->st_atime = + buf->st_mtime = + buf->st_ctime = time(NULL); + return 0; + } + case FTYPE_FILE: { + struct fsif_stat_response stat; + int ret; + ret = fs_stat(fs_import, files[fd].file.fd, &stat); + if (ret < 0) { + errno = EIO; + return -1; + } + /* The protocol is a bit evasive about this value */ + stat_from_fs(buf, &stat); + return 0; + } + case FTYPE_NONE: + case FTYPE_XENBUS: + case FTYPE_EVTCHN: + case FTYPE_TAP: + case FTYPE_BLK: + break; + } + + printk("statf(%d): Bad descriptor\n", fd); + errno = EBADF; + return -1; +} + +int ftruncate(int fd, off_t length) +{ + switch (files[fd].type) { + case FTYPE_FILE: { + int ret; + ret = fs_truncate(fs_import, files[fd].file.fd, length); + if (ret < 0) { + errno = EIO; + return -1; + } + return 0; + } + case FTYPE_NONE: + case FTYPE_CONSOLE: + case FTYPE_SOCKET: + case FTYPE_XENBUS: + case FTYPE_EVTCHN: + case FTYPE_TAP: + case FTYPE_BLK: + break; + } + + printk("ftruncate(%d): Bad descriptor\n", fd); + errno = EBADF; + return -1; +} + +int remove(const char *pathname) +{ + int ret; + printk("remove(%s)", pathname); + ret = fs_remove(fs_import, (char*) pathname); + if (ret < 0) { + errno = EIO; + return -1; + } + return 0; +} + +int unlink(const char *pathname) +{ + return remove(pathname); +} + +int rmdir(const char *pathname) +{ + return remove(pathname); +} + +int fcntl(int fd, int cmd, ...) +{ + long arg; + va_list ap; + va_start(ap, cmd); + arg = va_arg(ap, long); + va_end(ap); + + switch (cmd) { + case F_SETFL: + if (files[fd].type == FTYPE_SOCKET && !(arg & ~O_NONBLOCK)) { + /* Only flag supported: non-blocking mode */ + uint32_t nblock = !!(arg & O_NONBLOCK); + return lwip_ioctl(files[fd].socket.fd, FIONBIO, &nblock); + } + /* Fallthrough */ + default: + printk("fcntl(%d, %d, %lx/%lo)\n", fd, cmd, arg, arg); + errno = ENOSYS; + return -1; + } +} + +DIR *opendir(const char *name) +{ + DIR *ret; + ret = malloc(sizeof(*ret)); + ret->name = strdup(name); + ret->offset = 0; + ret->entries = NULL; + ret->curentry = -1; + ret->nbentries = 0; + ret->has_more = 1; + return ret; +} + +struct dirent *readdir(DIR *dir) +{ + if (dir->curentry >= 0) { + free(dir->entries[dir->curentry]); + dir->entries[dir->curentry] = NULL; + } + dir->curentry++; + if (dir->curentry >= dir->nbentries) { + dir->offset += dir->nbentries; + free(dir->entries); + dir->curentry = -1; + dir->nbentries = 0; + if (!dir->has_more) + return NULL; + dir->entries = fs_list(fs_import, dir->name, dir->offset, &dir->nbentries, &dir->has_more); + if (!dir->entries || !dir->nbentries) + return NULL; + dir->curentry = 0; + } + dir->dirent.d_name = dir->entries[dir->curentry]; + return &dir->dirent; +} +int closedir(DIR *dir) +{ + int i; + for (i=0; inbentries; i++) + free(dir->entries[i]); + free(dir->entries); + free(dir->name); + free(dir); + return 0; +} + +/* We assume that only the main thread calls select(). */ + +static const char file_types[] = { + [FTYPE_NONE] = 'N', + [FTYPE_CONSOLE] = 'C', + [FTYPE_FILE] = 'F', + [FTYPE_XENBUS] = 'X', + [FTYPE_EVTCHN] = 'E', + [FTYPE_SOCKET] = 'S', + [FTYPE_TAP] = 'T', + [FTYPE_BLK] = 'B', +}; +#ifdef LIBC_DEBUG +static void dump_set(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) +{ + int i, comma; +#define printfds(set) do {\ + comma = 0; \ + for (i = 0; i < nfds; i++) { \ + if (FD_ISSET(i, set)) { \ + if (comma) \ + printk(", "); \ + printk("%d(%c)", i, file_types[files[i].type]); \ + comma = 1; \ + } \ + } \ +} while (0) + + printk("["); + if (readfds) + printfds(readfds); + printk("], ["); + if (writefds) + printfds(writefds); + printk("], ["); + if (exceptfds) + printfds(exceptfds); + printk("], "); + if (timeout) + printk("{ %ld, %ld }", timeout->tv_sec, timeout->tv_usec); +} +#else +#define dump_set(nfds, readfds, writefds, exceptfds, timeout) +#endif + +/* Just poll without blocking */ +static int select_poll(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds) +{ + int i, n = 0, sock_n, sock_nfds = 0; + fd_set sock_readfds, sock_writefds, sock_exceptfds; + struct timeval timeout = { .tv_sec = 0, .tv_usec = 0}; + +#ifdef LIBC_VERBOSE + static int nb; + static int nbread[NOFILE], nbwrite[NOFILE], nbexcept[NOFILE]; + static s64_t lastshown; + + nb++; +#endif + + /* first poll network */ + FD_ZERO(&sock_readfds); + FD_ZERO(&sock_writefds); + FD_ZERO(&sock_exceptfds); + for (i = 0; i < nfds; i++) { + if (files[i].type == FTYPE_SOCKET) { + if (FD_ISSET(i, readfds)) { + FD_SET(files[i].socket.fd, &sock_readfds); + sock_nfds = i+1; + } + if (FD_ISSET(i, writefds)) { + FD_SET(files[i].socket.fd, &sock_writefds); + sock_nfds = i+1; + } + if (FD_ISSET(i, exceptfds)) { + FD_SET(files[i].socket.fd, &sock_exceptfds); + sock_nfds = i+1; + } + } + } + DEBUG("lwip_select("); + dump_set(nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout); + DEBUG("); -> "); + sock_n = lwip_select(sock_nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout); + dump_set(nfds, &sock_readfds, &sock_writefds, &sock_exceptfds, &timeout); + DEBUG("\n"); + + /* Then see others as well. */ + for (i = 0; i < nfds; i++) { + switch(files[i].type) { + case FTYPE_NONE: + if (FD_ISSET(i, readfds) || FD_ISSET(i, writefds) || FD_ISSET(i, exceptfds)) + printk("bogus fd %d in select\n", i); + /* Fallthrough. */ + case FTYPE_FILE: + FD_CLR(i, readfds); + FD_CLR(i, writefds); + FD_CLR(i, exceptfds); + break; + case FTYPE_CONSOLE: + FD_CLR(i, readfds); + if (FD_ISSET(i, writefds)) + n++; + FD_CLR(i, exceptfds); + break; + case FTYPE_XENBUS: + if (FD_ISSET(i, readfds)) { + if (files[i].xenbus.events) + n++; + else + FD_CLR(i, readfds); + } + FD_CLR(i, writefds); + FD_CLR(i, exceptfds); + break; + case FTYPE_EVTCHN: + case FTYPE_TAP: + case FTYPE_BLK: + if (FD_ISSET(i, readfds)) { + if (files[i].read) + n++; + else + FD_CLR(i, readfds); + } + FD_CLR(i, writefds); + FD_CLR(i, exceptfds); + break; + case FTYPE_SOCKET: + if (FD_ISSET(i, readfds)) { + /* Optimize no-network-packet case. */ + if (sock_n && FD_ISSET(files[i].socket.fd, &sock_readfds)) + n++; + else + FD_CLR(i, readfds); + } + if (FD_ISSET(i, writefds)) { + if (sock_n && FD_ISSET(files[i].socket.fd, &sock_writefds)) + n++; + else + FD_CLR(i, writefds); + } + if (FD_ISSET(i, exceptfds)) { + if (sock_n && FD_ISSET(files[i].socket.fd, &sock_exceptfds)) + n++; + else + FD_CLR(i, exceptfds); + } + break; + } +#ifdef LIBC_VERBOSE + if (FD_ISSET(i, readfds)) + nbread[i]++; + if (FD_ISSET(i, writefds)) + nbwrite[i]++; + if (FD_ISSET(i, exceptfds)) + nbexcept[i]++; +#endif + } +#ifdef LIBC_VERBOSE + if (NOW() > lastshown + 1000000000ull) { + lastshown = NOW(); + printk("%lu MB free, ", num_free_pages() / ((1 << 20) / PAGE_SIZE)); + printk("%d(%d): ", nb, sock_n); + for (i = 0; i < nfds; i++) { + if (nbread[i] || nbwrite[i] || nbexcept[i]) + printk(" %d(%c):", i, file_types[files[i].type]); + if (nbread[i]) + printk(" %dR", nbread[i]); + if (nbwrite[i]) + printk(" %dW", nbwrite[i]); + if (nbexcept[i]) + printk(" %dE", nbexcept[i]); + } + printk("\n"); + memset(nbread, 0, sizeof(nbread)); + memset(nbwrite, 0, sizeof(nbwrite)); + memset(nbexcept, 0, sizeof(nbexcept)); + nb = 0; + } +#endif + return n; +} + +/* The strategy is to + * - announce that we will maybe sleep + * - poll a bit ; if successful, return + * - if timeout, return + * - really sleep (except if somebody woke us in the meanwhile) */ +int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + struct timeval *timeout) +{ + int n, ret; + fd_set myread, mywrite, myexcept; + struct thread *thread = get_current(); + s_time_t start = NOW(), stop; + DEFINE_WAIT(w1); + DEFINE_WAIT(w2); + DEFINE_WAIT(w3); + DEFINE_WAIT(w4); + + assert(thread == main_thread); + + DEBUG("select(%d, ", nfds); + dump_set(nfds, readfds, writefds, exceptfds, timeout); + DEBUG(");\n"); + + if (timeout) + stop = start + SECONDS(timeout->tv_sec) + timeout->tv_usec * 1000; + else + /* just make gcc happy */ + stop = start; + + /* Tell people we're going to sleep before looking at what they are + * saying, hence letting them wake us if events happen between here and + * schedule() */ + add_waiter(w1, netfront_queue); + add_waiter(w2, event_queue); + add_waiter(w3, blkfront_queue); + add_waiter(w4, xenbus_watch_queue); + + myread = *readfds; + mywrite = *writefds; + myexcept = *exceptfds; + DEBUG("polling "); + dump_set(nfds, &myread, &mywrite, &myexcept, timeout); + DEBUG("\n"); + n = select_poll(nfds, &myread, &mywrite, &myexcept); + + if (n) { + dump_set(nfds, readfds, writefds, exceptfds, timeout); + if (readfds) + *readfds = myread; + if (writefds) + *writefds = mywrite; + if (exceptfds) + *exceptfds = myexcept; + DEBUG(" -> "); + dump_set(nfds, readfds, writefds, exceptfds, timeout); + DEBUG("\n"); + wake(thread); + ret = n; + goto out; + } + if (timeout && NOW() >= stop) { + if (readfds) + FD_ZERO(readfds); + if (writefds) + FD_ZERO(writefds); + if (exceptfds) + FD_ZERO(exceptfds); + timeout->tv_sec = 0; + timeout->tv_usec = 0; + wake(thread); + ret = 0; + goto out; + } + + if (timeout) + thread->wakeup_time = stop; + schedule(); + + myread = *readfds; + mywrite = *writefds; + myexcept = *exceptfds; + n = select_poll(nfds, &myread, &mywrite, &myexcept); + + if (n) { + if (readfds) + *readfds = myread; + if (writefds) + *writefds = mywrite; + if (exceptfds) + *exceptfds = myexcept; + ret = n; + goto out; + } + errno = EINTR; + ret = -1; + +out: + remove_waiter(w1); + remove_waiter(w2); + remove_waiter(w3); + remove_waiter(w4); + return ret; +} + +int socket(int domain, int type, int protocol) +{ + int fd, res; + fd = lwip_socket(domain, type, protocol); + if (fd < 0) + return -1; + res = alloc_fd(FTYPE_SOCKET); + printk("socket -> %d\n", res); + files[res].socket.fd = fd; + return res; +} + +int accept(int s, struct sockaddr *addr, socklen_t *addrlen) +{ + int fd, res; + if (files[s].type != FTYPE_SOCKET) { + printk("accept(%d): Bad descriptor\n", s); + errno = EBADF; + return -1; + } + fd = lwip_accept(files[s].socket.fd, addr, addrlen); + if (fd < 0) + return -1; + res = alloc_fd(FTYPE_SOCKET); + files[res].socket.fd = fd; + printk("accepted on %d -> %d\n", s, res); + return res; +} + +#define LWIP_STUB(ret, name, proto, args) \ +ret name proto \ +{ \ + if (files[s].type != FTYPE_SOCKET) { \ + printk(#name "(%d): Bad descriptor\n", s); \ + errno = EBADF; \ + return -1; \ + } \ + s = files[s].socket.fd; \ + return lwip_##name args; \ +} + +LWIP_STUB(int, bind, (int s, struct sockaddr *my_addr, socklen_t addrlen), (s, my_addr, addrlen)) +LWIP_STUB(int, getsockopt, (int s, int level, int optname, void *optval, socklen_t *optlen), (s, level, optname, optval, optlen)) +LWIP_STUB(int, setsockopt, (int s, int level, int optname, void *optval, socklen_t optlen), (s, level, optname, optval, optlen)) +LWIP_STUB(int, connect, (int s, struct sockaddr *serv_addr, socklen_t addrlen), (s, serv_addr, addrlen)) +LWIP_STUB(int, listen, (int s, int backlog), (s, backlog)); +LWIP_STUB(ssize_t, recv, (int s, void *buf, size_t len, int flags), (s, buf, len, flags)) +LWIP_STUB(ssize_t, recvfrom, (int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen), (s, buf, len, flags, from, fromlen)) +LWIP_STUB(ssize_t, send, (int s, void *buf, size_t len, int flags), (s, buf, len, flags)) +LWIP_STUB(ssize_t, sendto, (int s, void *buf, size_t len, int flags, struct sockaddr *to, socklen_t tolen), (s, buf, len, flags, to, tolen)) +LWIP_STUB(int, getsockname, (int s, struct sockaddr *name, socklen_t *namelen), (s, name, namelen)) + +int nanosleep(const struct timespec *req, struct timespec *rem) +{ + s_time_t start = NOW(); + s_time_t stop = start + SECONDS(req->tv_sec) + req->tv_nsec; + s_time_t stopped; + struct thread *thread = get_current(); + + thread->wakeup_time = stop; + clear_runnable(thread); + schedule(); + stopped = NOW(); + + if (rem) + { + s_time_t remaining = stop - stopped; + if (remaining > 0) + { + rem->tv_nsec = remaining % 1000000000ULL; + rem->tv_sec = remaining / 1000000000ULL; + } else memset(rem, 0, sizeof(*rem)); + } + + return 0; +} + +int usleep(useconds_t usec) +{ + /* "usec shall be less than one million." */ + struct timespec req; + req.tv_nsec = usec * 1000; + req.tv_sec = 0; + + if (nanosleep(&req, NULL)) + return -1; + + return 0; +} + +unsigned int sleep(unsigned int seconds) +{ + struct timespec req, rem; + req.tv_sec = seconds; + req.tv_nsec = 0; + + if (nanosleep(&req, &rem)) + return -1; + + if (rem.tv_nsec > 0) + rem.tv_sec++; + + return rem.tv_sec; +} + +int clock_gettime(clockid_t clk_id, struct timespec *tp) +{ + switch (clk_id) { + case CLOCK_MONOTONIC: + { + struct timeval tv; + + gettimeofday(&tv, NULL); + + tp->tv_sec = tv.tv_sec; + tp->tv_nsec = tv.tv_usec * 1000; + + break; + } + case CLOCK_REALTIME: + { + u64 nsec = monotonic_clock(); + + tp->tv_sec = nsec / 1000000000ULL; + tp->tv_nsec = nsec % 1000000000ULL; + + break; + } + default: + print_unsupported("clock_gettime(%d)", clk_id); + errno = EINVAL; + return -1; + } + + return 0; +} + +void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) +{ + ASSERT(!start); + length = (length + PAGE_SIZE - 1) & PAGE_MASK; + ASSERT(prot == (PROT_READ|PROT_WRITE)); + ASSERT(flags == (MAP_SHARED|MAP_ANON) || flags == (MAP_PRIVATE|MAP_ANON)); + ASSERT(fd == -1); + ASSERT(offset == 0); + + return map_zero(length / PAGE_SIZE, 1); +} +#if defined(__x86_64__) || defined(__ia64__) +__typeof__(mmap) mmap64 __attribute__((__alias__("mmap"))); +#endif + +int munmap(void *start, size_t length) +{ + int i, n = length / PAGE_SIZE; + multicall_entry_t call[n]; + unsigned char (*data)[PAGE_SIZE] = start; + int ret; + ASSERT(!((unsigned long)start & ~PAGE_MASK)); + ASSERT(!(length & ~PAGE_MASK)); + + for (i = 0; i < n; i++) { + call[i].op = __HYPERVISOR_update_va_mapping; + call[i].args[0] = (unsigned long) &data[i]; + call[i].args[1] = 0; + call[i].args[2] = 0; + call[i].args[3] = UVMF_INVLPG | UVMF_ALL; + } + + ret = HYPERVISOR_multicall(call, n); + if (ret) { + errno = -ret; + return -1; + } + + for (i = 0; i < n; i++) { + if (call[i].result) { + errno = call[i].result; + return -1; + } + } + return 0; +} + +/* Not supported by FS yet. */ +unsupported_function_crash(link); +unsupported_function(int, readlink, -1); + +/* We could support that. */ +unsupported_function_log(int, chdir, -1); + +/* No dynamic library support. */ +unsupported_function_log(void *, dlopen, NULL); +unsupported_function_log(void *, dlsym, NULL); +unsupported_function_log(char *, dlerror, NULL); +unsupported_function_log(int, dlclose, -1); + +/* We don't raise signals anyway. */ +unsupported_function(int, sigemptyset, -1); +unsupported_function(int, sigfillset, -1); +unsupported_function(int, sigaddset, -1); +unsupported_function(int, sigdelset, -1); +unsupported_function(int, sigismember, -1); +unsupported_function(int, sigprocmask, -1); +unsupported_function(int, sigaction, -1); +unsupported_function(int, __sigsetjmp, 0); +unsupported_function(int, sigaltstack, -1); +unsupported_function_crash(kill); + +/* Linuxish abi for the Caml runtime, don't support */ +unsupported_function_log(struct dirent *, readdir64, NULL); +unsupported_function_log(int, getrusage, -1); +unsupported_function_log(int, getrlimit, -1); +unsupported_function_log(int, getrlimit64, -1); +unsupported_function_log(int, __xstat64, -1); +unsupported_function_log(long, __strtol_internal, LONG_MIN); +unsupported_function_log(double, __strtod_internal, HUGE_VAL); +#endif diff --git a/extras/mini-os/lib/xs.c b/extras/mini-os/lib/xs.c new file mode 100644 index 0000000000..b654b0ee5d --- /dev/null +++ b/extras/mini-os/lib/xs.c @@ -0,0 +1,187 @@ +/* + * libxs-compatible layer + * + * Samuel Thibault , 2007-2008 + * + * Mere wrapper around xenbus_* + */ + +#ifdef HAVE_LIBC +#include +#include +#include +#include +#include +#include + +static inline int _xs_fileno(struct xs_handle *h) { + return (intptr_t) h; +} + +struct xs_handle *xs_daemon_open() +{ + int fd = alloc_fd(FTYPE_XENBUS); + files[fd].xenbus.events = NULL; + printk("xs_daemon_open -> %d, %p\n", fd, &files[fd].xenbus.events); + return (void*)(intptr_t) fd; +} + +void xs_daemon_close(struct xs_handle *h) +{ + int fd = _xs_fileno(h); + struct xenbus_event *event; + for (event = files[fd].xenbus.events; event; event = event->next) + free(event); + files[fd].type = FTYPE_NONE; +} + +int xs_fileno(struct xs_handle *h) +{ + return _xs_fileno(h); +} + +void *xs_read(struct xs_handle *h, xs_transaction_t t, + const char *path, unsigned int *len) +{ + char *value; + char *msg; + + msg = xenbus_read(t, path, &value); + if (msg) { + printk("xs_read(%s): %s\n", path, msg); + return NULL; + } + + if (len) + *len = strlen(value); + return value; +} + +bool xs_write(struct xs_handle *h, xs_transaction_t t, + const char *path, const void *data, unsigned int len) +{ + char value[len + 1]; + char *msg; + + memcpy(value, data, len); + value[len] = 0; + + msg = xenbus_write(t, path, value); + if (msg) { + printk("xs_write(%s): %s\n", path, msg); + return false; + } + return true; +} + +static bool xs_bool(char *reply) +{ + if (!reply) + return true; + free(reply); + return false; +} + +bool xs_rm(struct xs_handle *h, xs_transaction_t t, const char *path) +{ + return xs_bool(xenbus_rm(t, path)); +} + +static void *xs_talkv(struct xs_handle *h, xs_transaction_t t, + enum xsd_sockmsg_type type, + struct write_req *iovec, + unsigned int num_vecs, + unsigned int *len) +{ + struct xsd_sockmsg *msg; + void *ret; + + msg = xenbus_msg_reply(type, t, iovec, num_vecs); + ret = malloc(msg->len); + memcpy(ret, (char*) msg + sizeof(*msg), msg->len); + if (len) + *len = msg->len - 1; + free(msg); + return ret; +} + +static void *xs_single(struct xs_handle *h, xs_transaction_t t, + enum xsd_sockmsg_type type, + const char *string, + unsigned int *len) +{ + struct write_req iovec; + + iovec.data = (void *)string; + iovec.len = strlen(string) + 1; + + return xs_talkv(h, t, type, &iovec, 1, len); +} + +char *xs_get_domain_path(struct xs_handle *h, unsigned int domid) +{ + char domid_str[MAX_STRLEN(domid)]; + + sprintf(domid_str, "%u", domid); + + return xs_single(h, XBT_NULL, XS_GET_DOMAIN_PATH, domid_str, NULL); +} + +char **xs_directory(struct xs_handle *h, xs_transaction_t t, + const char *path, unsigned int *num) +{ + char *msg; + char **entries, **res; + char *entry; + int i, n; + int size; + + msg = xenbus_ls(t, path, &res); + if (msg) { + printk("xs_directory(%s): %s\n", path, msg); + return NULL; + } + + size = 0; + for (n = 0; res[n]; n++) + size += strlen(res[n]) + 1; + + entries = malloc(n * sizeof(char *) + size); + entry = (char *) (&entries[n]); + + for (i = 0; i < n; i++) { + int l = strlen(res[i]) + 1; + memcpy(entry, res[i], l); + free(res[i]); + entries[i] = entry; + entry += l; + } + + *num = n; + return entries; +} + +bool xs_watch(struct xs_handle *h, const char *path, const char *token) +{ + int fd = _xs_fileno(h); + printk("xs_watch(%s, %s)\n", path, token); + return xs_bool(xenbus_watch_path_token(XBT_NULL, path, token, &files[fd].xenbus.events)); +} + +char **xs_read_watch(struct xs_handle *h, unsigned int *num) +{ + int fd = _xs_fileno(h); + struct xenbus_event *event; + event = files[fd].xenbus.events; + files[fd].xenbus.events = event->next; + printk("xs_read_watch() -> %s %s\n", event->path, event->token); + *num = 2; + return (char **) &event->path; +} + +bool xs_unwatch(struct xs_handle *h, const char *path, const char *token) +{ + printk("xs_unwatch(%s, %s)\n", path, token); + return xs_bool(xenbus_unwatch_path_token(XBT_NULL, path, token)); +} +#endif diff --git a/extras/mini-os/main-caml.c b/extras/mini-os/main-caml.c new file mode 100644 index 0000000000..dd55aca38f --- /dev/null +++ b/extras/mini-os/main-caml.c @@ -0,0 +1,42 @@ +/* + * Caml bootstrap + * + * Samuel Thibault , January 2008 + */ + +#include +#include + +#include +#include +#include + +/* Ugly binary compatibility with Linux */ +FILE *_stderr asm("stderr"); +int *__errno_location; +/* Will probably break everything, probably need to fetch from glibc */ +void *__ctype_b_loc; + +int main(int argc, char *argv[], char *envp[]) +{ + value *val; + + /* Get current thread's value */ + _stderr = stderr; + __errno_location = &errno; + + printf("starting caml\n"); + + /* Wait before things might hang up */ + sleep(1); + + caml_startup(argv); + val = caml_named_value("main"); + if (!val) { + printf("Couldn't find Caml main"); + return 1; + } + caml_callback(*val, Val_int(0)); + printf("callback returned\n"); + return 0; +} diff --git a/extras/mini-os/main.c b/extras/mini-os/main.c new file mode 100644 index 0000000000..345f7e9487 --- /dev/null +++ b/extras/mini-os/main.c @@ -0,0 +1,167 @@ +/* + * POSIX-compatible main layer + * + * Samuel Thibault , October 2007 + */ + +#ifdef HAVE_LIBC +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int main(int argc, char *argv[], char *envp[]); +extern void __libc_init_array(void); +extern void __libc_fini_array(void); + +struct thread *main_thread; + +#if 0 +#include +int main(int argc, char *argv[], char *envp[]) +{ + printf("Hello, World!\n"); + return 1; +} +#endif + +void _init(void) +{ +} + +void _fini(void) +{ +} + +static void call_main(void *p) +{ + char *args, /**path,*/ *msg, *c; + int argc; + char **argv; + char *envp[] = { NULL }; + char *vm; + int i; + char path[128]; + + /* Let other parts initialize (including console output) before maybe + * crashing. */ + //sleep(1); + + start_networking(); + init_fs_frontend(); + +#ifdef CONFIG_QEMU + if (!fs_import) { + printk("No FS backend found, is it running?\n"); + do_exit(); + } + + /* Fetch argc, argv from XenStore */ + char domid_s[10]; + int domid; + domid = xenbus_read_integer("target"); + if (domid == -1) { + printk("Couldn't read target\n"); + do_exit(); + } + snprintf(domid_s, sizeof(domid_s), "%d", domid); + + snprintf(path, sizeof(path), "/local/domain/%d/vm", domid); + msg = xenbus_read(XBT_NIL, path, &vm); + if (msg) { + printk("Couldn't read vm path\n"); + do_exit(); + } + printk("vm is at %s\n", vm); +#else + msg = xenbus_read(XBT_NIL, "vm", &vm); + if (msg) { + printk("Couldn't read vm path\n"); + do_exit(); + } +#endif + + snprintf(path, sizeof(path), "%s/image/dmargs", vm); + free(vm); + msg = xenbus_read(XBT_NIL, path, &args); + + if (msg) { + printk("Couldn't get stubdom args: %s\n", msg); + args = strdup(""); + } + + argc = 1; +#ifdef CONFIG_QEMU + argc += 2; +#endif + c = args; + while (*c) { + if (*c != ' ') { + argc++; + while (*c && *c != ' ') + c++; + } else { + while (*c == ' ') + c++; + } + } + argv = alloca((argc + 1) * sizeof(char *)); + argv[0] = "main"; + argc = 1; +#ifdef CONFIG_QEMU + argv[1] = "-d"; + argv[2] = domid_s; + argc += 2; +#endif + c = args; + while (*c) { + if (*c != ' ') { + argv[argc++] = c; + while (*c && *c != ' ') + c++; + } else { + *c++ = 0; + while (*c == ' ') + c++; + } + } + argv[argc] = NULL; + + for (i = 0; i < argc; i++) + printf("\"%s\" ", argv[i]); + printf("\n"); + + __libc_init_array(); + environ = envp; + tzset(); + + exit(main(argc, argv, envp)); +} + +void _exit(int ret) +{ + close_all_files(); + __libc_fini_array(); + printk("main returned %d\n", ret); + unbind_all_ports(); + if (!ret) { + /* No problem, just shutdown. */ + struct sched_shutdown sched_shutdown = { .reason = SHUTDOWN_poweroff }; + HYPERVISOR_sched_op(SCHEDOP_shutdown, &sched_shutdown); + } + do_exit(); +} + +int app_main(start_info_t *si) +{ + printk("Dummy main: start_info=%p\n", si); + main_thread = create_thread("main", call_main, si); + return 0; +} +#endif diff --git a/extras/mini-os/minios.mk b/extras/mini-os/minios.mk index fa6f6bd0c9..078c396fc2 100644 --- a/extras/mini-os/minios.mk +++ b/extras/mini-os/minios.mk @@ -9,7 +9,7 @@ debug = y DEF_CFLAGS += -fno-builtin -Wall -Werror -Wredundant-decls -Wno-format DEF_CFLAGS += $(call cc-option,$(CC),-fno-stack-protector,) DEF_CFLAGS += -Wstrict-prototypes -Wnested-externs -Wpointer-arith -Winline -DEF_CFLAGS += -D__XEN_INTERFACE_VERSION__=$(XEN_INTERFACE_VERSION) +DEF_CPPFLAGS += -D__XEN_INTERFACE_VERSION__=$(XEN_INTERFACE_VERSION) DEF_ASFLAGS = -D__ASSEMBLY__ DEF_LDFLAGS = @@ -24,12 +24,10 @@ endif # 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) +CPPFLAGS := $(DEF_CPPFLAGS) $(ARCH_CPPFLAGS) ASFLAGS := $(DEF_ASFLAGS) $(ARCH_ASFLAGS) LDFLAGS := $(DEF_LDFLAGS) $(ARCH_LDFLAGS) -# The path pointing to the architecture specific header files. -ARCH_INC := $(MINI-OS_ROOT)/include/$(TARGET_ARCH_FAM) - # Special build dependencies. # Rebuild all after touching this/these file(s) EXTRA_DEPS = $(MINI-OS_ROOT)/minios.mk \ @@ -44,18 +42,17 @@ 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_INC) $(extra_incl) +override CPPFLAGS := $(CPPFLAGS) $(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_NAME = $(XEN_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_ARCH_OBJ := $(XEN_TARGET_ARCH).o HEAD_OBJ := $(TARGET_ARCH_DIR)/$(HEAD_ARCH_OBJ) diff --git a/extras/mini-os/mm.c b/extras/mini-os/mm.c index 11e249d421..f204fa66ec 100644 --- a/extras/mini-os/mm.c +++ b/extras/mini-os/mm.c @@ -360,6 +360,29 @@ void free_pages(void *pointer, int order) } +#ifdef HAVE_LIBC +void *sbrk(ptrdiff_t increment) +{ + unsigned long old_brk = brk; + unsigned long new_brk = old_brk + increment; + + if (new_brk > heap_end) { + printk("Heap exhausted: %p + %lx = %p > %p\n", old_brk, increment, new_brk, heap_end); + return NULL; + } + + if (new_brk > heap_mapped) { + unsigned long n = (new_brk - heap_mapped + PAGE_SIZE - 1) / PAGE_SIZE; + do_map_zero(heap_mapped, n); + heap_mapped += n * PAGE_SIZE; + } + + brk = new_brk; + + return (void *) old_brk; +} +#endif + void init_mm(void) diff --git a/extras/mini-os/netfront.c b/extras/mini-os/netfront.c index e3c56c10c4..095f55ca15 100644 --- a/extras/mini-os/netfront.c +++ b/extras/mini-os/netfront.c @@ -19,7 +19,10 @@ DECLARE_WAIT_QUEUE_HEAD(netfront_queue); +#ifdef HAVE_LIBC #define NETIF_SELECT_RX ((void*)-1) +#endif + #define NET_TX_RING_SIZE __RING_SIZE((struct netif_tx_sring *)0, PAGE_SIZE) @@ -50,6 +53,13 @@ struct netfront_dev { char *nodename; char *backend; +#ifdef HAVE_LIBC + int fd; + unsigned char *data; + size_t len; + size_t rlen; +#endif + void (*netif_rx)(unsigned char* data, int len); }; @@ -92,7 +102,8 @@ moretodo: cons = dev->rx.rsp_cons; int nr_consumed=0; - while ((cons != rp)) + int some = 0; + while ((cons != rp) && !some) { struct net_buffer* buf; unsigned char* page; @@ -116,7 +127,18 @@ moretodo: if(rx->status>0) { - dev->netif_rx(page+rx->offset,rx->status); +#ifdef HAVE_LIBC + if (dev->netif_rx == NETIF_SELECT_RX) { + int len = rx->status; + ASSERT(current == main_thread); + if (len > dev->len) + len = dev->len; + memcpy(dev->data, page+rx->offset, len); + dev->rlen = len; + some = 1; + } else +#endif + dev->netif_rx(page+rx->offset,rx->status); } nr_consumed++; @@ -127,7 +149,7 @@ moretodo: int more; RING_FINAL_CHECK_FOR_RESPONSES(&dev->rx,more); - if(more) goto moretodo; + if(more && !some) goto moretodo; RING_IDX req_prod = dev->rx.req_prod_pvt; @@ -178,6 +200,9 @@ void network_tx_buf_gc(struct netfront_dev *dev) if (txrsp->status == NETIF_RSP_NULL) continue; + if (txrsp->status == NETIF_RSP_ERROR) + printk("packet error\n"); + id = txrsp->id; struct net_buffer* buf = &dev->tx_buffers[id]; gnttab_end_access(buf->gref); @@ -218,6 +243,22 @@ void netfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data) local_irq_restore(flags); } +#ifdef HAVE_LIBC +void netfront_select_handler(evtchn_port_t port, struct pt_regs *regs, void *data) +{ + int flags; + struct netfront_dev *dev = data; + int fd = dev->fd; + + local_irq_save(flags); + network_tx_buf_gc(dev); + local_irq_restore(flags); + + files[fd].read = 1; + wake_up(&netfront_queue); +} +#endif + struct netfront_dev *init_netfront(char *nodename, void (*thenetif_rx)(unsigned char* data, int len), unsigned char rawmac[6]) { xenbus_transaction_t xbt; @@ -266,7 +307,12 @@ struct netfront_dev *init_netfront(char *nodename, void (*thenetif_rx)(unsigned dev->dom = op.remote_dom = xenbus_read_integer(path); HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op); clear_evtchn(op.port); /* Without, handler gets invoked now! */ - dev->local_port = bind_evtchn(op.port, netfront_handler, dev); +#ifdef HAVE_LIBC + if (thenetif_rx == NETIF_SELECT_RX) + dev->local_port = bind_evtchn(op.port, netfront_select_handler, dev); + else +#endif + dev->local_port = bind_evtchn(op.port, netfront_handler, dev); dev->evtchn=op.port; txs = (struct netif_tx_sring*) alloc_page(); @@ -381,6 +427,23 @@ done: return dev; } +#ifdef HAVE_LIBC +int netfront_tap_open(char *nodename) { + struct netfront_dev *dev; + + dev = init_netfront(nodename, NETIF_SELECT_RX, NULL); + if (!dev) { + printk("TAP open failed\n"); + errno = EIO; + return -1; + } + dev->fd = alloc_fd(FTYPE_TAP); + printk("tap_open(%s) -> %d\n", nodename, dev->fd); + files[dev->fd].tap.dev = dev; + return dev->fd; +} +#endif + void shutdown_netfront(struct netfront_dev *dev) { char* err; @@ -481,3 +544,30 @@ void netfront_xmit(struct netfront_dev *dev, unsigned char* data,int len) network_tx_buf_gc(dev); local_irq_restore(flags); } + +#ifdef HAVE_LIBC +ssize_t netfront_receive(struct netfront_dev *dev, unsigned char *data, size_t len) +{ + unsigned long flags; + int fd = dev->fd; + ASSERT(current == main_thread); + + dev->rlen = 0; + dev->data = data; + dev->len = len; + + local_irq_save(flags); + network_rx(dev); + if (!dev->rlen) + /* No data for us, make select stop returning */ + files[fd].read = 0; + /* Before re-enabling the interrupts, in case a packet just arrived in the + * meanwhile. */ + local_irq_restore(flags); + + dev->data = NULL; + dev->len = 0; + + return dev->rlen; +} +#endif diff --git a/extras/mini-os/sched.c b/extras/mini-os/sched.c index 18b3f01538..19a102f056 100644 --- a/extras/mini-os/sched.c +++ b/extras/mini-os/sched.c @@ -56,6 +56,7 @@ struct thread *idle_thread = NULL; LIST_HEAD(exited_threads); +static int threads_started; void inline print_runqueue(void) { @@ -172,6 +173,9 @@ struct thread* create_thread(char *name, void (*function)(void *), void *data) /* Not runable, not exited, not sleeping */ thread->flags = 0; thread->wakeup_time = 0LL; +#ifdef HAVE_LIBC + _REENT_INIT_PTR((&thread->reent)) +#endif set_runnable(thread); local_irq_save(flags); if(idle_thread != NULL) { @@ -185,6 +189,42 @@ struct thread* create_thread(char *name, void (*function)(void *), void *data) return thread; } +#ifdef HAVE_LIBC +static struct _reent callback_reent; +struct _reent *__getreent(void) +{ + struct _reent *_reent; + + if (!threads_started) + _reent = _impure_ptr; + else if (in_callback) + _reent = &callback_reent; + else + _reent = &get_current()->reent; + +#ifndef NDEBUG +#if defined(__x86_64__) || defined(__x86__) + { +#ifdef __x86_64__ + register unsigned long sp asm ("rsp"); +#else + register unsigned long sp asm ("esp"); +#endif + if ((sp & (STACK_SIZE-1)) < STACK_SIZE / 16) { + static int overflowing; + if (!overflowing) { + overflowing = 1; + printk("stack overflow\n"); + BUG(); + } + } + } +#endif +#endif + return _reent; +} +#endif + void exit_thread(void) { unsigned long flags; @@ -228,6 +268,7 @@ void wake(struct thread *thread) void idle_thread_fn(void *unused) { s_time_t until; + threads_started = 1; unsigned long flags; struct list_head *iterator; struct thread *next, *thread; @@ -297,6 +338,9 @@ void init_sched(void) { printk("Initialising scheduler\n"); +#ifdef HAVE_LIBC + _REENT_INIT_PTR((&callback_reent)) +#endif idle_thread = create_thread("Idle", idle_thread_fn, NULL); INIT_LIST_HEAD(&idle_thread->thread_list); } diff --git a/stubdom/Makefile b/stubdom/Makefile new file mode 100644 index 0000000000..ca2f342c3a --- /dev/null +++ b/stubdom/Makefile @@ -0,0 +1,256 @@ +XEN_ROOT = .. + +include $(XEN_ROOT)/Config.mk +export stubdom=y +export debug=y + +IOEMU_OPTIONS=--disable-vnc-tls +BINUTILS_VERSION=2.18 +GCC_VERSION=4.2.2 +ZLIB_VERSION=1.2.3 +LIBPCI_VERSION=2.2.9 +NEWLIB_DATE=2008-01-01 +LWIP_DATE=2008-02-08 + +WGET=wget -c + +GNU_TARGET_ARCH:=$(XEN_TARGET_ARCH) +ifeq ($(XEN_TARGET_ARCH),x86_32) +GNU_TARGET_ARCH:=i686 +endif + +ifeq ($(GNU_TARGET_ARCH), i686) +TARGET_CFLAGS= +endif +ifeq ($(GNU_TARGET_ARCH), x86_64) +TARGET_CFLAGS=-mno-red-zone +endif +ifeq ($(GNU_TARGET_ARCH), ia64) +TARGET_CFLAGS=-mconstant-gp +endif + +CROSS_ROOT=cross-root-$(GNU_TARGET_ARCH) +CROSS_PREFIX=$(CURDIR)/$(CROSS_ROOT) +export CROSS_COMPILE=$(GNU_TARGET_ARCH)-xen-elf- +export PATH:=$(CROSS_PREFIX)/bin:$(PATH) + +.PHONY: all +all: qemu-stubdom + +################ +# Cross-binutils +################ + +binutils-$(BINUTILS_VERSION).tar.bz2: + $(WGET) http://ftp.gnu.org/gnu/binutils/$@ +binutils-$(BINUTILS_VERSION): binutils-$(BINUTILS_VERSION).tar.bz2 + tar xjf $@.tar.bz2 + ( cd binutils-$(BINUTILS_VERSION) && patch -p1 < ../binutils.patch ) + touch $@ + +BINUTILS_STAMPFILE=$(CROSS_ROOT)/bin/$(GNU_TARGET_ARCH)-xen-elf-ar +.PHONY: cross-binutils +cross-binutils: $(BINUTILS_STAMPFILE) +$(BINUTILS_STAMPFILE): binutils-$(BINUTILS_VERSION) + mkdir -p binutils.build + ( cd binutils.build && \ + ../binutils-$(BINUTILS_VERSION)/configure --prefix=$(CROSS_PREFIX) --verbose --target=$(GNU_TARGET_ARCH)-xen-elf && \ + $(MAKE) && \ + $(MAKE) check && \ + $(MAKE) install ) + +########### +# Cross-gcc +########### + +gcc-$(GCC_VERSION).tar.bz2: + $(WGET) http://ftp.gnu.org/gnu/gcc/gcc-$(GCC_VERSION)/gcc-$(GCC_VERSION).tar.bz2 +gcc-$(GCC_VERSION): gcc-$(GCC_VERSION).tar.bz2 + tar xjf gcc-$(GCC_VERSION).tar.bz2 + ( cd gcc-$(GCC_VERSION) && patch -p1 < ../gcc.patch ) + touch $@ + +GCC_STAMPFILE=$(CROSS_ROOT)/bin/$(GNU_TARGET_ARCH)-xen-elf-gcc-$(GCC_VERSION) +.PHONY: cross-gcc +cross-gcc: $(GCC_STAMPFILE) +$(GCC_STAMPFILE): gcc-$(GCC_VERSION) $(BINUTILS_STAMPFILE) + mkdir -p gcc.build + ( cd gcc.build && \ + ../gcc-$(GCC_VERSION)/configure --prefix=$(CROSS_PREFIX) --verbose --target=$(GNU_TARGET_ARCH)-xen-elf --enable-languages=c --disable-libssp --with-gnu-as --with-gnu-ld && \ + $(MAKE) GCC_FOR_TARGET='$$$$r/gcc/xgcc -B$$$$r/gcc/ '"$(TARGET_CFLAGS)"' $$(FLAGS_FOR_TARGET)' && \ + $(MAKE) install ) + +############## +# Cross-newlib +############## + +newlib: + cvs -z 9 -d :pserver:anoncvs@sources.redhat.com:/cvs/src co -D $(NEWLIB_DATE) newlib + mv src newlib + ( cd newlib && patch -p0 < ../newlib.patch) + +NEWLIB_STAMPFILE=$(CROSS_ROOT)/$(GNU_TARGET_ARCH)-xen-elf/lib/libc.a +.PHONY: cross-newlib +cross-newlib: $(NEWLIB_STAMPFILE) +$(NEWLIB_STAMPFILE): newlib $(GCC_STAMPFILE) + mkdir -p newlib.build + ( cd newlib.build && \ + CC_FOR_TARGET="$(GNU_TARGET_ARCH)-xen-elf-gcc $(TARGET_CFLAGS)" ../newlib/configure --prefix=$(CROSS_PREFIX) --verbose --target=$(GNU_TARGET_ARCH)-xen-elf --enable-newlib-io-long-long && \ + $(MAKE) && \ + $(MAKE) install ) + +############ +# Cross-zlib +############ + +zlib-$(ZLIB_VERSION).tar.gz: + $(WGET) http://www.zlib.net/zlib-$(ZLIB_VERSION).tar.gz + +ZLIB_STAMPFILE=$(CROSS_ROOT)/$(GNU_TARGET_ARCH)-xen-elf/lib/libz.a +.PHONY: cross-zlib +cross-zlib: $(ZLIB_STAMPFILE) +$(ZLIB_STAMPFILE): zlib-$(ZLIB_VERSION).tar.gz $(NEWLIB_STAMPFILE) + tar xzf $< + ( cd zlib-$(ZLIB_VERSION) && \ + CFLAGS="$(TARGET_CFLAGS)" CC=$(GNU_TARGET_ARCH)-xen-elf-gcc ./configure --prefix=$(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf && \ + $(MAKE) libz.a && \ + $(MAKE) install ) + +############## +# Cross-libpci +############## + +pciutils-$(LIBPCI_VERSION).tar.bz2: + $(WGET) http://www.kernel.org/pub/software/utils/pciutils/pciutils-$(LIBPCI_VERSION).tar.bz2 + +LIBPCI_STAMPFILE=$(CROSS_ROOT)/$(GNU_TARGET_ARCH)-xen-elf/lib/libpci.a +.PHONY: cross-libpci +cross-libpci: $(LIBPCI_STAMPFILE) +$(LIBPCI_STAMPFILE): pciutils-$(LIBPCI_VERSION).tar.bz2 $(NEWLIB_STAMPFILE) $(ZLIB_STAMPFILE) + tar xjf $< + ( cd pciutils-$(LIBPCI_VERSION) && \ + cp ../libpci.config.h lib/config.h && \ + echo '#define PCILIB_VERSION "$(LIBPCI_VERSION)"' >> lib/config.h && \ + cp ../libpci.config.mak lib/config.mk && \ + $(MAKE) CC="$(GNU_TARGET_ARCH)-xen-elf-gcc $(TARGET_CFLAGS)" lib/libpci.a && \ + $(INSTALL_DATA) lib/libpci.a $(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/lib/ && \ + $(INSTALL_DIR) $(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/include/pci && \ + $(INSTALL_DATA) lib/{config,header,pci,types}.h $(CROSS_PREFIX)/$(GNU_TARGET_ARCH)-xen-elf/include/pci/ \ + ) + +###### +# lwIP +###### + +lwip: + cvs -z 9 -d :pserver:anonymous@cvs.savannah.nongnu.org:/sources/lwip co -D $(LWIP_DATE) lwip + +####### +# Links +####### + +.PHONY: $(CROSS_ROOT) +$(CROSS_ROOT): cross-newlib cross-zlib cross-libpci + +.PHONY: mk-symlinks +mk-symlinks: + [ -h include ] || ln -sf ../tools/include . + mkdir -p libxc + [ -h libxc/Makefile ] || ( cd libxc && \ + ln -sf ../../tools/libxc/*.h . && \ + ln -sf ../../tools/libxc/*.c . && \ + ln -sf ../../tools/libxc/Makefile . ) + mkdir -p libxc/$(XEN_TARGET_ARCH) + [ -h libxc/$(XEN_TARGET_ARCH) ] || ( cd libxc/$(XEN_TARGET_ARCH) && \ + ln -sf ../../tools/libxc/$(XEN_TARGET_ARCH)/*.c . && \ + ln -sf ../../tools/libxc/$(XEN_TARGET_ARCH)/*.h . && \ + ln -sf ../../tools/libxc/$(XEN_TARGET_ARCH)/Makefile . ) + mkdir -p ioemu + [ -h ioemu/Makefile ] || ( cd ioemu && \ + ln -sf ../../tools/ioemu/* . && \ + ([ ! -h config-host.h ] || rm -f config-host.h) && \ + ([ ! -h config-host.mak ] || rm -f config-host.mak) ) + [ -h mini-os ] || ln -sf ../extras/mini-os . + +####### +# libxc +####### + +.PHONY: libxc +libxc: cross-zlib mk-symlinks + $(MAKE) -C $@ + +####### +# ioemu +####### + +.PHONY: ioemu +ioemu: cross-zlib cross-libpci mk-symlinks libxc + [ -f ioemu/config-host.mak ] || \ + ( cd ioemu ; XEN_TARGET_ARCH=$(XEN_TARGET_ARCH) sh configure --prefix=/usr --enable-stubdom $(IOEMU_OPTIONS)) + $(MAKE) -C ioemu LWIPDIR=$(CURDIR)/lwip + +###### +# caml +###### + +.PHONY: caml +caml: + $(MAKE) -C $@ + +######## +# minios +######## + +.PHONY: qemu-stubdom +qemu-stubdom: mk-symlinks lwip libxc ioemu + $(MAKE) -C mini-os LWIPDIR=$(CURDIR)/lwip QEMUDIR=$(CURDIR)/ioemu + +.PHONY: caml-stubdom +caml-stubdom: mk-symlinks lwip libxc cross-libpci caml + $(MAKE) -C mini-os LWIPDIR=$(CURDIR)/lwip CAMLDIR=$(CURDIR)/caml + +######### +# install +######### + +install: mini-os/mini-os.gz + $(INSTALL_PROG) stubdom-dm "$(DESTDIR)/usr/lib/xen/bin" + $(INSTALL_PROG) mini-os/mini-os.gz "$(DESTDIR)/usr/lib/xen/boot/stubdom.gz" + +####### +# clean +####### + +# Only clean the libxc/ioemu/mini-os part +.PHONY: clean +clean: + -$(MAKE) -C mini-os LWIPDIR=$(CURDIR)/lwip clean + $(MAKE) -C caml clean + rm -fr libxc ioemu mini-os include + +# clean the cross-compilation result +.PHONY: crossclean +crossclean: clean + rm -fr $(CROSS_ROOT) + rm -fr binutils.build gcc.build newlib.build + rm -fr zlib-$(ZLIB_VERSION) pciutils-$(LIBPCI_VERSION) + +# clean patched sources +.PHONY: patchclean +patchclean: crossclean + rm -fr binutils-$(BINUTILS_VERSION) + rm -fr gcc-$(GCC_VERSION) + rm -fr newlib + rm -fr lwip + +# clean downloads +.PHONY: downloadclean +downloadclean: patchclean + rm -f binutils-$(BINUTILS_VERSION).tar.bz2 + rm -f gcc-$(GCC_VERSION).tar.bz2 + rm -f zlib-$(ZLIB_VERSION).tar.gz + rm -f pciutils-$(LIBPCI_VERSION).tar.bz2 + +.PHONY: distclean +distclean: downloadclean diff --git a/stubdom/README b/stubdom/README new file mode 100644 index 0000000000..42c47601fa --- /dev/null +++ b/stubdom/README @@ -0,0 +1,41 @@ +To compile +========== + +Just run make -j 4, that will download / patch / compile +Then make install to install the result. + +Also, run make and make install in $XEN_ROOT/tools/fs-back + +To run +====== + +mkdir -p /exports/usr/share/qemu +ln -s /usr/share/qemu/keymaps /exports/usr/share/qemu +/usr/sbin/fs-backend & + + +In your HVM config "hvmconfig", + +- use VNC, set vnclisten to "172.30.206.1" for instance: + +vnc=1 +vnclisten="172.30.206.1" + +- use /usr/lib/xen/bin/stubdom-dm as dm script + +device_model = '/usr/lib/xen/bin/stubdom-dm' + +- comment the disk statement: +#disk = [ 'file:/tmp/install.iso,hdc:cdrom,r', 'phy:/dev/sda6,hda,w', 'file:/tmp/test,hdb,r' ] + +Create /etc/xen/stubdom-hvmconfig ("hvmconfig" must match your main config file) +with + +kernel="/usr/lib/xen/boot/stubdom.gz" +vif=[ 'ip=172.30.206.1', 'ip=10.0.1.1,mac=aa:00:00:12:23:34'] +disk = [ 'file:/tmp/install.iso,hdc:cdrom,r', 'phy:/dev/sda6,hda,w', 'file:/tmp/test,hdb,r' ] + +where +- 172.30.206.1 is the IP for vnc, +- 'ip=10.0.1.1,mac=' is the same net configuration as in the hvmconfig script, +- and disk = is the same block configuration as in the hvmconfig script. diff --git a/stubdom/caml/Makefile b/stubdom/caml/Makefile new file mode 100644 index 0000000000..69595a8f99 --- /dev/null +++ b/stubdom/caml/Makefile @@ -0,0 +1,18 @@ +XEN_ROOT = ../.. + +include $(XEN_ROOT)/Config.mk + +OCAMLFIND=ocamlfind +OCAMLOPT=ocamlopt + +OBJS := hello.cmx +LIBS := + +%.cmx: %.ml + $(OCAMLFIND) $(OCAMLOPT) -c $< -o $@ + +caml.o: $(OBJS) + $(OCAMLFIND) $(OCAMLOPT) $(LIBS) $^ -output-obj -o $@ + +clean: + rm -f *.o *.cmx *.cmi diff --git a/stubdom/caml/hello.ml b/stubdom/caml/hello.ml new file mode 100644 index 0000000000..3a7181134a --- /dev/null +++ b/stubdom/caml/hello.ml @@ -0,0 +1,4 @@ +let main arg = + Printf.printf "Hello, world!\n%!." + +let _ = Callback.register "main" main diff --git a/stubdom/libpci.config.h b/stubdom/libpci.config.h new file mode 100644 index 0000000000..a84ead5708 --- /dev/null +++ b/stubdom/libpci.config.h @@ -0,0 +1,5 @@ +#define PCI_OS_STUBDOM +#define PCI_HAVE_STDINT_H +#define PCI_PATH_IDS_DIR "." +#define PCI_COMPRESSED_IDS +#define PCI_IDS "pci.ids.gz" diff --git a/stubdom/libpci.config.mak b/stubdom/libpci.config.mak new file mode 100644 index 0000000000..5bc5b261d0 --- /dev/null +++ b/stubdom/libpci.config.mak @@ -0,0 +1,2 @@ +LIBZ=-lz +LDLIBS+=$(LIBZ) diff --git a/stubdom/stubdom-dm b/stubdom/stubdom-dm new file mode 100644 index 0000000000..3edeb9d2dc --- /dev/null +++ b/stubdom/stubdom-dm @@ -0,0 +1,97 @@ +#!/bin/bash +# +# Copyright 2007-2008 Samuel Thibault +# +# dm script around stubdomains. +# + +# To fit xterms nicely +height=339 + +# Parse arguments + +domid= +domname= +vncviewer=0 +vncpid= +while [ "$#" -gt 0 ]; +do + if [ "$#" -ge 2 ]; + then + case "$1" in + -d) domid=$2; shift ;; + -domain-name) domname=$2; shift ;; + -vnc) + ip=${2%:*}; + vnc_port=${2#*:}; + shift + ;; + esac + fi + case "$1" in + -vncviewer) vncviewer=1 ;; + esac + shift +done + +[ -z "$domid" ] && ( echo "couldn't find domain ID" ; exit 1 ) +[ -z "$domname" ] && ( echo "couldn't find domain name" ; exit 1 ) + +# Termination handler + +term() { + kill %1 + ( + [ -n "$vncpid" ] && kill -9 $vncpid + xm destroy stubdom-$domname + #xm destroy $domname + ) & + # We need to exit immediately so as to let xend do the commands above + exit 0 +} + +trap term SIGHUP + +############ +# stubdomain +# Wait for any previous stubdom to terminate +while xm list | grep stubdom-$domname +do + sleep 1 +done + +creation="xm create -c stubdom-$domname target=$domid memory=32" + +(while true ; do sleep 60 ; done) | $creation & +#xterm -geometry +0+0 -e /bin/sh -c "$creation ; echo ; echo press ENTER to shut down ; read" & +consolepid=$! + + +while ! vnc_port=`xenstore-read /local/domain/$domid/console/vnc-port` +do + # Check that the stubdom job is still alive + kill -0 $consolepid || term + sleep 1 +done + +################ +# DEBUG: tcpdump +#while ! stubdomid=`xm domid stubdom-$domname` +#do +# sleep 1 +#done +#xterm -geometry 160x25+0+$height -e /bin/sh -c "tcpdump -n -i vif$stubdomid.0" & +#xterm -geometry 160x25+0+$((2 * $height)) -e /bin/sh -c "tcpdump -n -i vif$stubdomid.1" & + +########### +# vncviewer +if [ "$vncviewer" = 1 ] +then + vncviewer $ip:$vnc_port & + vncpid=$! +fi + +# wait for SIGHUP or stubdom termination +wait $consolepid + +term diff --git a/tools/ioemu/Makefile.target b/tools/ioemu/Makefile.target index 2b1bc6bb13..965d726adf 100644 --- a/tools/ioemu/Makefile.target +++ b/tools/ioemu/Makefile.target @@ -15,7 +15,7 @@ TARGET_BASE_ARCH:=sparc endif TARGET_PATH=$(SRC_PATH)/target-$(TARGET_BASE_ARCH)$(TARGET_SUB) VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw:$(SRC_PATH)/audio -CPPFLAGS=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH) +CPPFLAGS+=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH) CPPFLAGS+= -I$(XEN_ROOT)/tools/libxc CPPFLAGS+= -I$(XEN_ROOT)/tools/xenstore CPPFLAGS+= -I$(XEN_ROOT)/tools/include @@ -66,7 +66,11 @@ else QEMU_SYSTEM=qemu-fast endif +ifdef CONFIG_STUBDOM +QEMU_SYSTEM=qemu.a +else QEMU_SYSTEM=qemu-dm +endif ifdef CONFIG_USER_ONLY PROGS=$(QEMU_USER) @@ -345,14 +349,25 @@ VL_OBJS=vl.o osdep.o readline.o monitor.o pci.o console.o isa_mmio.o VL_OBJS+=cutils.o VL_OBJS+=block.o block-raw.o VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o block-qcow2.o +ifdef CONFIG_STUBDOM +VL_OBJS+=block-vbd.o +endif ifdef CONFIG_WIN32 VL_OBJS+=tap-win32.o endif -ifeq (,$(wildcard /usr/include/pci)) +ifdef CONFIG_STUBDOM +CONFIG_PASSTHROUGH=1 +else + ifeq (,$(wildcard /usr/include/pci)) $(warning *** pciutils-devl package not found - missing /usr/include/pci) $(warning *** PCI passthrough capability has been disabled) -else + else +CONFIG_PASSTHROUGH=1 + endif +endif + +ifdef CONFIG_PASSTHROUGH LIBS+=-lpci VL_OBJS+= pass-through.o CFLAGS += -DCONFIG_PASSTHROUGH @@ -404,13 +419,13 @@ VL_OBJS+= ne2000.o rtl8139.o pcnet.o e100.o ifeq ($(TARGET_BASE_ARCH), i386) # Hardware support -VL_OBJS+= ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV) extboot.o +VL_OBJS+= ide.o pckbd.o ps2.o vga.o dma.o extboot.o ifeq ($(ARCH),ia64) VL_OBJS+= fdc.o mc146818rtc.o serial.o pc.o else VL_OBJS+= fdc.o serial.o pc.o endif -VL_OBJS+= cirrus_vga.o mixeng.o parallel.o acpi.o +VL_OBJS+= cirrus_vga.o parallel.o acpi.o VL_OBJS+= usb-uhci.o smbus_eeprom.o VL_OBJS+= piix4acpi.o VL_OBJS+= xenstore.o @@ -419,23 +434,32 @@ VL_OBJS+= xen_machine_fv.o VL_OBJS+= xen_machine_pv.o VL_OBJS+= xenfb.o VL_OBJS+= xen_console.o +ifndef CONFIG_STUBDOM VL_OBJS+= tpm_tis.o +VL_OBJS+= $(SOUND_HW) $(AUDIODRV) mixeng.o CPPFLAGS += -DHAS_TPM CPPFLAGS += -DHAS_AUDIO endif +endif ifeq ($(TARGET_BASE_ARCH), ppc) -VL_OBJS+= ppc.o ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV) +VL_OBJS+= ppc.o ide.o pckbd.o ps2.o vga.o dma.o VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o mixeng.o VL_OBJS+= grackle_pci.o prep_pci.o unin_pci.o +ifndef CONFIG_STUBDOM +VL_OBJS+= $(SOUND_HW) $(AUDIODRV) CPPFLAGS += -DHAS_AUDIO endif +endif ifeq ($(TARGET_ARCH), mips) VL_OBJS+= mips_r4k.o mips_malta.o mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o VL_OBJS+= ide.o gt64xxx.o pckbd.o ps2.o fdc.o mc146818rtc.o usb-uhci.o acpi.o -VL_OBJS+= piix_pci.o parallel.o mixeng.o cirrus_vga.o $(SOUND_HW) $(AUDIODRV) +VL_OBJS+= piix_pci.o parallel.o mixeng.o cirrus_vga.o +ifndef CONFIG_STUBDOM +VL_OBJS+= $(SOUND_HW) $(AUDIODRV) DEFINES += -DHAS_AUDIO endif +endif ifeq ($(TARGET_BASE_ARCH), sparc) ifeq ($(TARGET_ARCH), sparc64) VL_OBJS+= sun4u.o ide.o pckbd.o ps2.o vga.o apb_pci.o @@ -513,7 +537,11 @@ SDL_LIBS := $(filter-out -mwindows, $(SDL_LIBS)) -mconsole endif $(QEMU_SYSTEM): $(VL_OBJS) libqemu.a +ifdef CONFIG_STUBDOM + $(AR) rcs $@ $(VL_OBJS) +else $(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS) +endif cocoa.o: cocoa.m $(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $< diff --git a/tools/ioemu/aes.c b/tools/ioemu/aes.c index cd4484ff9b..e75b168a80 100644 --- a/tools/ioemu/aes.c +++ b/tools/ioemu/aes.c @@ -33,9 +33,11 @@ #define NDEBUG #include +#ifndef CONFIG_STUBDOM typedef uint32_t u32; typedef uint16_t u16; typedef uint8_t u8; +#endif #define MAXKC (256/32) #define MAXKB (256/8) diff --git a/tools/ioemu/block-vbd.c b/tools/ioemu/block-vbd.c new file mode 100644 index 0000000000..9cb97255e6 --- /dev/null +++ b/tools/ioemu/block-vbd.c @@ -0,0 +1,341 @@ +/* + * Block driver for Mini-os PV devices + * Based on block-raw.c + * + * Copyright (c) 2006 Fabrice Bellard, 2007 Samuel Thibault + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" +#include "block_int.h" +#include +#include +#include +#include + +#define SECTOR_SIZE 512 + +#ifndef QEMU_TOOL +#include "exec-all.h" +#endif + +#define DEBUG_BLOCK +#ifdef DEBUG_BLOCK +#define DEBUG_BLOCK_PRINT( formatCstr, args... ) fprintf( logfile, formatCstr, ##args ); fflush( logfile ) +#else +#define DEBUG_BLOCK_PRINT( formatCstr, args... ) +#endif + +#define FTYPE_FILE 0 +#define FTYPE_CD 1 +#define FTYPE_FD 2 + +typedef struct BDRVVbdState { + struct blkfront_dev *dev; + int fd; + int type; + int mode; + uint64_t sectors; + unsigned sector_size; + QEMU_LIST_ENTRY(BDRVVbdState) list; +} BDRVVbdState; + +QEMU_LIST_HEAD(, BDRVVbdState) vbds; + +static int vbd_probe(const uint8_t *buf, int buf_size, const char *filename) +{ + char *value; + if (xenbus_read(XBT_NIL, filename, &value)) + return 0; + free(value); + return 100; +} + +static int vbd_open(BlockDriverState *bs, const char *filename, int flags) +{ + BDRVVbdState *s = bs->opaque; + + //handy to test posix access + //return -EIO; + + s->dev = init_blkfront((char *) filename, &s->sectors, &s->sector_size, &s->mode); + + if (!s->dev) + return -EIO; + + if (SECTOR_SIZE % s->sector_size) { + printf("sector size is %d, we only support sector sizes that divide %d\n", s->sector_size, SECTOR_SIZE); + return -EIO; + } + + s->fd = blkfront_open(s->dev); + + QEMU_LIST_INSERT_HEAD(&vbds, s, list); + + return 0; +} + +typedef struct VbdAIOCB { + BlockDriverAIOCB common; + struct blkfront_aiocb aiocb; +} VbdAIOCB; + +void qemu_aio_init(void) +{ +} + +void qemu_aio_poll(void) +{ + BDRVVbdState *s; + for (s = vbds.lh_first; s; s = s->list.le_next) + blkfront_aio_poll(s->dev); +} + +/* Wait for all IO requests to complete. */ +void qemu_aio_flush(void) +{ + BDRVVbdState *s; + for (s = vbds.lh_first; s; s = s->list.le_next) + blkfront_sync(s->dev); +} + +void qemu_aio_wait_start(void) +{ +} + +void qemu_aio_wait(void) +{ + int some = 0; + DEFINE_WAIT(w); + while (1) { + BDRVVbdState *s; + add_waiter(w, blkfront_queue); + for (s = vbds.lh_first; s; s = s->list.le_next) + if (blkfront_aio_poll(s->dev)) + some = 1; + if (some) + break; + schedule(); + } + remove_waiter(w); +} + +void qemu_aio_wait_end(void) +{ +} + +static void vbd_aio_callback(struct blkfront_aiocb *aiocbp, int ret) { + VbdAIOCB *acb = aiocbp->data; + + acb->common.cb(acb->common.opaque, ret); + qemu_aio_release(acb); +} + +static VbdAIOCB *vbd_aio_setup(BlockDriverState *bs, + int64_t sector_num, uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) +{ + BDRVVbdState *s = bs->opaque; + VbdAIOCB *acb; + + acb = qemu_aio_get(bs, cb, opaque); + if (!acb) + return NULL; + acb->aiocb.aio_dev = s->dev; + acb->aiocb.aio_buf = buf; + acb->aiocb.aio_nbytes = nb_sectors * SECTOR_SIZE; + acb->aiocb.aio_offset = sector_num * SECTOR_SIZE; + acb->aiocb.aio_cb = vbd_aio_callback; + acb->aiocb.data = acb; + + return acb; +} + +static BlockDriverAIOCB *vbd_aio_read(BlockDriverState *bs, + int64_t sector_num, uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) +{ + VbdAIOCB *acb; + + acb = vbd_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque); + if (!acb) + return NULL; + blkfront_aio(&acb->aiocb, 0); + return &acb->common; +} + +static BlockDriverAIOCB *vbd_aio_write(BlockDriverState *bs, + int64_t sector_num, const uint8_t *buf, int nb_sectors, + BlockDriverCompletionFunc *cb, void *opaque) +{ + VbdAIOCB *acb; + + acb = vbd_aio_setup(bs, sector_num, (uint8_t*) buf, nb_sectors, cb, opaque); + if (!acb) + return NULL; + blkfront_aio(&acb->aiocb, 1); + return &acb->common; +} + +static void vbd_cb(void *data, int ret) { + int *result = data; + result[0] = 1; + result[1] = ret; +} + +static int vbd_aligned_io(BlockDriverState *bs, + int64_t sector_num, uint8_t *buf, int nb_sectors, int write) +{ + VbdAIOCB *acb; + int result[2]; + result[0] = 0; + qemu_aio_wait_start(); + acb = vbd_aio_setup(bs, sector_num, (uint8_t*) buf, nb_sectors, vbd_cb, &result); + blkfront_aio(&acb->aiocb, write); + while (!result[0]) + qemu_aio_wait(); + qemu_aio_wait_end(); + return result[1]; +} + +static int vbd_read(BlockDriverState *bs, + int64_t sector_num, uint8_t *buf, int nb_sectors) +{ + uint8_t *iobuf; + int ret; + /* page alignment would be a bit better, but that's still fine compared to + * copying */ + if (!((uintptr_t)buf & (SECTOR_SIZE-1))) + return vbd_aligned_io(bs, sector_num, buf, nb_sectors, 0); + iobuf = memalign(PAGE_SIZE, nb_sectors * SECTOR_SIZE); + ret = vbd_aligned_io(bs, sector_num, iobuf, nb_sectors, 0); + memcpy(buf, iobuf, nb_sectors * SECTOR_SIZE); + free(iobuf); + if (ret < 0) + return ret; + else if (ret != nb_sectors * SECTOR_SIZE) + return -EINVAL; + else + return 0; +} + +static int vbd_write(BlockDriverState *bs, + int64_t sector_num, const uint8_t *buf, int nb_sectors) +{ + uint8_t *iobuf; + int ret; + if (!((uintptr_t)buf & (SECTOR_SIZE-1))) + return vbd_aligned_io(bs, sector_num, (uint8_t*) buf, nb_sectors, 1); + iobuf = memalign(PAGE_SIZE, nb_sectors * SECTOR_SIZE); + memcpy(iobuf, buf, nb_sectors * SECTOR_SIZE); + ret = vbd_aligned_io(bs, sector_num, iobuf, nb_sectors, 1); + free(iobuf); + if (ret < 0) + return ret; + else if (ret != nb_sectors * SECTOR_SIZE) + return -EINVAL; + else + return 0; +} + +static void vbd_aio_cancel(BlockDriverAIOCB *blockacb) +{ + /* TODO */ + //VbdAIOCB *acb = (VbdAIOCB *)blockacb; + + // Try to cancel. If can't, wait for it, drop the callback and call qemu_aio_release(acb) +} + +static void vbd_close(BlockDriverState *bs) +{ + BDRVVbdState *s = bs->opaque; + bs->total_sectors = 0; + if (s->fd >= 0) { + close(s->fd); + s->fd = -1; + } + QEMU_LIST_REMOVE(s, list); +} + +static int64_t vbd_getlength(BlockDriverState *bs) +{ + BDRVVbdState *s = bs->opaque; + return s->sectors * s->sector_size; +} + +static void vbd_flush(BlockDriverState *bs) +{ + BDRVVbdState *s = bs->opaque; + blkfront_sync(s->dev); +} + +/***********************************************/ +/* host device */ + +static int vbd_is_inserted(BlockDriverState *bs) +{ + /* TODO: monitor the backend */ + return 1; +} + +/* currently only used by fdc.c, but a CD version would be good too */ +static int vbd_media_changed(BlockDriverState *bs) +{ + /* TODO: monitor the backend */ + return -ENOTSUP; +} + +static int vbd_eject(BlockDriverState *bs, int eject_flag) +{ + /* TODO: Xen support needed */ + return -ENOTSUP; +} + +static int vbd_set_locked(BlockDriverState *bs, int locked) +{ + /* TODO: Xen support needed */ + return -ENOTSUP; +} + +BlockDriver bdrv_vbd = { + "vbd", + sizeof(BDRVVbdState), + vbd_probe, + vbd_open, + NULL, + NULL, + vbd_close, + NULL, + vbd_flush, + + .bdrv_aio_read = vbd_aio_read, + .bdrv_aio_write = vbd_aio_write, + .bdrv_aio_cancel = vbd_aio_cancel, + .aiocb_size = sizeof(VbdAIOCB), + .bdrv_read = vbd_read, + .bdrv_write = vbd_write, + .bdrv_getlength = vbd_getlength, + + /* removable device support */ + .bdrv_is_inserted = vbd_is_inserted, + .bdrv_media_changed = vbd_media_changed, + .bdrv_eject = vbd_eject, + .bdrv_set_locked = vbd_set_locked, +}; + diff --git a/tools/ioemu/block.c b/tools/ioemu/block.c index cf84e8ffbb..a43f3fe27b 100644 --- a/tools/ioemu/block.c +++ b/tools/ioemu/block.c @@ -1235,6 +1235,9 @@ void bdrv_init(void) { bdrv_register(&bdrv_raw); bdrv_register(&bdrv_host_device); +#ifdef CONFIG_STUBDOM + bdrv_register(&bdrv_vbd); +#endif #ifndef _WIN32 bdrv_register(&bdrv_cow); #endif diff --git a/tools/ioemu/configure b/tools/ioemu/configure index ef0bac1f8e..3e3b427b87 100755 --- a/tools/ioemu/configure +++ b/tools/ioemu/configure @@ -74,6 +74,7 @@ softmmu="yes" linux_user="no" darwin_user="no" build_docs="no" +stubdom="no" uname_release="" # OS specific @@ -231,6 +232,8 @@ for opt do ;; --enable-uname-release=*) uname_release="$optarg" ;; + --enable-stubdom) stubdom="yes" + ;; esac done @@ -416,7 +419,11 @@ if test -z "$target_list" ; then target_list="i386-darwin-user ppc-darwin-user $target_list" fi # the i386-dm target - target_list="i386-dm" + if test "$stubdom" = "yes"; then + target_list="i386-dm-stubdom" + else + target_list="i386-dm" + fi else target_list=`echo "$target_list" | sed -e 's/,/ /g'` fi @@ -575,6 +582,11 @@ bindir="$prefix/$libdir/xen/bin" configdir="/etc/xen" fi +if test "$stubdom" = "yes"; then + oss="no" + sdl="no" +fi + echo "Install prefix $prefix" echo "BIOS directory $datadir" echo "binary directory $bindir" @@ -943,6 +955,14 @@ if expr $target : '.*-dm' > /dev/null ; then echo "#define CONFIG_DM 1" >> $config_h fi +if test "$stubdom" = "yes" ; then + echo "CONFIG_STUBDOM=yes" >> $config_mak + echo "#define CONFIG_STUBDOM 1" >> $config_h + echo "#define NO_UNIX_SOCKETS 1" >> $config_h + echo "#define NO_DAEMONIZE 1" >> $config_h + echo "#define NO_AIO 1" >> $config_h +fi + if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64" -o "$target_cpu" = "m68k"; then echo "CONFIG_SOFTFLOAT=yes" >> $config_mak echo "#define CONFIG_SOFTFLOAT 1" >> $config_h diff --git a/tools/ioemu/exec-all.h b/tools/ioemu/exec-all.h index f6804b1a0a..28c120d4ca 100644 --- a/tools/ioemu/exec-all.h +++ b/tools/ioemu/exec-all.h @@ -481,6 +481,9 @@ static inline int testandset (int *p) } #endif +#ifdef CONFIG_STUBDOM +#include +#else typedef int spinlock_t; #define SPIN_LOCK_UNLOCKED 0 @@ -514,6 +517,7 @@ static inline int spin_trylock(spinlock_t *lock) return 1; } #endif +#endif extern spinlock_t tb_lock; diff --git a/tools/ioemu/hw/ide.c b/tools/ioemu/hw/ide.c index 0e65141ec6..cba064bd10 100644 --- a/tools/ioemu/hw/ide.c +++ b/tools/ioemu/hw/ide.c @@ -22,6 +22,7 @@ * THE SOFTWARE. */ #include "vl.h" +#include /* debug IDE devices */ //#define DEBUG_IDE @@ -347,7 +348,7 @@ typedef struct IDEState { EndTransferFunc *end_transfer_func; uint8_t *data_ptr; uint8_t *data_end; - uint8_t io_buffer[MAX_MULT_SECTORS*512 + 4]; + uint8_t *io_buffer; QEMUTimer *sector_write_timer; /* only used for win2k instal hack */ uint32_t irq_count; /* counts IRQs when using win2k install hack */ } IDEState; @@ -2305,6 +2306,7 @@ static void ide_init2(IDEState *ide_state, for(i = 0; i < 2; i++) { s = ide_state + i; + s->io_buffer = memalign(getpagesize(), MAX_MULT_SECTORS*512 + 4); if (i == 0) s->bs = hd0; else diff --git a/tools/ioemu/hw/scsi-disk.c b/tools/ioemu/hw/scsi-disk.c index c6280fd559..d62d4d0d95 100644 --- a/tools/ioemu/hw/scsi-disk.c +++ b/tools/ioemu/hw/scsi-disk.c @@ -26,13 +26,18 @@ do { printf("scsi-disk: " fmt , ##args); } while (0) do { fprintf(stderr, "scsi-disk: " fmt , ##args); } while (0) #include "vl.h" +#include #define SENSE_NO_SENSE 0 #define SENSE_NOT_READY 2 #define SENSE_HARDWARE_ERROR 4 #define SENSE_ILLEGAL_REQUEST 5 +#ifdef CONFIG_STUBDOM +#define SCSI_DMA_BUF_SIZE 32768 +#else #define SCSI_DMA_BUF_SIZE 65536 +#endif typedef struct SCSIRequest { SCSIDevice *dev; @@ -44,7 +49,7 @@ typedef struct SCSIRequest { int sector_count; /* The amounnt of data in the buffer. */ int buf_len; - uint8_t dma_buf[SCSI_DMA_BUF_SIZE]; + uint8_t *dma_buf; BlockDriverAIOCB *aiocb; struct SCSIRequest *next; } SCSIRequest; @@ -76,6 +81,7 @@ static SCSIRequest *scsi_new_request(SCSIDevice *s, uint32_t tag) free_requests = r->next; } else { r = qemu_malloc(sizeof(SCSIRequest)); + r->dma_buf = memalign(getpagesize(), SCSI_DMA_BUF_SIZE); } r->dev = s; r->tag = tag; diff --git a/tools/ioemu/hw/xen_machine_fv.c b/tools/ioemu/hw/xen_machine_fv.c index 22ba1dbc3f..272f67946f 100644 --- a/tools/ioemu/hw/xen_machine_fv.c +++ b/tools/ioemu/hw/xen_machine_fv.c @@ -24,6 +24,9 @@ */ #include "vl.h" +#ifdef CONFIG_STUBDOM +#include +#endif #include #include diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index 452bfcc555..6841f07848 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -36,22 +36,29 @@ #include #include #include +#ifndef CONFIG_STUBDOM #include +#endif #include #include #include #include #include +#ifndef CONFIG_STUBDOM #include +#endif #if defined(__NetBSD__) #include #endif #if defined(__linux__) || defined(__Linux__) #include #endif +#ifndef CONFIG_STUBDOM #include #include +#endif #include +#ifndef CONFIG_STUBDOM #ifdef _BSD #include #ifndef _BSD @@ -70,6 +77,7 @@ #include #endif #endif +#endif #if defined(CONFIG_SLIRP) #include "libslirp.h" @@ -132,10 +140,9 @@ #define MAX_IOPORTS 65536 const char *bios_dir = CONFIG_QEMU_SHAREDIR; -char phys_ram_file[1024]; -void *ioport_opaque[MAX_IOPORTS]; -IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS]; -IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS]; +void **ioport_opaque; +IOPortReadFunc *(*ioport_read_table)[MAX_IOPORTS]; +IOPortWriteFunc *(*ioport_write_table)[MAX_IOPORTS]; /* Note: bs_table[MAX_DISKS] is a dummy block driver if none available to store the VM snapshots */ BlockDriverState *bs_table[MAX_DISKS + MAX_SCSI_DISKS + 1], *fd_table[MAX_FD]; @@ -270,6 +277,9 @@ void default_ioport_writel(void *opaque, uint32_t address, uint32_t data) void init_ioports(void) { + ioport_opaque = malloc(MAX_IOPORTS * sizeof(*ioport_opaque)); + ioport_read_table = malloc(3 * MAX_IOPORTS * sizeof(**ioport_read_table)); + ioport_write_table = malloc(3 * MAX_IOPORTS * sizeof(**ioport_write_table)); } /* size is the word size in byte */ @@ -797,9 +807,6 @@ static QEMUTimer *active_timers[2]; static MMRESULT timerID; static HANDLE host_alarm = NULL; static unsigned int period = 1; -#else -/* frequency of the times() clock tick */ -static int timer_freq; #endif QEMUClock *qemu_new_clock(int type) @@ -1137,9 +1144,6 @@ static void init_timer_alarm(void) struct itimerval itv; #endif - /* get times() syscall frequency */ - timer_freq = sysconf(_SC_CLK_TCK); - #ifndef CONFIG_DM /* timer signal */ sigfillset(&act.sa_mask); @@ -1497,6 +1501,7 @@ static CharDriverState *qemu_chr_open_file_out(const char *file_out) return qemu_chr_open_fd(-1, fd_out); } +#ifndef CONFIG_STUBDOM static CharDriverState *qemu_chr_open_pipe(const char *filename) { int fd_in, fd_out; @@ -1742,6 +1747,7 @@ static CharDriverState *qemu_chr_open_stdio(void) } return chr; } +#endif /* * Create a store entry for a device (e.g., monitor, serial/parallel lines). @@ -1751,6 +1757,9 @@ static CharDriverState *qemu_chr_open_stdio(void) static int store_dev_info(char *devName, int domid, CharDriverState *cState, char *storeString) { +#ifdef CONFIG_STUBDOM + return 0; +#else int xc_handle; struct xs_handle *xs; char *path; @@ -1826,8 +1835,10 @@ static int store_dev_info(char *devName, int domid, close(xc_handle); return 0; +#endif } +#ifndef CONFIG_STUBDOM #ifdef __sun__ /* Once Solaris has openpty(), this is going to be removed. */ int openpty(int *amaster, int *aslave, char *name, @@ -2486,6 +2497,7 @@ static CharDriverState *qemu_chr_open_win_file_out(const char *file_out) return qemu_chr_open_win_file(fd_out); } #endif +#endif /***********************************************************/ /* UDP Net console */ @@ -2978,12 +2990,14 @@ CharDriverState *qemu_chr_open(const char *filename) return qemu_chr_open_tcp(p, 0, 1); } else if (strstart(filename, "file:", &p)) { return qemu_chr_open_file_out(p); +#ifndef CONFIG_STUBDOM } else if (strstart(filename, "pipe:", &p)) { return qemu_chr_open_pipe(p); } else if (!strcmp(filename, "pty")) { return qemu_chr_open_pty(); } else if (!strcmp(filename, "stdio")) { return qemu_chr_open_stdio(); +#endif } else #endif #if defined(__linux__) @@ -3473,7 +3487,16 @@ static TAPState *net_tap_fd_init(VLANState *vlan, int fd) return s; } -#ifdef _BSD +#ifdef CONFIG_STUBDOM +#include +static int tap_open(char *ifname, int ifname_size) +{ + char nodename[64]; + static int num = 1; // 0 is for our own TCP/IP networking + snprintf(nodename, sizeof(nodename), "device/vif/%d", num++); + return netfront_tap_open(nodename); +} +#elif defined(_BSD) static int tap_open(char *ifname, int ifname_size) { int fd; @@ -3561,6 +3584,7 @@ static int net_tap_init(VLANState *vlan, const char *ifname1, if (fd < 0) return -1; +#ifndef CONFIG_STUBDOM if (!setup_script || !strcmp(setup_script, "no")) setup_script = ""; if (setup_script[0] != '\0') { @@ -3593,6 +3617,7 @@ static int net_tap_init(VLANState *vlan, const char *ifname1, } } } +#endif s = net_tap_fd_init(vlan, fd); if (!s) return -1; @@ -7041,12 +7066,14 @@ int main(int argc, char **argv) char usb_devices[MAX_USB_CMDLINE][128]; int usb_devices_index; int fds[2]; +#ifndef CONFIG_STUBDOM struct rlimit rl; +#endif sigset_t set; char qemu_dm_logfilename[128]; const char *direct_pci = NULL; -#ifndef __sun__ +#if !defined(__sun__) && !defined(CONFIG_STUBDOM) /* Maximise rlimits. Needed where default constraints are tight (*BSD). */ if (getrlimit(RLIMIT_STACK, &rl) != 0) { perror("getrlimit(RLIMIT_STACK)"); @@ -7072,6 +7099,7 @@ int main(int argc, char **argv) perror("setrlimit(RLIMIT_MEMLOCK)"); #endif +#ifndef CONFIG_STUBDOM /* Ensure that SIGUSR2 is blocked by default when a new thread is created, then only the threads that use the signal unblock it -- this fixes a race condition in Qcow support where the AIO signal is misdelivered. */ @@ -7113,6 +7141,7 @@ int main(int argc, char **argv) } } } +#endif #endif register_machines(); @@ -7631,7 +7660,15 @@ int main(int argc, char **argv) #ifdef CONFIG_DM bdrv_init(); xc_handle = xc_interface_open(); +#ifdef CONFIG_STUBDOM + char *domid_s, *msg; + if ((msg = xenbus_read(XBT_NIL, "domid", &domid_s))) + fprintf(stderr,"Can not read our own domid\n", msg); + else + xenstore_parse_domain_config(atoi(domid_s)); +#else /* CONFIG_STUBDOM */ xenstore_parse_domain_config(domid); +#endif /* CONFIG_STUBDOM */ #endif /* CONFIG_DM */ #ifdef USE_KQEMU @@ -7799,8 +7836,10 @@ int main(int argc, char **argv) vnc_display_password(ds, password); if ((vnc_display_port = vnc_display_open(ds, vnc_display, vncunused)) < 0) exit (0); +#ifndef CONFIG_STUBDOM if (vncviewer) vnc_start_viewer(vnc_display_port); +#endif xenstore_write_vncport(vnc_display_port); } else { #if defined(CONFIG_SDL) @@ -7928,6 +7967,7 @@ int main(int argc, char **argv) } #endif +#ifndef CONFIG_STUBDOM /* Unblock SIGTERM and SIGHUP, which may have been blocked by the caller */ signal(SIGHUP, SIG_DFL); sigemptyset(&set); @@ -7935,6 +7975,7 @@ int main(int argc, char **argv) sigaddset(&set, SIGHUP); if (sigprocmask(SIG_UNBLOCK, &set, NULL) == -1) fprintf(stderr, "Failed to unblock SIGTERM and SIGHUP\n"); +#endif main_loop(); quit_timers(); diff --git a/tools/ioemu/vl.h b/tools/ioemu/vl.h index 04d04845c5..00f5c16333 100644 --- a/tools/ioemu/vl.h +++ b/tools/ioemu/vl.h @@ -574,6 +574,9 @@ typedef struct BlockDriver BlockDriver; extern BlockDriver bdrv_raw; extern BlockDriver bdrv_host_device; +#ifdef CONFIG_STUBDOM +extern BlockDriver bdrv_vbd; +#endif extern BlockDriver bdrv_cow; extern BlockDriver bdrv_qcow; extern BlockDriver bdrv_vmdk; diff --git a/tools/ioemu/vnc.c b/tools/ioemu/vnc.c index 7b6e633f7a..f07ce8ca34 100644 --- a/tools/ioemu/vnc.c +++ b/tools/ioemu/vnc.c @@ -27,10 +27,12 @@ #include #include #include -#include #include "vl.h" #include "qemu_socket.h" #include +#ifdef CONFIG_STUBDOM +#include +#endif /* The refresh interval starts at BASE. If we scan the buffer and find no change, we increase by INC, up to MAX. If the mouse moves @@ -2407,7 +2409,9 @@ int vnc_display_open(DisplayState *ds, const char *display, int find_unused) #ifndef NO_UNIX_SOCKETS struct sockaddr_un uaddr; #endif +#ifndef CONFIG_STUBDOM int reuse_addr, ret; +#endif socklen_t addrlen; const char *p; VncState *vs = ds ? (VncState *)ds->opaque : vnc_state; @@ -2539,6 +2543,15 @@ int vnc_display_open(DisplayState *ds, const char *display, int find_unused) return -1; } +#ifdef CONFIG_STUBDOM + { + struct ip_addr ipaddr = { iaddr.sin_addr.s_addr }; + struct ip_addr netmask = { 0 }; + struct ip_addr gw = { 0 }; + networking_set_addr(&ipaddr, &netmask, &gw); + } +#endif + iaddr.sin_port = htons(ntohs(iaddr.sin_port) + 5900); vs->lsock = socket(PF_INET, SOCK_STREAM, 0); @@ -2549,6 +2562,7 @@ int vnc_display_open(DisplayState *ds, const char *display, int find_unused) return -1; } +#ifndef CONFIG_STUBDOM reuse_addr = 1; ret = setsockopt(vs->lsock, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuse_addr, sizeof(reuse_addr)); @@ -2560,6 +2574,7 @@ int vnc_display_open(DisplayState *ds, const char *display, int find_unused) vs->display = NULL; return -1; } +#endif } while (bind(vs->lsock, addr, addrlen) == -1) { @@ -2590,6 +2605,7 @@ int vnc_display_open(DisplayState *ds, const char *display, int find_unused) return ntohs(iaddr.sin_port); } +#ifndef CONFIG_STUBDOM int vnc_start_viewer(int port) { int pid, i, open_max; @@ -2617,4 +2633,5 @@ int vnc_start_viewer(int port) return pid; } } +#endif diff --git a/tools/ioemu/xenstore.c b/tools/ioemu/xenstore.c index 9d33237cb3..8cad6bda2d 100644 --- a/tools/ioemu/xenstore.c +++ b/tools/ioemu/xenstore.c @@ -11,8 +11,10 @@ #include "vl.h" #include "block_int.h" #include +#ifndef CONFIG_STUBDOM #include #include +#endif #include #include #include @@ -219,10 +221,18 @@ void xenstore_parse_domain_config(int domid) } /* open device now if media present */ +#ifdef CONFIG_STUBDOM + if (pasprintf(&buf, "%s/device/vbd/%s", path, e[i]) == -1) + continue; + if (bdrv_open2(bs, buf, 0 /* snapshot */, &bdrv_vbd) == 0) { + pstrcpy(bs->filename, sizeof(bs->filename), params); + continue; + } +#endif + if (params[0]) { if (bdrv_open(bs, params, 0 /* snapshot */) < 0) - fprintf(stderr, "qemu: could not open hard disk image '%s'\n", - params); + fprintf(stderr, "qemu: could not open vbd '%s' or hard disk image '%s'\n", buf, params); } } @@ -265,6 +275,10 @@ extern int vga_ram_size, bios_size; void xenstore_process_logdirty_event(void) { +#ifdef CONFIG_STUBDOM + /* XXX we just can't use shm. */ + return; +#else char *act; static char *active_path = NULL; static char *next_active_path = NULL; @@ -367,6 +381,7 @@ void xenstore_process_logdirty_event(void) /* Ack that we've switched */ xs_write(xsh, XBT_NULL, active_path, act, len); free(act); +#endif } diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile index ffc5662052..41dcbab808 100644 --- a/tools/libxc/Makefile +++ b/tools/libxc/Makefile @@ -5,10 +5,12 @@ MAJOR = 3.2 MINOR = 0 CTRL_SRCS-y := +ifneq ($(stubdom),y) CTRL_SRCS-y += xc_core.c CTRL_SRCS-$(CONFIG_X86) += xc_core_x86.c CTRL_SRCS-$(CONFIG_IA64) += xc_core_ia64.c CTRL_SRCS-$(CONFIG_POWERPC) += xc_core_powerpc.c +endif CTRL_SRCS-y += xc_domain.c CTRL_SRCS-y += xc_evtchn.c CTRL_SRCS-y += xc_misc.c @@ -19,21 +21,29 @@ CTRL_SRCS-y += xc_private.c CTRL_SRCS-y += xc_sedf.c CTRL_SRCS-y += xc_csched.c CTRL_SRCS-y += xc_tbuf.c +ifneq ($(stubdom),y) CTRL_SRCS-y += xc_resume.c +endif CTRL_SRCS-$(CONFIG_X86) += xc_pagetab.c +ifneq ($(stubdom),y) CTRL_SRCS-$(CONFIG_Linux) += xc_linux.c CTRL_SRCS-$(CONFIG_SunOS) += xc_solaris.c CTRL_SRCS-$(CONFIG_X86_Linux) += xc_ptrace.c xc_ptrace_core.c CTRL_SRCS-$(CONFIG_NetBSD) += xc_netbsd.c +endif +CTRL_SRCS-$(stubdom) += xc_minios.c GUEST_SRCS-y := GUEST_SRCS-y += xg_private.c +ifneq ($(stubdom),y) GUEST_SRCS-$(CONFIG_MIGRATE) += xc_domain_restore.c xc_domain_save.c GUEST_SRCS-$(CONFIG_HVM) += xc_hvm_build.c +endif VPATH = ../../xen/common/libelf CFLAGS += -I../../xen/common/libelf +ifneq ($(stubdom),y) GUEST_SRCS-y += libelf-tools.c libelf-loader.c GUEST_SRCS-y += libelf-dominfo.c libelf-relocate.c @@ -46,6 +56,7 @@ GUEST_SRCS-y += xc_dom_compat_linux.c GUEST_SRCS-$(CONFIG_X86) += xc_dom_x86.c GUEST_SRCS-$(CONFIG_IA64) += xc_dom_ia64.c GUEST_SRCS-$(CONFIG_POWERPC) += xc_dom_powerpc.c +endif -include $(XEN_TARGET_ARCH)/Makefile @@ -64,6 +75,10 @@ CFLAGS += -Wp,-MD,.$(@F).d LDFLAGS += -L. DEPS = .*.d +ifneq ($(stubdom),y) +LDLIBS = -lpthread +endif + CTRL_LIB_OBJS := $(patsubst %.c,%.o,$(CTRL_SRCS-y)) CTRL_PIC_OBJS := $(patsubst %.c,%.opic,$(CTRL_SRCS-y)) @@ -71,10 +86,14 @@ GUEST_LIB_OBJS := $(patsubst %.c,%.o,$(GUEST_SRCS-y)) GUEST_PIC_OBJS := $(patsubst %.c,%.opic,$(GUEST_SRCS-y)) LIB := libxenctrl.a +ifneq ($(stubdom),y) LIB += libxenctrl.so libxenctrl.so.$(MAJOR) libxenctrl.so.$(MAJOR).$(MINOR) +endif LIB += libxenguest.a +ifneq ($(stubdom),y) LIB += libxenguest.so libxenguest.so.$(MAJOR) libxenguest.so.$(MAJOR).$(MINOR) +endif .PHONY: all all: build @@ -133,7 +152,7 @@ libxenctrl.so.$(MAJOR): libxenctrl.so.$(MAJOR).$(MINOR) ln -sf $< $@ libxenctrl.so.$(MAJOR).$(MINOR): $(CTRL_PIC_OBJS) - $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $^ -lpthread + $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $^ $(LDLIBS) # libxenguest @@ -146,7 +165,7 @@ libxenguest.so.$(MAJOR): libxenguest.so.$(MAJOR).$(MINOR) ln -sf $< $@ libxenguest.so.$(MAJOR).$(MINOR): $(GUEST_PIC_OBJS) libxenctrl.so - $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenguest.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $(GUEST_PIC_OBJS) -lz -lxenctrl -lpthread + $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenguest.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $(GUEST_PIC_OBJS) -lz -lxenctrl $(LDLIBS) -include $(DEPS) diff --git a/tools/libxc/ia64/Makefile b/tools/libxc/ia64/Makefile index 8a23024b24..4fd4fbbe86 100644 --- a/tools/libxc/ia64/Makefile +++ b/tools/libxc/ia64/Makefile @@ -1,3 +1,4 @@ +ifneq ($(stubdom),y) CTRL_SRCS-y += ia64/xc_ia64_stubs.c GUEST_SRCS-y += ia64/xc_ia64_hvm_build.c @@ -8,6 +9,7 @@ GUEST_SRCS-y += ia64/xc_dom_ia64_util.c GUEST_SRCS-y += ia64/dom_fw_acpi.c DOMFW_SRCS_BASE := dom_fw_common.c dom_fw_domu.c dom_fw_asm.S +endif DOMFW_SRCS := $(addprefix ia64/, $(DOMFW_SRCS_BASE)) $(DOMFW_SRCS): ln -sf ../$(XEN_ROOT)/xen/arch/ia64/xen/$(@F) $@ diff --git a/tools/libxc/xc_minios.c b/tools/libxc/xc_minios.c new file mode 100644 index 0000000000..53f7a148da --- /dev/null +++ b/tools/libxc/xc_minios.c @@ -0,0 +1,313 @@ +/****************************************************************************** + * + * Copyright 2007-2008 Samuel Thibault . + * All rights reserved. + * Use is subject to license terms. + * + * 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, version 2 of the + * License. + */ + +#undef NDEBUG +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xc_private.h" + +extern struct wait_queue_head event_queue; + +int xc_interface_open(void) +{ + return 0; +} + +int xc_interface_close(int xc_handle) +{ + return 0; +} + +void *xc_map_foreign_batch(int xc_handle, uint32_t dom, int prot, + xen_pfn_t *arr, int num) +{ + unsigned long pt_prot = 0; +#ifdef __ia64__ + /* TODO */ +#else + if (prot & PROT_READ) + pt_prot = L1_PROT_RO; + if (prot & PROT_WRITE) + pt_prot = L1_PROT; +#endif + return map_frames_ex(arr, num, 1, 0, 1, dom, 1, pt_prot); +} + +void *xc_map_foreign_range(int xc_handle, uint32_t dom, + int size, int prot, + unsigned long mfn) +{ + unsigned long pt_prot = 0; + printf("xc_map_foreign_range(%lx, %d)\n", mfn, size); +#ifdef __ia64__ + /* TODO */ +#else + if (prot & PROT_READ) + pt_prot = L1_PROT_RO; + if (prot & PROT_WRITE) + pt_prot = L1_PROT; +#endif + assert(!(size % getpagesize())); + return map_frames_ex(&mfn, size / getpagesize(), 0, 1, 1, dom, 0, pt_prot); +} + +int xc_map_foreign_ranges(int xc_handle, uint32_t dom, + privcmd_mmap_entry_t *entries, int nr) +{ + printf("xc_map_foreign_ranges, TODO\n"); + do_exit(); +} + +int do_xen_hypercall(int xc_handle, privcmd_hypercall_t *hypercall) +{ + multicall_entry_t call; + int i, ret; + + call.op = hypercall->op; + for (i = 0; i < sizeof(hypercall->arg) / sizeof(*hypercall->arg); i++) + call.args[i] = hypercall->arg[i]; + + ret = HYPERVISOR_multicall(&call, 1); + + if (ret < 0) { + errno = -ret; + return -1; + } + if (call.result < 0) { + errno = -call.result; + return -1; + } + return call.result; +} + +int xc_find_device_number(const char *name) +{ + printf("xc_find_device_number(%s)\n", name); + do_exit(); +} + +int xc_evtchn_open(void) +{ + int fd = alloc_fd(FTYPE_EVTCHN), i; + for (i = 0; i < MAX_EVTCHN_PORTS; i++) { + files[fd].evtchn.ports[i].port = -1; + files[fd].evtchn.ports[i].bound = 0; + } + printf("evtchn_open() -> %d\n", fd); + return fd; +} + +int xc_evtchn_close(int xce_handle) +{ + int i; + for (i = 0; i < MAX_EVTCHN_PORTS; i++) + if (files[xce_handle].evtchn.ports[i].bound) + unbind_evtchn(files[xce_handle].evtchn.ports[i].port); + files[xce_handle].type = FTYPE_NONE; + return 0; +} + +int xc_evtchn_fd(int xce_handle) +{ + return xce_handle; +} + +int xc_evtchn_notify(int xce_handle, evtchn_port_t port) +{ + int ret; + + ret = notify_remote_via_evtchn(port); + + if (ret < 0) { + errno = -ret; + ret = -1; + } + return ret; +} + +/* XXX Note: This is not threadsafe */ +static int port_alloc(int xce_handle) { + int i; + for (i= 0; i < MAX_EVTCHN_PORTS; i++) + if (files[xce_handle].evtchn.ports[i].port == -1) + break; + if (i == MAX_EVTCHN_PORTS) { + printf("Too many ports in xc handle\n"); + errno = EMFILE; + return -1; + } + files[xce_handle].evtchn.ports[i].pending = 0; + return i; +} + +static void poke_port(int xce_handle, evtchn_port_t port) +{ + shared_info_t *s = HYPERVISOR_shared_info; + printk("poking port %d\n", port); + synch_set_bit(port, &s->evtchn_pending[0]); + xc_evtchn_unmask(xce_handle, port); +} + +static void evtchn_handler(evtchn_port_t port, struct pt_regs *regs, void *data) +{ + int xce_handle = (intptr_t) data; + int i; + assert(files[xce_handle].type == FTYPE_EVTCHN); + mask_evtchn(port); + for (i= 0; i < MAX_EVTCHN_PORTS; i++) + if (files[xce_handle].evtchn.ports[i].port == port) + break; + if (i == MAX_EVTCHN_PORTS) { + printk("Unknown port for handle %d\n", xce_handle); + return; + } + files[xce_handle].evtchn.ports[i].pending++; + files[xce_handle].read = 1; + wake_up(&event_queue); +} + +evtchn_port_or_error_t xc_evtchn_bind_unbound_port(int xce_handle, int domid) +{ + int ret, i; + evtchn_port_t port; + + assert(get_current() == main_thread); + i = port_alloc(xce_handle); + if (i == -1) + return -1; + + printf("xc_evtchn_bind_unbound_port(%d)", domid); + ret = evtchn_alloc_unbound(domid, evtchn_handler, (void*)(intptr_t)xce_handle, &port); + printf(" = %d\n", ret); + + if (ret < 0) { + errno = -ret; + return -1; + } + files[xce_handle].evtchn.ports[i].bound = 1; + files[xce_handle].evtchn.ports[i].port = port; + return port; +} + +evtchn_port_or_error_t xc_evtchn_bind_interdomain(int xce_handle, int domid, + evtchn_port_t remote_port) +{ + evtchn_port_t local_port; + int ret, i; + + assert(get_current() == main_thread); + i = port_alloc(xce_handle); + if (i == -1) + return -1; + + printf("xc_evtchn_bind_interdomain(%d, %"PRId32")", domid, remote_port); + ret = evtchn_bind_interdomain(domid, remote_port, evtchn_handler, (void*)(intptr_t)xce_handle, &local_port); + printf(" = %d\n", ret); + + if (ret < 0) { + errno = -ret; + return -1; + } + files[xce_handle].evtchn.ports[i].bound = 1; + files[xce_handle].evtchn.ports[i].port = local_port; +/* Poke port on start: HVM won't send an event for the very first request since + * we were not ready yet */ + poke_port(xce_handle, local_port); + return local_port; +} + +int xc_evtchn_unbind(int xce_handle, evtchn_port_t port) +{ + int i; + for (i = 0; i < MAX_EVTCHN_PORTS; i++) + if (files[xce_handle].evtchn.ports[i].port == port) { + files[xce_handle].evtchn.ports[i].port = -1; + break; + } + if (i == MAX_EVTCHN_PORTS) + printf("Warning: couldn't find port %"PRId32" for xc handle %x\n", port, xce_handle); + files[xce_handle].evtchn.ports[i].bound = 0; + unbind_evtchn(port); + return 0; +} + +evtchn_port_or_error_t xc_evtchn_bind_virq(int xce_handle, unsigned int virq) +{ + evtchn_port_t port; + int i; + + assert(get_current() == main_thread); + i = port_alloc(xce_handle); + if (i == -1) + return -1; + + printf("xc_evtchn_bind_virq(%d)", virq); + port = bind_virq(virq, evtchn_handler, (void*)(intptr_t)xce_handle); + + if (port < 0) { + errno = -port; + return -1; + } + files[xce_handle].evtchn.ports[i].bound = 1; + files[xce_handle].evtchn.ports[i].port = port; + return port; +} + +evtchn_port_or_error_t xc_evtchn_pending(int xce_handle) +{ + int i; + unsigned long flags; + local_irq_save(flags); + for (i = 0; i < MAX_EVTCHN_PORTS; i++) { + evtchn_port_t port = files[xce_handle].evtchn.ports[i].port; + if (port != -1 && files[xce_handle].evtchn.ports[i].pending) { + files[xce_handle].evtchn.ports[i].pending--; + local_irq_restore(flags); + return port; + } + } + files[xce_handle].read = 0; + local_irq_restore(flags); + return -1; +} + +int xc_evtchn_unmask(int xce_handle, evtchn_port_t port) +{ + unmask_evtchn(port); + return 0; +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ -- cgit v1.2.3 From b650bde790d6e2c918de3d2ce3b2a89d56b25896 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Tue, 12 Feb 2008 14:57:36 +0000 Subject: [BUILD] Add option to ensure kernel build is non-interactive. This is useful for the non 2.6.18-xen builds where the defconfig at any particular momement may require additional questions to be answered. Signed-off-by: Ian Campbell --- buildconfigs/mk.linux-2.6-common | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/buildconfigs/mk.linux-2.6-common b/buildconfigs/mk.linux-2.6-common index 35150591b5..5b6810c56d 100644 --- a/buildconfigs/mk.linux-2.6-common +++ b/buildconfigs/mk.linux-2.6-common @@ -14,6 +14,12 @@ else __XEN_LINUX_UPDATE = endif +ifeq ($(XEN_LINUX_NONINTERACTIVE_CONFIG),y) +__NONINT_CONFIG = yes $$'\n' | +else +__NONINT_CONFIG = +endif + # Let XEN_TARGET_ARCH override ARCH. ifeq ($(XEN_TARGET_ARCH),x86_32) LINUX_ARCH ?= i386 @@ -102,7 +108,7 @@ endif ifneq ($(EXTRAVERSION),) echo "$(EXTRAVERSION)" >$(LINUX_DIR)/localversion-xen endif - $(MAKE) -C $(LINUX_SRCDIR) ARCH=$(LINUX_ARCH) oldconfig O=$$(/bin/pwd)/$(LINUX_DIR) + $(__NONINT_CONFIG) $(MAKE) -C $(LINUX_SRCDIR) ARCH=$(LINUX_ARCH) oldconfig O=$$(/bin/pwd)/$(LINUX_DIR) @set -e ; if [ ! -f $(LINUX_DIR)/Makefile ] ; then \ echo "***********************************"; \ echo "oldconfig did not create a Makefile"; \ -- cgit v1.2.3 From 3eae93972b9e0b74e3060603d29eebec7d89d14a Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Tue, 12 Feb 2008 14:59:01 +0000 Subject: [BUILD] Fixup support for building upstream kernels. In particular: - support merged x86 architecture. To facilitate this it made sense to encode some existing logic in shell scripts rather than increasing complicated make conditionals. - set CONFIG_PARAVIRT_GUEST=y which is required for newer kernels. Signed-off-by: Ian Campbell --- buildconfigs/enable-xen-config | 9 ++++++++- buildconfigs/mk.linux-2.6-common | 24 ++++++++---------------- buildconfigs/select-linux-arch | 30 ++++++++++++++++++++++++++++++ buildconfigs/select-linux-image | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 17 deletions(-) create mode 100755 buildconfigs/select-linux-arch create mode 100755 buildconfigs/select-linux-image diff --git a/buildconfigs/enable-xen-config b/buildconfigs/enable-xen-config index 1f9945faef..1d40aca3e5 100644 --- a/buildconfigs/enable-xen-config +++ b/buildconfigs/enable-xen-config @@ -1,6 +1,6 @@ #!/bin/sh -set -ex +set -e if [ $# -ne 1 ] ; then echo "Usage $(basename $0) " 1>&2 @@ -26,6 +26,7 @@ setopt() } setopt CONFIG_PARAVIRT y +setopt CONFIG_PARAVIRT_GUEST y setopt CONFIG_XEN y setopt CONFIG_VMI y setopt CONFIG_KVM y @@ -37,4 +38,10 @@ setopt CONFIG_XEN_NETDEV_FRONTEND y setopt CONFIG_HVC_XEN y setopt CONFIG_NUMA n +case ${XEN_TARGET_ARCH} in + x86_32) setopt CONFIG_64BIT n ;; + x86_64) setopt CONFIG_64BIT y ;; + *) ;; +esac + exit 0 diff --git a/buildconfigs/mk.linux-2.6-common b/buildconfigs/mk.linux-2.6-common index 5b6810c56d..024d55f680 100644 --- a/buildconfigs/mk.linux-2.6-common +++ b/buildconfigs/mk.linux-2.6-common @@ -20,22 +20,9 @@ else __NONINT_CONFIG = endif -# Let XEN_TARGET_ARCH override ARCH. -ifeq ($(XEN_TARGET_ARCH),x86_32) -LINUX_ARCH ?= i386 -else -LINUX_ARCH ?= $(XEN_TARGET_ARCH) -endif - LINUX_DIR = build-linux-$(LINUX_VER)$(EXTRAVERSION)_$(XEN_TARGET_ARCH) IMAGE_TARGET ?= vmlinuz -ifneq ($(XEN_TARGET_ARCH),ia64) -IMAGE_PATH ?= arch/$(LINUX_ARCH)/boot/$(firstword $(IMAGE_TARGET)) -else -IMAGE_PATH ?= arch/ia64/hp/sim/boot/vmlinux.gz -endif -INSTALL_BOOT_PATH := $(DESTDIR)/boot LINUX_VER3 := $(LINUX_SERIES).$(word 3, $(subst ., ,$(LINUX_VER))) @@ -44,6 +31,11 @@ _build: build include buildconfigs/src.$(XEN_LINUX_SOURCE) +LINUX_ARCH = $$(sh buildconfigs/select-linux-arch $(LINUX_SRCDIR)) +IMAGE_PATH = $$(sh buildconfigs/select-linux-image $(LINUX_DIR) $(LINUX_ARCH) $(IMAGE_TARGET)) + +INSTALL_BOOT_PATH := $(DESTDIR)/boot + # Default to allowing interface mismatch ifndef XEN_LINUX_ALLOW_INTERFACE_MISMATCH XEN_LINUX_ALLOW_INTERFACE_MISMATCH := y @@ -70,9 +62,9 @@ endif fi $(MAKE) -C $(LINUX_DIR) ARCH=$(LINUX_ARCH) INSTALL_PATH=$(DESTDIR) $(IMAGE_TARGET) mkdir -p $(INSTALL_BOOT_PATH) - cp $(LINUX_DIR)/$(IMAGE_PATH) $(INSTALL_BOOT_PATH)/vmlinuz-$(KERNELRELEASE) - cp $(LINUX_DIR)/.config $(INSTALL_BOOT_PATH)/config-$(KERNELRELEASE) - cp $(LINUX_DIR)/System.map $(INSTALL_BOOT_PATH)/System.map-$(KERNELRELEASE) + @cp -v $(IMAGE_PATH) $(INSTALL_BOOT_PATH)/vmlinuz-$(KERNELRELEASE) + @cp -v $(LINUX_DIR)/.config $(INSTALL_BOOT_PATH)/config-$(KERNELRELEASE) + @cp -v $(LINUX_DIR)/System.map $(INSTALL_BOOT_PATH)/System.map-$(KERNELRELEASE) $(LINUX_DIR)/include/linux/autoconf.h: CONFIG_FILE=$(CURDIR)/$(LINUX_DIR)/.config $(LINUX_DIR)/include/linux/autoconf.h: $(LINUX_SRCDIR)/.valid-src diff --git a/buildconfigs/select-linux-arch b/buildconfigs/select-linux-arch new file mode 100755 index 0000000000..a5d0856e12 --- /dev/null +++ b/buildconfigs/select-linux-arch @@ -0,0 +1,30 @@ +#!/bin/sh + +ME=$(basename $0) + +if [ $# -lt 1 ] || [ $# -gt 2 ] ; then + echo "usage: $ME " 1>&2 + exit 1; +fi + +LINUX_DIR=$1 + +case ${XEN_TARGET_ARCH} in + x86_32|x86_64) + if [ -d ${LINUX_DIR}/arch/x86 ] ; then + ARCH=x86 + elif [ "${XEN_TARGET_ARCH}" = "x86_32" ] ; then + ARCH=i386 + else + ARCH=x86_64 + fi + ;; + *) + ARCH=${XEN_TARGET_ARCH} + ;; +esac + +echo "$ME: ${ARCH}" 1>&2 +echo ${ARCH} + +exit 0 diff --git a/buildconfigs/select-linux-image b/buildconfigs/select-linux-image new file mode 100755 index 0000000000..07899f80e2 --- /dev/null +++ b/buildconfigs/select-linux-image @@ -0,0 +1,33 @@ +#!/bin/sh + +ME=$(basename $0) + +if [ $# -lt 3 ] ; then + echo "usage: $ME " 1>&2 + exit 1; +fi + +LINUX_DIR=$1 +LINUX_ARCH=$2 +LINUX_TARGET=$3 # We don't care about second and subsequent targets + +case ${XEN_TARGET_ARCH} in + ia64) + IMAGE=${LINUX_DIR}/arch/ia64/hp/sim/boot/vmlinux.gz + ;; + *) + if [ -f ${LINUX_DIR}/arch/${LINUX_ARCH}/boot/${LINUX_TARGET} ] ; then + IMAGE=${LINUX_DIR}/arch/${LINUX_ARCH}/boot/${LINUX_TARGET} + elif [ -f ${LINUX_DIR}/${LINUX_TARGET} ] ; then + IMAGE=${LINUX_DIR}/${LINUX_TARGET} + else + echo "$ME: cannot determine Linux image to use for ${LINUX_ARCH} in ${LINUX_DIR}" 1>&2 + exit 1 + fi + ;; +esac + +echo "$ME: ${IMAGE}" 1>&2 +echo ${IMAGE} + +exit 0 -- cgit v1.2.3 From 03dc7c2febb658da3fb7bf0b814e69c098d56bce Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Tue, 12 Feb 2008 14:59:22 +0000 Subject: [BUILD] Disable LOCALVERSION_AUTO in upstream Linux builds. If this option is enabled then the Xen mercurial version ID gets tacked onto the kernel version (e.g. 2.6.24-git22-hg2593b69b183b) which is unlikely to be useful or desirable. All the trees which we build using this method already have uniquely identifying versions (e.g. 2.6.24-git22 or 2.6.24-mm1). Signed-off-by: Ian Campbell --- buildconfigs/enable-xen-config | 1 + 1 file changed, 1 insertion(+) diff --git a/buildconfigs/enable-xen-config b/buildconfigs/enable-xen-config index 1d40aca3e5..75f648eab6 100644 --- a/buildconfigs/enable-xen-config +++ b/buildconfigs/enable-xen-config @@ -37,6 +37,7 @@ setopt CONFIG_XEN_BLKDEV_FRONTEND y setopt CONFIG_XEN_NETDEV_FRONTEND y setopt CONFIG_HVC_XEN y setopt CONFIG_NUMA n +setopt CONFIG_LOCALVERSION_AUTO n case ${XEN_TARGET_ARCH} in x86_32) setopt CONFIG_64BIT n ;; -- cgit v1.2.3 From 6e30359431245bde61c200b0e88ac256e6f7978e Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Tue, 12 Feb 2008 15:03:07 +0000 Subject: Make stubdom/Makefile override XEN_OS to MiniOS, and add config/MiniOS.mk. Add PTHREAD_LIBS to configs (usually holding -lpthread). Signed-off-by: Samuel Thibault --- Config.mk | 8 -------- config/MiniOS.mk | 9 +++++++++ config/StdGNU.mk | 1 + config/SunOS.mk | 1 + stubdom/Makefile | 2 ++ tools/libxc/Makefile | 12 +++--------- 6 files changed, 16 insertions(+), 17 deletions(-) create mode 100644 config/MiniOS.mk diff --git a/Config.mk b/Config.mk index 771d1fbfbc..5715debf9b 100644 --- a/Config.mk +++ b/Config.mk @@ -28,14 +28,6 @@ DESTDIR ?= / include $(XEN_ROOT)/config/$(XEN_OS).mk include $(XEN_ROOT)/config/$(XEN_TARGET_ARCH).mk -ifeq ($(stubdom),y) -include $(XEN_ROOT)/extras/mini-os/Config.mk -CFLAGS += $(DEF_CFLAGS) $(ARCH_CFLAGS) -CPPFLAGS += $(DEF_CPPFLAGS) $(ARCH_CPPFLAGS) $(extra_incl) -ASFLAGS += $(DEF_ASFLAGS) $(ARCH_ASFLAGS) -LDFLAGS += $(DEF_LDFLAGS) $(ARCH_LDFLAGS) -endif - ifneq ($(EXTRA_PREFIX),) EXTRA_INCLUDES += $(EXTRA_PREFIX)/include EXTRA_LIB += $(EXTRA_PREFIX)/$(LIBLEAFDIR) diff --git a/config/MiniOS.mk b/config/MiniOS.mk new file mode 100644 index 0000000000..fc02b70fc4 --- /dev/null +++ b/config/MiniOS.mk @@ -0,0 +1,9 @@ +include $(XEN_ROOT)/config/StdGNU.mk +include $(XEN_ROOT)/extras/mini-os/Config.mk +CFLAGS += $(DEF_CFLAGS) $(ARCH_CFLAGS) +CPPFLAGS += $(DEF_CPPFLAGS) $(ARCH_CPPFLAGS) $(extra_incl) +ASFLAGS += $(DEF_ASFLAGS) $(ARCH_ASFLAGS) +LDFLAGS += $(DEF_LDFLAGS) $(ARCH_LDFLAGS) + +# Override settings for this OS +PTHREAD_LIBS = diff --git a/config/StdGNU.mk b/config/StdGNU.mk index dfbc7ece44..82a99d3f11 100644 --- a/config/StdGNU.mk +++ b/config/StdGNU.mk @@ -35,6 +35,7 @@ PRIVATE_BINDIR = $(PRIVATE_PREFIX)/bin SOCKET_LIBS = CURSES_LIBS = -lncurses +PTHREAD_LIBS = -lpthread UTIL_LIBS = -lutil SONAME_LDFLAG = -soname SHLIB_CFLAGS = -shared diff --git a/config/SunOS.mk b/config/SunOS.mk index e6035bf4ca..c2a5594000 100644 --- a/config/SunOS.mk +++ b/config/SunOS.mk @@ -39,6 +39,7 @@ SunOS_LIBDIR_x86_64 = /usr/sfw/lib/amd64 SOCKET_LIBS = -lsocket CURSES_LIBS = -lcurses +PTHREAD_LIBS = -lpthread UTIL_LIBS = SONAME_LDFLAG = -h SHLIB_CFLAGS = -R $(SunOS_LIBDIR) -shared diff --git a/stubdom/Makefile b/stubdom/Makefile index ca2f342c3a..ae455be2a6 100644 --- a/stubdom/Makefile +++ b/stubdom/Makefile @@ -1,5 +1,7 @@ XEN_ROOT = .. +export XEN_OS=MiniOS + include $(XEN_ROOT)/Config.mk export stubdom=y export debug=y diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile index 41dcbab808..b73bbfe55b 100644 --- a/tools/libxc/Makefile +++ b/tools/libxc/Makefile @@ -25,13 +25,11 @@ ifneq ($(stubdom),y) CTRL_SRCS-y += xc_resume.c endif CTRL_SRCS-$(CONFIG_X86) += xc_pagetab.c -ifneq ($(stubdom),y) CTRL_SRCS-$(CONFIG_Linux) += xc_linux.c CTRL_SRCS-$(CONFIG_SunOS) += xc_solaris.c CTRL_SRCS-$(CONFIG_X86_Linux) += xc_ptrace.c xc_ptrace_core.c CTRL_SRCS-$(CONFIG_NetBSD) += xc_netbsd.c -endif -CTRL_SRCS-$(stubdom) += xc_minios.c +CTRL_SRCS-$(CONFIG_MiniOS) += xc_minios.c GUEST_SRCS-y := GUEST_SRCS-y += xg_private.c @@ -75,10 +73,6 @@ CFLAGS += -Wp,-MD,.$(@F).d LDFLAGS += -L. DEPS = .*.d -ifneq ($(stubdom),y) -LDLIBS = -lpthread -endif - CTRL_LIB_OBJS := $(patsubst %.c,%.o,$(CTRL_SRCS-y)) CTRL_PIC_OBJS := $(patsubst %.c,%.opic,$(CTRL_SRCS-y)) @@ -152,7 +146,7 @@ libxenctrl.so.$(MAJOR): libxenctrl.so.$(MAJOR).$(MINOR) ln -sf $< $@ libxenctrl.so.$(MAJOR).$(MINOR): $(CTRL_PIC_OBJS) - $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $^ $(LDLIBS) + $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenctrl.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $^ $(PTHREAD_LIBS) # libxenguest @@ -165,7 +159,7 @@ libxenguest.so.$(MAJOR): libxenguest.so.$(MAJOR).$(MINOR) ln -sf $< $@ libxenguest.so.$(MAJOR).$(MINOR): $(GUEST_PIC_OBJS) libxenctrl.so - $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenguest.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $(GUEST_PIC_OBJS) -lz -lxenctrl $(LDLIBS) + $(CC) $(CFLAGS) $(LDFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,libxenguest.so.$(MAJOR) $(SHLIB_CFLAGS) -o $@ $(GUEST_PIC_OBJS) -lz -lxenctrl $(PTHREAD_LIBS) -include $(DEPS) -- cgit v1.2.3 From 6d125ecd2380843e91b371d6ecd016b7fca67dd5 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Tue, 12 Feb 2008 16:46:23 +0000 Subject: stubdom: Rename stubdom/*.build into stubdom/*-build, newlib into newlib-cvs, lwip into lwip-cvs. Fix .hgignore to ignore only them and not the patches. Signed-off-by: Samuel Thibault --- .hgignore | 22 +++--- stubdom/Makefile | 39 +++++----- stubdom/binutils.patch | 14 ++++ stubdom/gcc.patch | 31 ++++++++ stubdom/newlib.patch | 203 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 279 insertions(+), 30 deletions(-) create mode 100644 stubdom/binutils.patch create mode 100644 stubdom/gcc.patch create mode 100644 stubdom/newlib.patch diff --git a/.hgignore b/.hgignore index f6affe953a..78f33293fa 100644 --- a/.hgignore +++ b/.hgignore @@ -80,17 +80,17 @@ ^pristine-.*$ ^ref-.*$ ^tmp-.*$ -^stubdom/binutils.*$ -^stubdom/cross-root.*$ -^stubdom/gcc.*$ -^stubdom/include.*$ -^stubdom/ioemu.*$ -^stubdom/libxc.*$ -^stubdom/lwip.*$ -^stubdom/mini-os.*$ -^stubdom/newlib.*$ -^stubdom/pciutils.*$ -^stubdom/zlib.*$ +^stubdom/binutils-.*$ +^stubdom/cross-root-.*$ +^stubdom/gcc-.*$ +^stubdom/include$ +^stubdom/ioemu$ +^stubdom/libxc$ +^stubdom/lwip-.*$ +^stubdom/mini-os$ +^stubdom/newlib-.*$ +^stubdom/pciutils-.*$ +^stubdom/zlib-.*$ ^tools/.*/TAGS$ ^tools/.*/build/lib.*/.*\.py$ ^tools/blktap/Makefile\.smh$ diff --git a/stubdom/Makefile b/stubdom/Makefile index ae455be2a6..21f6a2aa4a 100644 --- a/stubdom/Makefile +++ b/stubdom/Makefile @@ -54,8 +54,8 @@ BINUTILS_STAMPFILE=$(CROSS_ROOT)/bin/$(GNU_TARGET_ARCH)-xen-elf-ar .PHONY: cross-binutils cross-binutils: $(BINUTILS_STAMPFILE) $(BINUTILS_STAMPFILE): binutils-$(BINUTILS_VERSION) - mkdir -p binutils.build - ( cd binutils.build && \ + mkdir -p binutils-build + ( cd binutils-build && \ ../binutils-$(BINUTILS_VERSION)/configure --prefix=$(CROSS_PREFIX) --verbose --target=$(GNU_TARGET_ARCH)-xen-elf && \ $(MAKE) && \ $(MAKE) check && \ @@ -76,8 +76,8 @@ GCC_STAMPFILE=$(CROSS_ROOT)/bin/$(GNU_TARGET_ARCH)-xen-elf-gcc-$(GCC_VERSION) .PHONY: cross-gcc cross-gcc: $(GCC_STAMPFILE) $(GCC_STAMPFILE): gcc-$(GCC_VERSION) $(BINUTILS_STAMPFILE) - mkdir -p gcc.build - ( cd gcc.build && \ + mkdir -p gcc-build + ( cd gcc-build && \ ../gcc-$(GCC_VERSION)/configure --prefix=$(CROSS_PREFIX) --verbose --target=$(GNU_TARGET_ARCH)-xen-elf --enable-languages=c --disable-libssp --with-gnu-as --with-gnu-ld && \ $(MAKE) GCC_FOR_TARGET='$$$$r/gcc/xgcc -B$$$$r/gcc/ '"$(TARGET_CFLAGS)"' $$(FLAGS_FOR_TARGET)' && \ $(MAKE) install ) @@ -88,16 +88,16 @@ $(GCC_STAMPFILE): gcc-$(GCC_VERSION) $(BINUTILS_STAMPFILE) newlib: cvs -z 9 -d :pserver:anoncvs@sources.redhat.com:/cvs/src co -D $(NEWLIB_DATE) newlib - mv src newlib - ( cd newlib && patch -p0 < ../newlib.patch) + mv src newlib-cvs + ( cd newlib-cvs && patch -p0 < ../newlib.patch) NEWLIB_STAMPFILE=$(CROSS_ROOT)/$(GNU_TARGET_ARCH)-xen-elf/lib/libc.a .PHONY: cross-newlib cross-newlib: $(NEWLIB_STAMPFILE) $(NEWLIB_STAMPFILE): newlib $(GCC_STAMPFILE) - mkdir -p newlib.build - ( cd newlib.build && \ - CC_FOR_TARGET="$(GNU_TARGET_ARCH)-xen-elf-gcc $(TARGET_CFLAGS)" ../newlib/configure --prefix=$(CROSS_PREFIX) --verbose --target=$(GNU_TARGET_ARCH)-xen-elf --enable-newlib-io-long-long && \ + mkdir -p newlib-build + ( cd newlib-build && \ + CC_FOR_TARGET="$(GNU_TARGET_ARCH)-xen-elf-gcc $(TARGET_CFLAGS)" ../newlib-cvs/configure --prefix=$(CROSS_PREFIX) --verbose --target=$(GNU_TARGET_ARCH)-xen-elf --enable-newlib-io-long-long && \ $(MAKE) && \ $(MAKE) install ) @@ -144,8 +144,9 @@ $(LIBPCI_STAMPFILE): pciutils-$(LIBPCI_VERSION).tar.bz2 $(NEWLIB_STAMPFILE) $(ZL # lwIP ###### -lwip: +lwip-cvs: cvs -z 9 -d :pserver:anonymous@cvs.savannah.nongnu.org:/sources/lwip co -D $(LWIP_DATE) lwip + mv lwip lwip-cvs ####### # Links @@ -190,7 +191,7 @@ libxc: cross-zlib mk-symlinks ioemu: cross-zlib cross-libpci mk-symlinks libxc [ -f ioemu/config-host.mak ] || \ ( cd ioemu ; XEN_TARGET_ARCH=$(XEN_TARGET_ARCH) sh configure --prefix=/usr --enable-stubdom $(IOEMU_OPTIONS)) - $(MAKE) -C ioemu LWIPDIR=$(CURDIR)/lwip + $(MAKE) -C ioemu LWIPDIR=$(CURDIR)/lwip-cvs ###### # caml @@ -205,12 +206,12 @@ caml: ######## .PHONY: qemu-stubdom -qemu-stubdom: mk-symlinks lwip libxc ioemu - $(MAKE) -C mini-os LWIPDIR=$(CURDIR)/lwip QEMUDIR=$(CURDIR)/ioemu +qemu-stubdom: mk-symlinks lwip-cvs libxc ioemu + $(MAKE) -C mini-os LWIPDIR=$(CURDIR)/lwip-cvs QEMUDIR=$(CURDIR)/ioemu .PHONY: caml-stubdom -caml-stubdom: mk-symlinks lwip libxc cross-libpci caml - $(MAKE) -C mini-os LWIPDIR=$(CURDIR)/lwip CAMLDIR=$(CURDIR)/caml +caml-stubdom: mk-symlinks lwip-cvs libxc cross-libpci caml + $(MAKE) -C mini-os LWIPDIR=$(CURDIR)/lwia-cvs CAMLDIR=$(CURDIR)/caml ######### # install @@ -227,7 +228,7 @@ install: mini-os/mini-os.gz # Only clean the libxc/ioemu/mini-os part .PHONY: clean clean: - -$(MAKE) -C mini-os LWIPDIR=$(CURDIR)/lwip clean + -$(MAKE) -C mini-os LWIPDIR=$(CURDIR)/lwip-cvs clean $(MAKE) -C caml clean rm -fr libxc ioemu mini-os include @@ -235,7 +236,7 @@ clean: .PHONY: crossclean crossclean: clean rm -fr $(CROSS_ROOT) - rm -fr binutils.build gcc.build newlib.build + rm -fr binutils-build gcc-build newlib-build rm -fr zlib-$(ZLIB_VERSION) pciutils-$(LIBPCI_VERSION) # clean patched sources @@ -243,8 +244,8 @@ crossclean: clean patchclean: crossclean rm -fr binutils-$(BINUTILS_VERSION) rm -fr gcc-$(GCC_VERSION) - rm -fr newlib - rm -fr lwip + rm -fr newlib-cvs + rm -fr lwip-cvs # clean downloads .PHONY: downloadclean diff --git a/stubdom/binutils.patch b/stubdom/binutils.patch new file mode 100644 index 0000000000..65f120a377 --- /dev/null +++ b/stubdom/binutils.patch @@ -0,0 +1,14 @@ +It looks like binutils has troubles with makeinfo and the doc generation. +We don't need it anyway + +--- binutils-2.18/bfd/Makefile.inorig 2008-01-16 16:17:43.004484000 +0000 ++++ binutils-2.18/bfd/Makefile.in 2008-01-16 16:17:50.505526000 +0000 +@@ -271,7 +271,7 @@ + INCDIR = $(srcdir)/../include + CSEARCH = -I. -I$(srcdir) -I$(INCDIR) + MKDEP = gcc -MM +-SUBDIRS = doc po ++SUBDIRS = po + bfddocdir = doc + bfdlib_LTLIBRARIES = libbfd.la + AM_CFLAGS = $(WARN_CFLAGS) diff --git a/stubdom/gcc.patch b/stubdom/gcc.patch new file mode 100644 index 0000000000..d593986ab7 --- /dev/null +++ b/stubdom/gcc.patch @@ -0,0 +1,31 @@ +Backported from later versions + +--- gcc-4.2.2/gcc/config.gcc 2007-11-22 16:27:45.000000000 +0000 ++++ gcc-4.2.2/gcc/config.gcc 2007-11-22 16:23:00.000000000 +0000 +@@ -1033,6 +1033,11 @@ + tmake_file="i386/t-i386elf t-svr4" + use_fixproto=yes + ;; ++x86_64-*-elf*) ++ tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h i386/i386elf.h i386/x86-64.h" ++ tmake_file="i386/t-i386elf t-svr4" ++ use_fixproto=yes ++ ;; + i[34567]86-sequent-ptx4* | i[34567]86-sequent-sysv4*) + if test x$gas = xyes + then + +We don't have a libc yet at this stage. Unused anyway + +--- gcc-4.2.2/gcc/unwind-generic.h.orig 2008-01-11 18:54:40.000000000 +0100 ++++ gcc-4.2.2/gcc/unwind-generic.h 2008-01-11 18:54:31.000000000 +0100 +@@ -203,7 +203,6 @@ + compatible with the standard ABI for IA-64, we inline these. */ + + #ifdef __ia64__ +-#include + + static inline _Unwind_Ptr + _Unwind_GetDataRelBase (struct _Unwind_Context *_C) +Backported from later versions + diff --git a/stubdom/newlib.patch b/stubdom/newlib.patch new file mode 100644 index 0000000000..217205cccf --- /dev/null +++ b/stubdom/newlib.patch @@ -0,0 +1,203 @@ +There is a mix between longs and long longs. + +Index: newlib/libc/include/inttypes.h +=================================================================== +RCS file: /cvs/src/src/newlib/libc/include/inttypes.h,v +retrieving revision 1.3 +diff -u -p -r1.3 inttypes.h +--- newlib/libc/include/inttypes.h 16 Dec 2005 19:03:12 -0000 1.3 ++++ newlib/libc/include/inttypes.h 8 Nov 2007 16:32:44 -0000 +@@ -163,12 +163,12 @@ + + + /* 64-bit types */ +-#if __have_longlong64 +-#define __PRI64(x) __STRINGIFY(ll##x) +-#define __SCN64(x) __STRINGIFY(ll##x) +-#elif __have_long64 ++#if __have_long64 + #define __PRI64(x) __STRINGIFY(l##x) + #define __SCN64(x) __STRINGIFY(l##x) ++#elif __have_longlong64 ++#define __PRI64(x) __STRINGIFY(ll##x) ++#define __SCN64(x) __STRINGIFY(ll##x) + #else + #define __PRI64(x) __STRINGIFY(x) + #define __SCN64(x) __STRINGIFY(x) +@@ -217,12 +217,12 @@ + #endif + + /* max-bit types */ +-#if __have_longlong64 +-#define __PRIMAX(x) __STRINGIFY(ll##x) +-#define __SCNMAX(x) __STRINGIFY(ll##x) +-#elif __have_long64 ++#if __have_long64 + #define __PRIMAX(x) __STRINGIFY(l##x) + #define __SCNMAX(x) __STRINGIFY(l##x) ++#elif __have_longlong64 ++#define __PRIMAX(x) __STRINGIFY(ll##x) ++#define __SCNMAX(x) __STRINGIFY(ll##x) + #else + #define __PRIMAX(x) __STRINGIFY(x) + #define __SCNMAX(x) __STRINGIFY(x) +@@ -242,12 +242,12 @@ + #define SCNxMAX __SCNMAX(x) + + /* ptr types */ +-#if __have_longlong64 +-#define __PRIPTR(x) __STRINGIFY(ll##x) +-#define __SCNPTR(x) __STRINGIFY(ll##x) +-#elif __have_long64 ++#if __have_long64 + #define __PRIPTR(x) __STRINGIFY(l##x) + #define __SCNPTR(x) __STRINGIFY(l##x) ++#elif __have_longlong64 ++#define __PRIPTR(x) __STRINGIFY(ll##x) ++#define __SCNPTR(x) __STRINGIFY(ll##x) + #else + #define __PRIPTR(x) __STRINGIFY(x) + #define __SCNPTR(x) __STRINGIFY(x) + +We don't want u?int32_t to be long as our code assume in a lot of places to be +int. + +Index: newlib/libc/include/stdint.h +=================================================================== +RCS file: /cvs/src/src/newlib/libc/include/stdint.h,v +retrieving revision 1.10 +diff -u -p -r1.10 stdint.h +--- newlib/libc/include/stdint.h 16 Aug 2006 21:39:43 -0000 1.10 ++++ newlib/libc/include/stdint.h 12 Feb 2008 13:07:52 -0000 +@@ -38,7 +38,7 @@ extern "C" { + #if __STDINT_EXP(LONG_MAX) > 0x7fffffff + #define __have_long64 1 + #elif __STDINT_EXP(LONG_MAX) == 0x7fffffff && !defined(__SPU__) +-#define __have_long32 1 ++/* #define __have_long32 1 */ + #endif + + #if __STDINT_EXP(SCHAR_MAX) == 0x7f + +Define the basic ia64 jump buffer + +Index: newlib/libc/include/machine/setjmp.h +=================================================================== +RCS file: /cvs/src/src/newlib/libc/include/machine/setjmp.h,v +retrieving revision 1.34 +diff -u -p -r1.34 setjmp.h +--- newlib/libc/include/machine/setjmp.h 7 Nov 2007 21:42:24 -0000 1.34 ++++ newlib/libc/include/machine/setjmp.h 11 Jan 2008 18:10:43 -0000 +@@ -72,6 +72,11 @@ _BEGIN_STD_C + #define _JBLEN 8 + #endif + ++#ifdef __ia64__ ++#define _JBTYPE long ++#define _JBLEN 70 ++#endif ++ + #ifdef __i960__ + #define _JBLEN 35 + #endif + +In mini-os we use a dynamic reentrency buffer. + +Index: newlib/libc/include/sys/config.h +=================================================================== +RCS file: /cvs/src/src/newlib/libc/include/sys/config.h,v +retrieving revision 1.47 +diff -u -p -r1.47 config.h +--- newlib/libc/include/sys/config.h 15 Mar 2007 21:32:12 -0000 1.47 ++++ newlib/libc/include/sys/config.h 8 Nov 2007 16:32:44 -0000 +@@ -71,6 +71,10 @@ + #endif + #endif + ++#ifndef __DYNAMIC_REENT__ ++#define __DYNAMIC_REENT__ ++#endif ++ + #ifdef __mn10200__ + #define __SMALL_BITFIELDS + #endif + +Dynamic pointer to our reentrancy zone + +Index: newlib/libc/reent/getreent.c +=================================================================== +RCS file: /cvs/src/src/newlib/libc/reent/getreent.c,v +retrieving revision 1.2 +diff -u -p -r1.2 getreent.c +--- newlib/libc/reent/getreent.c 7 Sep 2007 00:45:55 -0000 1.2 ++++ newlib/libc/reent/getreent.c 8 Nov 2007 16:32:44 -0000 +@@ -3,12 +3,20 @@ + #include <_ansi.h> + #include + ++#define weak_alias(name, aliasname) \ ++ extern __typeof (name) aliasname __attribute__ ((weak, alias (#name))); ++ + #ifdef __getreent + #undef __getreent + #endif ++#ifdef __libc_getreent ++#undef __libc_getreent ++#endif + + struct _reent * +-_DEFUN_VOID(__getreent) ++__libc_getreent (void) + { + return _impure_ptr; + } ++weak_alias(__libc_getreent,__getreent) ++ + +We can't provide a red zone in mini-os. + +Index: newlib/libc/machine/x86_64/memcpy.S +=================================================================== +RCS file: /cvs/src/src/newlib/libc/machine/x86_64/memcpy.S,v +retrieving revision 1.1 +diff -u -p -r1.1 memcpy.S +--- newlib/libc/machine/x86_64/memcpy.S 28 Aug 2007 21:56:49 -0000 1.1 ++++ newlib/libc/machine/x86_64/memcpy.S 8 Nov 2007 16:32:44 -0000 +@@ -30,10 +30,18 @@ quadword_aligned: + cmpq $256, rdx + jb quadword_copy + ++#if 1 ++ subq $32, rsp ++ movq rax, 24 (rsp) ++ movq r12, 16 (rsp) ++ movq r13, 8 (rsp) ++ movq r14, 0 (rsp) ++#else + movq rax, -8 (rsp) + movq r12, -16 (rsp) + movq r13, -24 (rsp) + movq r14, -32 (rsp) ++#endif + + movq rdx, rcx /* Copy 128 bytes at a time with minimum cache polution */ + shrq $7, rcx +@@ -89,10 +97,18 @@ loop: + movq rdx, rcx + andq $127, rcx + rep movsb ++#if 1 ++ movq 24 (rsp), rax ++ movq 16 (rsp), r12 ++ movq 8 (rsp), r13 ++ movq 0 (rsp), r14 ++ addq $32, rsp ++#else + movq -8 (rsp), rax + movq -16 (rsp), r12 + movq -24 (rsp), r13 + movq -32 (rsp), r14 ++#endif + ret + + -- cgit v1.2.3 From afb567f7aac1201990530db17bc9f98e3c9f92b7 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Tue, 12 Feb 2008 16:59:08 +0000 Subject: stubdom: missing two renames (avoids always re-compiling newlib) Signed-off-by: Samuel Thibault --- stubdom/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stubdom/Makefile b/stubdom/Makefile index 21f6a2aa4a..7fdcdb22c0 100644 --- a/stubdom/Makefile +++ b/stubdom/Makefile @@ -86,7 +86,7 @@ $(GCC_STAMPFILE): gcc-$(GCC_VERSION) $(BINUTILS_STAMPFILE) # Cross-newlib ############## -newlib: +newlib-cvs: cvs -z 9 -d :pserver:anoncvs@sources.redhat.com:/cvs/src co -D $(NEWLIB_DATE) newlib mv src newlib-cvs ( cd newlib-cvs && patch -p0 < ../newlib.patch) @@ -94,7 +94,7 @@ newlib: NEWLIB_STAMPFILE=$(CROSS_ROOT)/$(GNU_TARGET_ARCH)-xen-elf/lib/libc.a .PHONY: cross-newlib cross-newlib: $(NEWLIB_STAMPFILE) -$(NEWLIB_STAMPFILE): newlib $(GCC_STAMPFILE) +$(NEWLIB_STAMPFILE): newlib-cvs $(GCC_STAMPFILE) mkdir -p newlib-build ( cd newlib-build && \ CC_FOR_TARGET="$(GNU_TARGET_ARCH)-xen-elf-gcc $(TARGET_CFLAGS)" ../newlib-cvs/configure --prefix=$(CROSS_PREFIX) --verbose --target=$(GNU_TARGET_ARCH)-xen-elf --enable-newlib-io-long-long && \ -- cgit v1.2.3 From 5ffec49444facf629f9cb4eab0cefa4433428d6e Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Wed, 13 Feb 2008 10:42:09 +0000 Subject: pv-on-hvm: Signal crash to Xen tools when HVM guest panics. Attached patch adds a function to automatically dump core file when guest linux on HVM domain panics, in the same way as PV domain. I tested this patch with kernel 2.6.9 and 2.6.18 on both of x86 and ia64 (to buid for ia64, some patches in the ia64 tree are needed) by the following steps, and confirmed it works well: 1. Build xen-platform-pci.ko. 2. In /etc/xen/xend-config.sxp, set (enable-dump yes). 3. On guest linux, execute insmod: # insmod xen-platform-pci.ko 4. When guest linux panics, a core file is dumped. Signed-off-by: Tetsu Yamamoto --- unmodified_drivers/linux-2.6/platform-pci/Kbuild | 1 + .../linux-2.6/platform-pci/panic-handler.c | 54 ++++++++++++++++++++++ .../linux-2.6/platform-pci/platform-pci.c | 4 ++ 3 files changed, 59 insertions(+) create mode 100644 unmodified_drivers/linux-2.6/platform-pci/panic-handler.c diff --git a/unmodified_drivers/linux-2.6/platform-pci/Kbuild b/unmodified_drivers/linux-2.6/platform-pci/Kbuild index ab836e4d51..de3e50bca0 100644 --- a/unmodified_drivers/linux-2.6/platform-pci/Kbuild +++ b/unmodified_drivers/linux-2.6/platform-pci/Kbuild @@ -7,6 +7,7 @@ EXTRA_CFLAGS += -I$(M)/platform-pci xen-platform-pci-objs := evtchn.o platform-pci.o gnttab.o xen_support.o xen-platform-pci-objs += features.o platform-compat.o xen-platform-pci-objs += reboot.o machine_reboot.o +xen-platform-pci-objs += panic-handler.o xen-platform-pci-objs += ../xenbus/xenbus_comms.o xen-platform-pci-objs += ../xenbus/xenbus_xs.o diff --git a/unmodified_drivers/linux-2.6/platform-pci/panic-handler.c b/unmodified_drivers/linux-2.6/platform-pci/panic-handler.c new file mode 100644 index 0000000000..91bc03549b --- /dev/null +++ b/unmodified_drivers/linux-2.6/platform-pci/panic-handler.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); + +#ifdef __ia64__ +static void +xen_panic_hypercall(struct unw_frame_info *info, void *arg) +{ + current->thread.ksp = (__u64)info->sw - 16; + HYPERVISOR_shutdown(SHUTDOWN_crash); + /* we're never actually going to get here... */ +} +#endif + +static int +xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr) +{ +#ifdef __ia64__ + unw_init_running(xen_panic_hypercall, NULL); +#else /* !__ia64__ */ + HYPERVISOR_shutdown(SHUTDOWN_crash); +#endif + /* we're never actually going to get here... */ + return NOTIFY_DONE; +} +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) +static struct notifier_block xen_panic_block = { + xen_panic_event, NULL, 0 /* try to go last */ +}; +#else +static struct notifier_block xen_panic_block = { + .notifier_call= xen_panic_event, + .next= NULL, + .priority= 0/* try to go last */ +}; +#endif /*LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)*/ + +static int __init setup_panic_event(void) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) + notifier_chain_register(&panic_notifier_list, &xen_panic_block); +#else + atomic_notifier_chain_register(&panic_notifier_list, &xen_panic_block); +#endif /*LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)*/ + return 0; +} + +int xen_panic_handler_init(void) +{ + return setup_panic_event(); +} diff --git a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c index 7a512073d2..3d3a4c79a1 100644 --- a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c +++ b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c @@ -249,6 +249,7 @@ static int set_callback_via(uint64_t via) int xen_irq_init(struct pci_dev *pdev); int xenbus_init(void); int xen_reboot_init(void); +int xen_panic_handler_init(void); int gnttab_init(void); static int __devinit platform_pci_init(struct pci_dev *pdev, @@ -317,6 +318,9 @@ static int __devinit platform_pci_init(struct pci_dev *pdev, if ((ret = xen_reboot_init())) goto out; + if ((ret = xen_panic_handler_init())) + goto out; + out: if (ret) { release_mem_region(mmio_addr, mmio_len); -- cgit v1.2.3 From cbd2de39520605f71f07f303ae592a816f6bbcb0 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Wed, 13 Feb 2008 10:43:13 +0000 Subject: Tools: fix save/restore of 32-bit PV guests with 64-bit tools by removing some obvious typos, handling CR3 folding and hvirt_start based on guest word-size, and understanding 32-bit INVALID_MFN. Signed-off-by: Tim Deegan --- tools/libxc/xc_domain_restore.c | 12 +++++------ tools/libxc/xc_domain_save.c | 48 +++++++++++++++++++++-------------------- tools/libxc/xg_private.h | 4 +++- tools/libxc/xg_save_restore.h | 17 +++++++++++++++ 4 files changed, 51 insertions(+), 30 deletions(-) diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c index ec7e8fc9a2..52fc1155d2 100644 --- a/tools/libxc/xc_domain_restore.c +++ b/tools/libxc/xc_domain_restore.c @@ -251,7 +251,7 @@ static xen_pfn_t *load_p2m_frame_list( /* Now that we know the guest's word-size, can safely allocate * the p2m frame list */ - if ( (p2m_frame_list = malloc(P2M_FL_SIZE)) == NULL ) + if ( (p2m_frame_list = malloc(P2M_TOOLS_FL_SIZE)) == NULL ) { ERROR("Couldn't allocate p2m_frame_list array"); return NULL; @@ -1040,7 +1040,7 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom, SET_FIELD(&ctxt, gdt_frames[j], p2m[pfn]); } /* Uncanonicalise the page table base pointer. */ - pfn = xen_cr3_to_pfn(GET_FIELD(&ctxt, ctrlreg[3])); + pfn = UNFOLD_CR3(GET_FIELD(&ctxt, ctrlreg[3])); if ( pfn >= p2m_size ) { @@ -1057,12 +1057,12 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom, (unsigned long)pt_levels<= p2m_size ) { ERROR("User PT base is bad: pfn=%lu p2m_size=%lu", @@ -1077,7 +1077,7 @@ int xc_domain_restore(int xc_handle, int io_fd, uint32_t dom, (unsigned long)pt_levels< sizeof (xen_pfn_t) ) for ( i = p2m_size - 1; i >= 0; i-- ) ((uint64_t *)p2m)[i] = p2m[i]; - else if ( guest_width > sizeof (xen_pfn_t) ) + else if ( guest_width < sizeof (xen_pfn_t) ) for ( i = 0; i < p2m_size; i++ ) ((uint32_t *)p2m)[i] = p2m[i]; diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c index d37ea9cd51..3bd2db08b6 100644 --- a/tools/libxc/xc_domain_save.c +++ b/tools/libxc/xc_domain_save.c @@ -61,10 +61,11 @@ unsigned int guest_width; #define mfn_to_pfn(_mfn) (live_m2p[(_mfn)]) -#define pfn_to_mfn(_pfn) \ - ((xen_pfn_t) ((guest_width==8) \ - ? (((uint64_t *)live_p2m)[(_pfn)]) \ - : (((uint32_t *)live_p2m)[(_pfn)]))) +#define pfn_to_mfn(_pfn) \ + ((xen_pfn_t) ((guest_width==8) \ + ? (((uint64_t *)live_p2m)[(_pfn)]) \ + : ((((uint32_t *)live_p2m)[(_pfn)]) == 0xffffffffU \ + ? (-1UL) : (((uint32_t *)live_p2m)[(_pfn)])))) /* * Returns TRUE if the given machine frame number has a unique mapping @@ -496,10 +497,9 @@ static int canonicalize_pagetable(unsigned long type, unsigned long pfn, xen_start = L3_PAGETABLE_ENTRIES_PAE; /* - ** in PAE only the L2 mapping the top 1GB contains Xen mappings. - ** We can spot this by looking for the guest linear mapping which - ** Xen always ensures is present in that L2. Guests must ensure - ** that this check will fail for other L2s. + ** In PAE only the L2 mapping the top 1GB contains Xen mappings. + ** We can spot this by looking for the guest's mappingof the m2p. + ** Guests must ensure that this check will fail for other L2s. */ if ( (pt_levels == 3) && (type == XEN_DOMCTL_PFINFO_L2TAB) ) { @@ -555,7 +555,13 @@ static int canonicalize_pagetable(unsigned long type, unsigned long pfn, /* This will happen if the type info is stale which is quite feasible under live migration */ pfn = 0; /* zap it - we'll retransmit this page later */ - race = 1; /* inform the caller of race; fatal if !live */ + /* XXX: We can't spot Xen mappings in compat-mode L2es + * from 64-bit tools, but the only thing in them is the + * compat m2p, so we quietly zap them. This doesn't + * count as a race, so don't report it. */ + if ( !(type == XEN_DOMCTL_PFINFO_L2TAB + && sizeof (unsigned long) > guest_width) ) + race = 1; /* inform the caller; fatal if !live */ } else pfn = mfn_to_pfn(mfn); @@ -690,7 +696,7 @@ static xen_pfn_t *map_and_save_p2m_table(int xc_handle, else p2m_frame_list_list[i] = 0; else if ( guest_width < sizeof(unsigned long) ) - for ( i = PAGE_SIZE/sizeof(unsigned long) - 1; i >= 0; i++ ) + for ( i = PAGE_SIZE/sizeof(unsigned long) - 1; i >= 0; i-- ) p2m_frame_list_list[i] = ((uint32_t *)p2m_frame_list_list)[i]; live_p2m_frame_list = @@ -704,19 +710,20 @@ static xen_pfn_t *map_and_save_p2m_table(int xc_handle, } /* Get a local copy of the live_P2M_frame_list */ - if ( !(p2m_frame_list = malloc(P2M_FL_SIZE)) ) + if ( !(p2m_frame_list = malloc(P2M_TOOLS_FL_SIZE)) ) { ERROR("Couldn't allocate p2m_frame_list array"); goto out; } - memcpy(p2m_frame_list, live_p2m_frame_list, P2M_FL_SIZE); + memset(p2m_frame_list, 0, P2M_TOOLS_FL_SIZE); + memcpy(p2m_frame_list, live_p2m_frame_list, P2M_GUEST_FL_SIZE); /* Canonicalize guest's unsigned long vs ours */ if ( guest_width > sizeof(unsigned long) ) for ( i = 0; i < P2M_FL_ENTRIES; i++ ) p2m_frame_list[i] = ((uint64_t *)p2m_frame_list)[i]; else if ( guest_width < sizeof(unsigned long) ) - for ( i = P2M_FL_ENTRIES - 1; i >= 0; i++ ) + for ( i = P2M_FL_ENTRIES - 1; i >= 0; i-- ) p2m_frame_list[i] = ((uint32_t *)p2m_frame_list)[i]; @@ -1559,31 +1566,26 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } /* Canonicalise the page table base pointer. */ - if ( !MFN_IS_IN_PSEUDOPHYS_MAP(xen_cr3_to_pfn( - GET_FIELD(&ctxt, ctrlreg[3]))) ) + if ( !MFN_IS_IN_PSEUDOPHYS_MAP(UNFOLD_CR3( + GET_FIELD(&ctxt, ctrlreg[3]))) ) { ERROR("PT base is not in range of pseudophys map"); goto out; } SET_FIELD(&ctxt, ctrlreg[3], - xen_pfn_to_cr3( - mfn_to_pfn( - xen_cr3_to_pfn( - GET_FIELD(&ctxt, ctrlreg[3]))))); + FOLD_CR3(mfn_to_pfn(UNFOLD_CR3(GET_FIELD(&ctxt, ctrlreg[3]))))); /* Guest pagetable (x86/64) stored in otherwise-unused CR1. */ if ( (pt_levels == 4) && ctxt.x64.ctrlreg[1] ) { - if ( !MFN_IS_IN_PSEUDOPHYS_MAP( - xen_cr3_to_pfn(ctxt.x64.ctrlreg[1])) ) + if ( !MFN_IS_IN_PSEUDOPHYS_MAP(UNFOLD_CR3(ctxt.x64.ctrlreg[1])) ) { ERROR("PT base is not in range of pseudophys map"); goto out; } /* Least-significant bit means 'valid PFN'. */ ctxt.x64.ctrlreg[1] = 1 | - xen_pfn_to_cr3( - mfn_to_pfn(xen_cr3_to_pfn(ctxt.x64.ctrlreg[1]))); + FOLD_CR3(mfn_to_pfn(UNFOLD_CR3(ctxt.x64.ctrlreg[1]))); } if ( write_exact(io_fd, &ctxt, ((guest_width==8) diff --git a/tools/libxc/xg_private.h b/tools/libxc/xg_private.h index 679c31896c..2ed3f55849 100644 --- a/tools/libxc/xg_private.h +++ b/tools/libxc/xg_private.h @@ -155,7 +155,9 @@ typedef l4_pgentry_64_t l4_pgentry_t; #define P2M_FL_ENTRIES (((p2m_size)+FPP-1)/FPP) /* Size in bytes of the pfn_to_mfn_frame_list */ -#define P2M_FL_SIZE ((P2M_FL_ENTRIES)*(guest_width)) +#define P2M_GUEST_FL_SIZE ((P2M_FL_ENTRIES) * (guest_width)) +#define P2M_TOOLS_FL_SIZE ((P2M_FL_ENTRIES) * \ + MAX((sizeof (xen_pfn_t)), guest_width)) /* Masks for PTE<->PFN conversions */ #define MADDR_BITS_X86 ((guest_width == 8) ? 52 : 44) diff --git a/tools/libxc/xg_save_restore.h b/tools/libxc/xg_save_restore.h index b0379a4550..2da1e2090d 100644 --- a/tools/libxc/xg_save_restore.h +++ b/tools/libxc/xg_save_restore.h @@ -68,6 +68,13 @@ static inline int get_platform_info(int xc_handle, uint32_t dom, *guest_width = domctl.u.address_size.size / 8; + /* 64-bit tools will see the 64-bit hvirt_start, but 32-bit guests + * will be using the compat one. */ + if ( *guest_width < sizeof (unsigned long) ) + /* XXX need to fix up a way of extracting this value from Xen if + * XXX it becomes variable for domU */ + *hvirt_start = 0xf5800000; + if (strstr(xen_caps, "xen-3.0-x86_64")) /* Depends on whether it's a compat 32-on-64 guest */ *pt_levels = ( (*guest_width == 8) ? 4 : 3 ); @@ -136,6 +143,16 @@ typedef union (_p)->x32._f = (_v); \ } while (0) +#define UNFOLD_CR3(_c) \ + ((uint64_t)((guest_width == 8) \ + ? ((_c) >> 12) \ + : (((uint32_t)(_c) >> 12) | ((uint32_t)(_c) << 20)))) + +#define FOLD_CR3(_c) \ + ((uint64_t)((guest_width == 8) \ + ? ((uint64_t)(_c)) << 12 \ + : (((uint32_t)(_c) << 12) | ((uint32_t)(_c) >> 20)))) + #define MEMCPY_FIELD(_d, _s, _f) do { \ if (guest_width == 8) \ memcpy(&(_d)->x64._f, &(_s)->x64._f,sizeof((_d)->x64._f)); \ -- cgit v1.2.3 From b50b34362888b362e32f2011b6a76b7cc2717784 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Wed, 13 Feb 2008 14:03:58 +0000 Subject: x86 hvm: Factor out save/restore of segment registers from VMX/SVM files into common HVM code. Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/hvm.c | 121 ++++++++++++++++++++++++++++++++++++++++++-- xen/arch/x86/hvm/svm/svm.c | 98 +---------------------------------- xen/arch/x86/hvm/vmx/vmcs.c | 4 ++ xen/arch/x86/hvm/vmx/vmx.c | 107 ++------------------------------------- 4 files changed, 129 insertions(+), 201 deletions(-) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 0f543dac9c..e2e94a9c5f 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -287,9 +287,10 @@ static int hvm_save_cpu_ctxt(struct domain *d, hvm_domain_context_t *h) { struct vcpu *v; struct hvm_hw_cpu ctxt; + struct segment_register seg; struct vcpu_guest_context *vc; - for_each_vcpu(d, v) + for_each_vcpu ( d, v ) { /* We don't need to save state for a vcpu that is down; the restore * code will leave it down if there is nothing saved. */ @@ -299,12 +300,69 @@ static int hvm_save_cpu_ctxt(struct domain *d, hvm_domain_context_t *h) /* Architecture-specific vmcs/vmcb bits */ hvm_funcs.save_cpu_ctxt(v, &ctxt); - /* Other vcpu register state */ + hvm_get_segment_register(v, x86_seg_idtr, &seg); + ctxt.idtr_limit = seg.limit; + ctxt.idtr_base = seg.base; + + hvm_get_segment_register(v, x86_seg_gdtr, &seg); + ctxt.gdtr_limit = seg.limit; + ctxt.gdtr_base = seg.base; + + hvm_get_segment_register(v, x86_seg_cs, &seg); + ctxt.cs_sel = seg.sel; + ctxt.cs_limit = seg.limit; + ctxt.cs_base = seg.base; + ctxt.cs_arbytes = seg.attr.bytes; + + hvm_get_segment_register(v, x86_seg_ds, &seg); + ctxt.ds_sel = seg.sel; + ctxt.ds_limit = seg.limit; + ctxt.ds_base = seg.base; + ctxt.ds_arbytes = seg.attr.bytes; + + hvm_get_segment_register(v, x86_seg_es, &seg); + ctxt.es_sel = seg.sel; + ctxt.es_limit = seg.limit; + ctxt.es_base = seg.base; + ctxt.es_arbytes = seg.attr.bytes; + + hvm_get_segment_register(v, x86_seg_ss, &seg); + ctxt.ss_sel = seg.sel; + ctxt.ss_limit = seg.limit; + ctxt.ss_base = seg.base; + ctxt.ss_arbytes = seg.attr.bytes; + + hvm_get_segment_register(v, x86_seg_fs, &seg); + ctxt.fs_sel = seg.sel; + ctxt.fs_limit = seg.limit; + ctxt.fs_base = seg.base; + ctxt.fs_arbytes = seg.attr.bytes; + + hvm_get_segment_register(v, x86_seg_gs, &seg); + ctxt.gs_sel = seg.sel; + ctxt.gs_limit = seg.limit; + ctxt.gs_base = seg.base; + ctxt.gs_arbytes = seg.attr.bytes; + + hvm_get_segment_register(v, x86_seg_tr, &seg); + ctxt.tr_sel = seg.sel; + ctxt.tr_limit = seg.limit; + ctxt.tr_base = seg.base; + ctxt.tr_arbytes = seg.attr.bytes; + + hvm_get_segment_register(v, x86_seg_ldtr, &seg); + ctxt.ldtr_sel = seg.sel; + ctxt.ldtr_limit = seg.limit; + ctxt.ldtr_base = seg.base; + ctxt.ldtr_arbytes = seg.attr.bytes; + vc = &v->arch.guest_context; + if ( v->fpu_initialised ) memcpy(ctxt.fpu_regs, &vc->fpu_ctxt, sizeof(ctxt.fpu_regs)); else memset(ctxt.fpu_regs, 0, sizeof(ctxt.fpu_regs)); + ctxt.rax = vc->user_regs.eax; ctxt.rbx = vc->user_regs.ebx; ctxt.rcx = vc->user_regs.ecx; @@ -343,6 +401,7 @@ static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h) int vcpuid, rc; struct vcpu *v; struct hvm_hw_cpu ctxt; + struct segment_register seg; struct vcpu_guest_context *vc; /* Which vcpu is this? */ @@ -398,8 +457,64 @@ static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h) if ( hvm_funcs.load_cpu_ctxt(v, &ctxt) < 0 ) return -EINVAL; - /* Other vcpu register state */ + seg.limit = ctxt.idtr_limit; + seg.base = ctxt.idtr_base; + hvm_set_segment_register(v, x86_seg_idtr, &seg); + + seg.limit = ctxt.gdtr_limit; + seg.base = ctxt.gdtr_base; + hvm_set_segment_register(v, x86_seg_gdtr, &seg); + + seg.sel = ctxt.cs_sel; + seg.limit = ctxt.cs_limit; + seg.base = ctxt.cs_base; + seg.attr.bytes = ctxt.cs_arbytes; + hvm_set_segment_register(v, x86_seg_cs, &seg); + + seg.sel = ctxt.ds_sel; + seg.limit = ctxt.ds_limit; + seg.base = ctxt.ds_base; + seg.attr.bytes = ctxt.ds_arbytes; + hvm_set_segment_register(v, x86_seg_ds, &seg); + + seg.sel = ctxt.es_sel; + seg.limit = ctxt.es_limit; + seg.base = ctxt.es_base; + seg.attr.bytes = ctxt.es_arbytes; + hvm_set_segment_register(v, x86_seg_es, &seg); + + seg.sel = ctxt.ss_sel; + seg.limit = ctxt.ss_limit; + seg.base = ctxt.ss_base; + seg.attr.bytes = ctxt.ss_arbytes; + hvm_set_segment_register(v, x86_seg_ss, &seg); + + seg.sel = ctxt.fs_sel; + seg.limit = ctxt.fs_limit; + seg.base = ctxt.fs_base; + seg.attr.bytes = ctxt.fs_arbytes; + hvm_set_segment_register(v, x86_seg_fs, &seg); + + seg.sel = ctxt.gs_sel; + seg.limit = ctxt.gs_limit; + seg.base = ctxt.gs_base; + seg.attr.bytes = ctxt.gs_arbytes; + hvm_set_segment_register(v, x86_seg_gs, &seg); + + seg.sel = ctxt.tr_sel; + seg.limit = ctxt.tr_limit; + seg.base = ctxt.tr_base; + seg.attr.bytes = ctxt.tr_arbytes; + hvm_set_segment_register(v, x86_seg_tr, &seg); + + seg.sel = ctxt.ldtr_sel; + seg.limit = ctxt.ldtr_limit; + seg.base = ctxt.ldtr_base; + seg.attr.bytes = ctxt.ldtr_arbytes; + hvm_set_segment_register(v, x86_seg_ldtr, &seg); + memcpy(&vc->fpu_ctxt, ctxt.fpu_regs, sizeof(ctxt.fpu_regs)); + vc->user_regs.eax = ctxt.rax; vc->user_regs.ebx = ctxt.rbx; vc->user_regs.ecx = ctxt.rcx; diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index 3845946633..ed42ece5e5 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -181,7 +181,7 @@ static void svm_restore_dr(struct vcpu *v) __restore_debug_registers(v); } -int svm_vmcb_save(struct vcpu *v, struct hvm_hw_cpu *c) +static int svm_vmcb_save(struct vcpu *v, struct hvm_hw_cpu *c) { struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; @@ -190,52 +190,6 @@ int svm_vmcb_save(struct vcpu *v, struct hvm_hw_cpu *c) c->cr3 = v->arch.hvm_vcpu.guest_cr[3]; c->cr4 = v->arch.hvm_vcpu.guest_cr[4]; - c->idtr_limit = vmcb->idtr.limit; - c->idtr_base = vmcb->idtr.base; - - c->gdtr_limit = vmcb->gdtr.limit; - c->gdtr_base = vmcb->gdtr.base; - - c->cs_sel = vmcb->cs.sel; - c->cs_limit = vmcb->cs.limit; - c->cs_base = vmcb->cs.base; - c->cs_arbytes = vmcb->cs.attr.bytes; - - c->ds_sel = vmcb->ds.sel; - c->ds_limit = vmcb->ds.limit; - c->ds_base = vmcb->ds.base; - c->ds_arbytes = vmcb->ds.attr.bytes; - - c->es_sel = vmcb->es.sel; - c->es_limit = vmcb->es.limit; - c->es_base = vmcb->es.base; - c->es_arbytes = vmcb->es.attr.bytes; - - c->ss_sel = vmcb->ss.sel; - c->ss_limit = vmcb->ss.limit; - c->ss_base = vmcb->ss.base; - c->ss_arbytes = vmcb->ss.attr.bytes; - - c->fs_sel = vmcb->fs.sel; - c->fs_limit = vmcb->fs.limit; - c->fs_base = vmcb->fs.base; - c->fs_arbytes = vmcb->fs.attr.bytes; - - c->gs_sel = vmcb->gs.sel; - c->gs_limit = vmcb->gs.limit; - c->gs_base = vmcb->gs.base; - c->gs_arbytes = vmcb->gs.attr.bytes; - - c->tr_sel = vmcb->tr.sel; - c->tr_limit = vmcb->tr.limit; - c->tr_base = vmcb->tr.base; - c->tr_arbytes = vmcb->tr.attr.bytes; - - c->ldtr_sel = vmcb->ldtr.sel; - c->ldtr_limit = vmcb->ldtr.limit; - c->ldtr_base = vmcb->ldtr.base; - c->ldtr_arbytes = vmcb->ldtr.attr.bytes; - c->sysenter_cs = vmcb->sysenter_cs; c->sysenter_esp = vmcb->sysenter_esp; c->sysenter_eip = vmcb->sysenter_eip; @@ -253,8 +207,7 @@ int svm_vmcb_save(struct vcpu *v, struct hvm_hw_cpu *c) return 1; } - -int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c) +static int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c) { unsigned long mfn = 0; p2m_type_t p2mt; @@ -301,53 +254,6 @@ int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c) __func__, c->cr3, c->cr0, c->cr4); #endif - vmcb->idtr.limit = c->idtr_limit; - vmcb->idtr.base = c->idtr_base; - - vmcb->gdtr.limit = c->gdtr_limit; - vmcb->gdtr.base = c->gdtr_base; - - vmcb->cs.sel = c->cs_sel; - vmcb->cs.limit = c->cs_limit; - vmcb->cs.base = c->cs_base; - vmcb->cs.attr.bytes = c->cs_arbytes; - - vmcb->ds.sel = c->ds_sel; - vmcb->ds.limit = c->ds_limit; - vmcb->ds.base = c->ds_base; - vmcb->ds.attr.bytes = c->ds_arbytes; - - vmcb->es.sel = c->es_sel; - vmcb->es.limit = c->es_limit; - vmcb->es.base = c->es_base; - vmcb->es.attr.bytes = c->es_arbytes; - - vmcb->ss.sel = c->ss_sel; - vmcb->ss.limit = c->ss_limit; - vmcb->ss.base = c->ss_base; - vmcb->ss.attr.bytes = c->ss_arbytes; - vmcb->cpl = vmcb->ss.attr.fields.dpl; - - vmcb->fs.sel = c->fs_sel; - vmcb->fs.limit = c->fs_limit; - vmcb->fs.base = c->fs_base; - vmcb->fs.attr.bytes = c->fs_arbytes; - - vmcb->gs.sel = c->gs_sel; - vmcb->gs.limit = c->gs_limit; - vmcb->gs.base = c->gs_base; - vmcb->gs.attr.bytes = c->gs_arbytes; - - vmcb->tr.sel = c->tr_sel; - vmcb->tr.limit = c->tr_limit; - vmcb->tr.base = c->tr_base; - vmcb->tr.attr.bytes = c->tr_arbytes; - - vmcb->ldtr.sel = c->ldtr_sel; - vmcb->ldtr.limit = c->ldtr_limit; - vmcb->ldtr.base = c->ldtr_base; - vmcb->ldtr.attr.bytes = c->ldtr_arbytes; - vmcb->sysenter_cs = c->sysenter_cs; vmcb->sysenter_esp = c->sysenter_esp; vmcb->sysenter_eip = c->sysenter_eip; diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index cd0c844887..3fc6145be7 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -338,6 +338,8 @@ void vmx_vmcs_enter(struct vcpu *v) if ( likely(v == current) ) return; + BUG_ON(vcpu_runnable(v)); + fv = &this_cpu(foreign_vmcs); if ( fv->v == v ) @@ -368,6 +370,8 @@ void vmx_vmcs_exit(struct vcpu *v) if ( likely(v == current) ) return; + BUG_ON(vcpu_runnable(v)); + fv = &this_cpu(foreign_vmcs); BUG_ON(fv->v != v); BUG_ON(fv->count == 0); diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 50efb4fcd9..bdccd7b312 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -450,7 +450,7 @@ static void vmx_restore_dr(struct vcpu *v) __restore_debug_registers(v); } -void vmx_vmcs_save(struct vcpu *v, struct hvm_hw_cpu *c) +static void vmx_vmcs_save(struct vcpu *v, struct hvm_hw_cpu *c) { uint32_t ev; @@ -463,52 +463,6 @@ void vmx_vmcs_save(struct vcpu *v, struct hvm_hw_cpu *c) c->msr_efer = v->arch.hvm_vcpu.guest_efer; - c->idtr_limit = __vmread(GUEST_IDTR_LIMIT); - c->idtr_base = __vmread(GUEST_IDTR_BASE); - - c->gdtr_limit = __vmread(GUEST_GDTR_LIMIT); - c->gdtr_base = __vmread(GUEST_GDTR_BASE); - - c->cs_sel = __vmread(GUEST_CS_SELECTOR); - c->cs_limit = __vmread(GUEST_CS_LIMIT); - c->cs_base = __vmread(GUEST_CS_BASE); - c->cs_arbytes = __vmread(GUEST_CS_AR_BYTES); - - c->ds_sel = __vmread(GUEST_DS_SELECTOR); - c->ds_limit = __vmread(GUEST_DS_LIMIT); - c->ds_base = __vmread(GUEST_DS_BASE); - c->ds_arbytes = __vmread(GUEST_DS_AR_BYTES); - - c->es_sel = __vmread(GUEST_ES_SELECTOR); - c->es_limit = __vmread(GUEST_ES_LIMIT); - c->es_base = __vmread(GUEST_ES_BASE); - c->es_arbytes = __vmread(GUEST_ES_AR_BYTES); - - c->ss_sel = __vmread(GUEST_SS_SELECTOR); - c->ss_limit = __vmread(GUEST_SS_LIMIT); - c->ss_base = __vmread(GUEST_SS_BASE); - c->ss_arbytes = __vmread(GUEST_SS_AR_BYTES); - - c->fs_sel = __vmread(GUEST_FS_SELECTOR); - c->fs_limit = __vmread(GUEST_FS_LIMIT); - c->fs_base = __vmread(GUEST_FS_BASE); - c->fs_arbytes = __vmread(GUEST_FS_AR_BYTES); - - c->gs_sel = __vmread(GUEST_GS_SELECTOR); - c->gs_limit = __vmread(GUEST_GS_LIMIT); - c->gs_base = __vmread(GUEST_GS_BASE); - c->gs_arbytes = __vmread(GUEST_GS_AR_BYTES); - - c->tr_sel = __vmread(GUEST_TR_SELECTOR); - c->tr_limit = __vmread(GUEST_TR_LIMIT); - c->tr_base = __vmread(GUEST_TR_BASE); - c->tr_arbytes = __vmread(GUEST_TR_AR_BYTES); - - c->ldtr_sel = __vmread(GUEST_LDTR_SELECTOR); - c->ldtr_limit = __vmread(GUEST_LDTR_LIMIT); - c->ldtr_base = __vmread(GUEST_LDTR_BASE); - c->ldtr_arbytes = __vmread(GUEST_LDTR_AR_BYTES); - c->sysenter_cs = __vmread(GUEST_SYSENTER_CS); c->sysenter_esp = __vmread(GUEST_SYSENTER_ESP); c->sysenter_eip = __vmread(GUEST_SYSENTER_EIP); @@ -552,7 +506,7 @@ static int vmx_restore_cr0_cr3( return 0; } -int vmx_vmcs_restore(struct vcpu *v, struct hvm_hw_cpu *c) +static int vmx_vmcs_restore(struct vcpu *v, struct hvm_hw_cpu *c) { int rc; @@ -585,52 +539,6 @@ int vmx_vmcs_restore(struct vcpu *v, struct hvm_hw_cpu *c) v->arch.hvm_vcpu.guest_efer = c->msr_efer; vmx_update_guest_efer(v); - __vmwrite(GUEST_IDTR_LIMIT, c->idtr_limit); - __vmwrite(GUEST_IDTR_BASE, c->idtr_base); - - __vmwrite(GUEST_GDTR_LIMIT, c->gdtr_limit); - __vmwrite(GUEST_GDTR_BASE, c->gdtr_base); - - __vmwrite(GUEST_CS_SELECTOR, c->cs_sel); - __vmwrite(GUEST_CS_LIMIT, c->cs_limit); - __vmwrite(GUEST_CS_BASE, c->cs_base); - __vmwrite(GUEST_CS_AR_BYTES, c->cs_arbytes); - - __vmwrite(GUEST_DS_SELECTOR, c->ds_sel); - __vmwrite(GUEST_DS_LIMIT, c->ds_limit); - __vmwrite(GUEST_DS_BASE, c->ds_base); - __vmwrite(GUEST_DS_AR_BYTES, c->ds_arbytes); - - __vmwrite(GUEST_ES_SELECTOR, c->es_sel); - __vmwrite(GUEST_ES_LIMIT, c->es_limit); - __vmwrite(GUEST_ES_BASE, c->es_base); - __vmwrite(GUEST_ES_AR_BYTES, c->es_arbytes); - - __vmwrite(GUEST_SS_SELECTOR, c->ss_sel); - __vmwrite(GUEST_SS_LIMIT, c->ss_limit); - __vmwrite(GUEST_SS_BASE, c->ss_base); - __vmwrite(GUEST_SS_AR_BYTES, c->ss_arbytes); - - __vmwrite(GUEST_FS_SELECTOR, c->fs_sel); - __vmwrite(GUEST_FS_LIMIT, c->fs_limit); - __vmwrite(GUEST_FS_BASE, c->fs_base); - __vmwrite(GUEST_FS_AR_BYTES, c->fs_arbytes); - - __vmwrite(GUEST_GS_SELECTOR, c->gs_sel); - __vmwrite(GUEST_GS_LIMIT, c->gs_limit); - __vmwrite(GUEST_GS_BASE, c->gs_base); - __vmwrite(GUEST_GS_AR_BYTES, c->gs_arbytes); - - __vmwrite(GUEST_TR_SELECTOR, c->tr_sel); - __vmwrite(GUEST_TR_LIMIT, c->tr_limit); - __vmwrite(GUEST_TR_BASE, c->tr_base); - __vmwrite(GUEST_TR_AR_BYTES, c->tr_arbytes); - - __vmwrite(GUEST_LDTR_SELECTOR, c->ldtr_sel); - __vmwrite(GUEST_LDTR_LIMIT, c->ldtr_limit); - __vmwrite(GUEST_LDTR_BASE, c->ldtr_base); - __vmwrite(GUEST_LDTR_AR_BYTES, c->ldtr_arbytes); - __vmwrite(GUEST_SYSENTER_CS, c->sysenter_cs); __vmwrite(GUEST_SYSENTER_ESP, c->sysenter_esp); __vmwrite(GUEST_SYSENTER_EIP, c->sysenter_eip); @@ -821,7 +729,7 @@ static void vmx_get_segment_register(struct vcpu *v, enum x86_segment seg, { uint32_t attr = 0; - ASSERT(v == current); + vmx_vmcs_enter(v); switch ( seg ) { @@ -885,6 +793,8 @@ static void vmx_get_segment_register(struct vcpu *v, enum x86_segment seg, BUG(); } + vmx_vmcs_exit(v); + reg->attr.bytes = (attr & 0xff) | ((attr >> 4) & 0xf00); /* Unusable flag is folded into Present flag. */ if ( attr & (1u<<16) ) @@ -896,8 +806,6 @@ static void vmx_set_segment_register(struct vcpu *v, enum x86_segment seg, { uint32_t attr; - ASSERT((v == current) || !vcpu_runnable(v)); - attr = reg->attr.bytes; attr = ((attr & 0xf00) << 4) | (attr & 0xff); @@ -1029,7 +937,6 @@ static enum hvm_intblk vmx_interrupt_blocked( static void vmx_update_host_cr3(struct vcpu *v) { - ASSERT((v == current) || !vcpu_runnable(v)); vmx_vmcs_enter(v); __vmwrite(HOST_CR3, v->arch.cr3); vmx_vmcs_exit(v); @@ -1037,8 +944,6 @@ static void vmx_update_host_cr3(struct vcpu *v) static void vmx_update_guest_cr(struct vcpu *v, unsigned int cr) { - ASSERT((v == current) || !vcpu_runnable(v)); - vmx_vmcs_enter(v); switch ( cr ) @@ -1089,8 +994,6 @@ static void vmx_update_guest_efer(struct vcpu *v) #ifdef __x86_64__ unsigned long vm_entry_value; - ASSERT((v == current) || !vcpu_runnable(v)); - vmx_vmcs_enter(v); vm_entry_value = __vmread(VM_ENTRY_CONTROLS); -- cgit v1.2.3 From acfb1cc5308c5ec110415d97139744a95979adef Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Wed, 13 Feb 2008 16:25:32 +0000 Subject: x86 vmx: Remove bogus BUG_ON() introduced in previous changeset. Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/vmx/vmcs.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index 3fc6145be7..cd0c844887 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -338,8 +338,6 @@ void vmx_vmcs_enter(struct vcpu *v) if ( likely(v == current) ) return; - BUG_ON(vcpu_runnable(v)); - fv = &this_cpu(foreign_vmcs); if ( fv->v == v ) @@ -370,8 +368,6 @@ void vmx_vmcs_exit(struct vcpu *v) if ( likely(v == current) ) return; - BUG_ON(vcpu_runnable(v)); - fv = &this_cpu(foreign_vmcs); BUG_ON(fv->v != v); BUG_ON(fv->count == 0); -- cgit v1.2.3 From 782e0cae244bff4db4c195e600e2085a887c32df Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Wed, 13 Feb 2008 16:28:38 +0000 Subject: x86 vmx: Streamline vmx_interrupt_blocked() to avoid a VMREAD if interrupt delivery is blocked by EFLAGS.IF. This speeds up real-mode emulation in some cases (where we are currently executing hvm_local_events_need_delivery() after every instruction). Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/vmx/vmx.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index bdccd7b312..8d4629df36 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -917,6 +917,14 @@ static enum hvm_intblk vmx_interrupt_blocked( { unsigned long intr_shadow; + /* + * Test EFLAGS.IF first. It is often the most likely reason for interrupt + * blockage, and is the cheapest to test (because no VMREAD is required). + */ + if ( (intack.source != hvm_intsrc_nmi) && + !(guest_cpu_user_regs()->eflags & X86_EFLAGS_IF) ) + return hvm_intblk_rflags_ie; + intr_shadow = __vmread(GUEST_INTERRUPTIBILITY_INFO); if ( intr_shadow & (VMX_INTR_SHADOW_STI|VMX_INTR_SHADOW_MOV_SS) ) @@ -929,9 +937,6 @@ static enum hvm_intblk vmx_interrupt_blocked( ASSERT((intack.source == hvm_intsrc_pic) || (intack.source == hvm_intsrc_lapic)); - if ( !(guest_cpu_user_regs()->eflags & X86_EFLAGS_IF) ) - return hvm_intblk_rflags_ie; - return hvm_intblk_none; } -- cgit v1.2.3 From df46d3520618c41dae22794a93ada7abfe20ed95 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Wed, 13 Feb 2008 16:35:51 +0000 Subject: vmx realmode: __hvm_copy() should not hvm_get_segment_register() when we are emulating. Firstly it is bogus, since VMCS segment state is stale in this context. Secondly, real mode and real->protected contexts are rather unlikely tohappen with SS.DPL == 3. Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/hvm.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index e2e94a9c5f..92a63bf325 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -1386,6 +1386,7 @@ void hvm_task_switch( static enum hvm_copy_result __hvm_copy( void *buf, paddr_t addr, int size, int dir, int virt, int fetch) { + struct vcpu *curr = current; unsigned long gfn, mfn; p2m_type_t p2mt; char *p; @@ -1394,12 +1395,22 @@ static enum hvm_copy_result __hvm_copy( if ( virt ) { - struct segment_register sreg; - hvm_get_segment_register(current, x86_seg_ss, &sreg); - if ( sreg.attr.fields.dpl == 3 ) - pfec |= PFEC_user_mode; + /* + * We cannot use hvm_get_segment_register() while executing in + * vmx_realmode() as segment register state is cached. Furthermore, + * VMREADs on every data access hurts emulation performance. + */ + if ( !curr->arch.hvm_vmx.vmxemul ) + { + struct segment_register sreg; + hvm_get_segment_register(curr, x86_seg_ss, &sreg); + if ( sreg.attr.fields.dpl == 3 ) + pfec |= PFEC_user_mode; + } + if ( dir ) pfec |= PFEC_write_access; + if ( fetch ) pfec |= PFEC_insn_fetch; } @@ -1411,7 +1422,7 @@ static enum hvm_copy_result __hvm_copy( if ( virt ) { - gfn = paging_gva_to_gfn(current, addr, &pfec); + gfn = paging_gva_to_gfn(curr, addr, &pfec); if ( gfn == INVALID_GFN ) { if ( virt == 2 ) /* 2 means generate a fault */ @@ -1435,7 +1446,7 @@ static enum hvm_copy_result __hvm_copy( if ( dir ) { memcpy(p, buf, count); /* dir == TRUE: *to* guest */ - paging_mark_dirty(current->domain, mfn); + paging_mark_dirty(curr->domain, mfn); } else memcpy(buf, p, count); /* dir == FALSE: *from guest */ -- cgit v1.2.3 From 5dfa26a76cefd4220962ac1dfbf9028081c0ac5a Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Wed, 13 Feb 2008 18:09:27 +0000 Subject: vmx realmode: Only check for pending interrupts every 16th instruction, since it is a moderately expensive operation. Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/vmx/realmode.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/xen/arch/x86/hvm/vmx/realmode.c b/xen/arch/x86/hvm/vmx/realmode.c index dc9f76e645..8d7572e0d5 100644 --- a/xen/arch/x86/hvm/vmx/realmode.c +++ b/xen/arch/x86/hvm/vmx/realmode.c @@ -781,7 +781,7 @@ void vmx_realmode(struct cpu_user_regs *regs) struct vcpu *curr = current; struct realmode_emulate_ctxt rm_ctxt; unsigned long intr_info = __vmread(VM_ENTRY_INTR_INFO); - int i; + unsigned int i, emulations = 0; rm_ctxt.ctxt.regs = regs; @@ -804,11 +804,19 @@ void vmx_realmode(struct cpu_user_regs *regs) while ( curr->arch.hvm_vmx.vmxemul && !softirq_pending(smp_processor_id()) && - !curr->arch.hvm_vmx.real_mode_io_in_progress && - /* Check for pending interrupts only in proper real mode. */ - ((curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE) || - !hvm_local_events_need_delivery(curr)) ) + !curr->arch.hvm_vmx.real_mode_io_in_progress ) + { + /* + * Check for pending interrupts only every 16 instructions, because + * hvm_local_events_need_delivery() is moderately expensive, and only + * in real mode, because we don't emulate protected-mode IDT vectoring. + */ + if ( unlikely(!(++emulations & 15)) && + !(curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE) && + hvm_local_events_need_delivery(curr) ) + break; realmode_emulate_one(&rm_ctxt); + } if ( !curr->arch.hvm_vmx.vmxemul ) { -- cgit v1.2.3 From f280af038a947b67694780f999e06e05d11de1cf Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Wed, 13 Feb 2008 18:30:12 +0000 Subject: xen: Clean up SMP/hotplug headers and implementation a bit. Signed-off-by: Keir Fraser --- xen/arch/x86/smpboot.c | 5 ++- xen/common/stop_machine.c | 20 +++--------- xen/include/xen/smp.h | 72 ++++-------------------------------------- xen/include/xen/stop_machine.h | 11 ------- 4 files changed, 14 insertions(+), 94 deletions(-) diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c index 914ec62689..1377355048 100644 --- a/xen/arch/x86/smpboot.c +++ b/xen/arch/x86/smpboot.c @@ -112,7 +112,7 @@ static void map_cpu_to_logical_apicid(void); DEFINE_PER_CPU(int, cpu_state) = { 0 }; static void *stack_base[NR_CPUS] __cacheline_aligned; -spinlock_t cpu_add_remove_lock; +static DEFINE_SPINLOCK(cpu_add_remove_lock); /* * The bootstrap kernel entry code has set these up. Save them for @@ -1164,7 +1164,6 @@ void __devinit smp_prepare_boot_cpu(void) cpu_set(smp_processor_id(), cpu_present_map); cpu_set(smp_processor_id(), cpu_possible_map); per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE; - spin_lock_init(&cpu_add_remove_lock); } #ifdef CONFIG_HOTPLUG_CPU @@ -1298,7 +1297,7 @@ int cpu_down(unsigned int cpu) printk("Prepare to bring CPU%d down...\n", cpu); - err = __stop_machine_run(take_cpu_down, NULL, cpu); + err = stop_machine_run(take_cpu_down, NULL, cpu); if ( err < 0 ) goto out; diff --git a/xen/common/stop_machine.c b/xen/common/stop_machine.c index b109167ef7..1411b9f197 100644 --- a/xen/common/stop_machine.c +++ b/xen/common/stop_machine.c @@ -22,12 +22,13 @@ #include #include +#include #include -#include -#include #include -#include #include +#include +#include +#include enum stopmachine_state { STOPMACHINE_START, @@ -61,7 +62,7 @@ static void stopmachine_set_state(enum stopmachine_state state) cpu_relax(); } -int __stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu) +int stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu) { cpumask_t allbutself; unsigned int i, nr_cpus; @@ -116,17 +117,6 @@ int __stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu) return ret; } -int stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu) -{ - int ret; - - lock_cpu_hotplug(); - ret = __stop_machine_run(fn, data, cpu); - unlock_cpu_hotplug(); - - return ret; -} - static void stopmachine_softirq(void) { enum stopmachine_state state = STOPMACHINE_START; diff --git a/xen/include/xen/smp.h b/xen/include/xen/smp.h index 3e7de77ec8..6ab913a430 100644 --- a/xen/include/xen/smp.h +++ b/xen/include/xen/smp.h @@ -1,22 +1,9 @@ -#ifndef __LINUX_SMP_H -#define __LINUX_SMP_H - -/* - * Generic SMP support - * Alan Cox. - */ +#ifndef __XEN_SMP_H__ +#define __XEN_SMP_H__ #include - -#ifdef CONFIG_SMP - #include -/* - * main cross-CPU interfaces, handles INIT, TLB flush, STOP, etc. - * (defined in asm header): - */ - /* * stops all CPUs but the current one: */ @@ -66,38 +53,6 @@ extern int on_selected_cpus( */ void smp_prepare_boot_cpu(void); -#else - -/* - * These macros fold the SMP functionality into a single CPU system - */ - -#define smp_send_event_check_mask(m) ((void)0) -#define smp_send_event_check_cpu(p) ((void)0) -#define raw_smp_processor_id() 0 -#define hard_smp_processor_id() 0 -#define smp_call_function(func,info,retry,wait) ({ do {} while (0); 0; }) -#define num_booting_cpus() 1 -#define smp_prepare_boot_cpu() do {} while (0) - -static inline int on_selected_cpus( - cpumask_t selected, - void (*func) (void *info), - void *info, - int retry, - int wait) -{ - if ( cpu_isset(0, selected) ) - { - local_irq_disable(); - func(info); - local_irq_enable(); - } - return 0; -} - -#endif - /* * Call a function on all processors */ @@ -112,21 +67,8 @@ static inline int on_each_cpu( #define smp_processor_id() raw_smp_processor_id() -#ifdef CONFIG_HOTPLUG_CPU -extern spinlock_t cpu_add_remove_lock; -/* - * FIXME: need a better lock mechanism when real cpu hotplug is later - * supported, since spinlock may cause dead lock: - * cpu0: in stop_machine with lock held. Wait for cpu1 to respond - * to stop request - * cpu1: spin loop on lock upon cpu hotplug request from guest, - * without chance to handle softirq - * ... - */ -#define lock_cpu_hotplug() spin_lock(&cpu_add_remove_lock); -#define unlock_cpu_hotplug() spin_unlock(&cpu_add_remove_lock); -#else -#define lock_cpu_hotplug() do { } while ( 0 ) -#define unlock_cpu_hotplug() do { } while ( 0 ) -#endif -#endif +/* No Xen contexts can be preempted by CPU hotplug. */ +#define lock_cpu_hotplug() ((void)0) +#define unlock_cpu_hotplug() ((void)0) + +#endif /* __XEN_SMP_H__ */ diff --git a/xen/include/xen/stop_machine.h b/xen/include/xen/stop_machine.h index f379f6705a..7d4506869f 100644 --- a/xen/include/xen/stop_machine.h +++ b/xen/include/xen/stop_machine.h @@ -16,15 +16,4 @@ * grabbing every spinlock in the kernel. */ int stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu); -/** - * __stop_machine_run: freeze the machine on all CPUs and run this function - * @fn: the function to run - * @data: the data ptr for the @fn - * @cpu: the cpu to run @fn on (or any, if @cpu == NR_CPUS. - * - * Description: This is a special version of the above, without explicit - * lock acquisition. Used by hotplug cpu. - */ -int __stop_machine_run(int (*fn)(void *), void *data, unsigned int cpu); - #endif /* __XEN_STOP_MACHINE_H__ */ -- cgit v1.2.3 From fdbcfd71bbc84b9e44bc0c79489b750109a380d0 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 14 Feb 2008 09:22:33 +0000 Subject: Mini-OS: Fix alignment in maybe_split() Needed on ia64, speeds up on x86. Signed-off-by: Samuel Thibault --- extras/mini-os/lib/xmalloc.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/extras/mini-os/lib/xmalloc.c b/extras/mini-os/lib/xmalloc.c index 9e59c9f834..d4c3941738 100644 --- a/extras/mini-os/lib/xmalloc.c +++ b/extras/mini-os/lib/xmalloc.c @@ -62,10 +62,19 @@ struct xmalloc_pad size_t hdr_size; }; +/* Return size, increased to alignment with align. */ +static inline size_t align_up(size_t size, size_t align) +{ + return (size + align - 1) & ~(align - 1); +} + static void maybe_split(struct xmalloc_hdr *hdr, size_t size, size_t block) { struct xmalloc_hdr *extra; - size_t leftover = block - size; + size_t leftover; + size = align_up(size, __alignof__(struct xmalloc_hdr)); + size = align_up(size, __alignof__(struct xmalloc_pad)); + leftover = block - size; /* If enough is left to make a block, put it on free list. */ if ( leftover >= (2 * (sizeof(struct xmalloc_hdr) + sizeof(struct xmalloc_pad))) ) @@ -100,12 +109,6 @@ static struct xmalloc_hdr *xmalloc_new_page(size_t size) return hdr; } -/* Return size, increased to alignment with align. */ -static inline size_t align_up(size_t size, size_t align) -{ - return (size + align - 1) & ~(align - 1); -} - /* Big object? Just use the page allocator. */ static void *xmalloc_whole_pages(size_t size, size_t align) { -- cgit v1.2.3 From 20457bb88157c63901c0b1b7219bf084d4bac2a6 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 14 Feb 2008 09:23:14 +0000 Subject: stubdom: optimize block io completion polling by not polling all the time; only when some requests have completed. Signed-off-by: Samuel Thibault --- extras/mini-os/blkfront.c | 5 +++++ tools/ioemu/block-vbd.c | 10 +++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/extras/mini-os/blkfront.c b/extras/mini-os/blkfront.c index b83d5af345..1021bb018f 100644 --- a/extras/mini-os/blkfront.c +++ b/extras/mini-os/blkfront.c @@ -327,6 +327,11 @@ int blkfront_aio_poll(struct blkfront_dev *dev) struct blkif_response *rsp; moretodo: +#ifdef HAVE_LIBC + files[dev->fd].read = 0; + mb(); /* Make sure to let the handler set read to 1 before we start looking at the ring */ +#endif + rp = dev->ring.sring->rsp_prod; rmb(); /* Ensure we see queued responses up to 'rp'. */ cons = dev->ring.rsp_cons; diff --git a/tools/ioemu/block-vbd.c b/tools/ioemu/block-vbd.c index 9cb97255e6..5561cf1787 100644 --- a/tools/ioemu/block-vbd.c +++ b/tools/ioemu/block-vbd.c @@ -67,6 +67,12 @@ static int vbd_probe(const uint8_t *buf, int buf_size, const char *filename) return 100; } +static void vbd_io_completed(void *opaque) +{ + BDRVVbdState *s = opaque; + blkfront_aio_poll(s->dev); +} + static int vbd_open(BlockDriverState *bs, const char *filename, int flags) { BDRVVbdState *s = bs->opaque; @@ -85,6 +91,7 @@ static int vbd_open(BlockDriverState *bs, const char *filename, int flags) } s->fd = blkfront_open(s->dev); + qemu_set_fd_handler(s->fd, vbd_io_completed, NULL, s); QEMU_LIST_INSERT_HEAD(&vbds, s, list); @@ -102,9 +109,6 @@ void qemu_aio_init(void) void qemu_aio_poll(void) { - BDRVVbdState *s; - for (s = vbds.lh_first; s; s = s->list.le_next) - blkfront_aio_poll(s->dev); } /* Wait for all IO requests to complete. */ -- cgit v1.2.3 From ca517cba30bfa45899ecd97135b2a17d07b5ce22 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 14 Feb 2008 09:24:35 +0000 Subject: minios: drop unused xenblk_rxidx function Signed-off-by: Samuel Thibault --- extras/mini-os/blkfront.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/extras/mini-os/blkfront.c b/extras/mini-os/blkfront.c index 1021bb018f..3210396b7b 100644 --- a/extras/mini-os/blkfront.c +++ b/extras/mini-os/blkfront.c @@ -59,11 +59,6 @@ struct blkfront_dev { #endif }; -static inline int xenblk_rxidx(RING_IDX idx) -{ - return idx & (BLK_RING_SIZE - 1); -} - void blkfront_handler(evtchn_port_t port, struct pt_regs *regs, void *data) { #ifdef HAVE_LIBC -- cgit v1.2.3 From 834516f06e5bd47f3259732f3d29496f557567c2 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 14 Feb 2008 09:26:38 +0000 Subject: ioemu: backport upstream's qemu_memalign. Signed-off-by: Samuel Thibault --- tools/ioemu/block-vbd.c | 4 ++-- tools/ioemu/hw/fdc.c | 7 ++++++- tools/ioemu/hw/ide.c | 2 +- tools/ioemu/hw/scsi-disk.c | 2 +- tools/ioemu/osdep.c | 20 ++++++++++++++++++++ tools/ioemu/osdep.h | 1 + 6 files changed, 31 insertions(+), 5 deletions(-) diff --git a/tools/ioemu/block-vbd.c b/tools/ioemu/block-vbd.c index 5561cf1787..937bb5e62d 100644 --- a/tools/ioemu/block-vbd.c +++ b/tools/ioemu/block-vbd.c @@ -227,7 +227,7 @@ static int vbd_read(BlockDriverState *bs, * copying */ if (!((uintptr_t)buf & (SECTOR_SIZE-1))) return vbd_aligned_io(bs, sector_num, buf, nb_sectors, 0); - iobuf = memalign(PAGE_SIZE, nb_sectors * SECTOR_SIZE); + iobuf = qemu_memalign(PAGE_SIZE, nb_sectors * SECTOR_SIZE); ret = vbd_aligned_io(bs, sector_num, iobuf, nb_sectors, 0); memcpy(buf, iobuf, nb_sectors * SECTOR_SIZE); free(iobuf); @@ -246,7 +246,7 @@ static int vbd_write(BlockDriverState *bs, int ret; if (!((uintptr_t)buf & (SECTOR_SIZE-1))) return vbd_aligned_io(bs, sector_num, (uint8_t*) buf, nb_sectors, 1); - iobuf = memalign(PAGE_SIZE, nb_sectors * SECTOR_SIZE); + iobuf = qemu_memalign(PAGE_SIZE, nb_sectors * SECTOR_SIZE); memcpy(iobuf, buf, nb_sectors * SECTOR_SIZE); ret = vbd_aligned_io(bs, sector_num, iobuf, nb_sectors, 1); free(iobuf); diff --git a/tools/ioemu/hw/fdc.c b/tools/ioemu/hw/fdc.c index dc2ea6ebff..5989afd7d0 100644 --- a/tools/ioemu/hw/fdc.c +++ b/tools/ioemu/hw/fdc.c @@ -378,7 +378,7 @@ struct fdctrl_t { uint8_t cur_drv; uint8_t bootsel; /* Command FIFO */ - uint8_t fifo[FD_SECTOR_LEN]; + uint8_t *fifo; uint32_t data_pos; uint32_t data_len; uint8_t data_state; @@ -497,6 +497,11 @@ fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped, fdctrl = qemu_mallocz(sizeof(fdctrl_t)); if (!fdctrl) return NULL; + fdctrl->fifo = qemu_memalign(512, FD_SECTOR_LEN); + if (fdctrl->fifo == NULL) { + qemu_free(fdctrl); + return NULL; + } fdctrl->result_timer = qemu_new_timer(vm_clock, fdctrl_result_timer, fdctrl); diff --git a/tools/ioemu/hw/ide.c b/tools/ioemu/hw/ide.c index cba064bd10..9dd9653aa9 100644 --- a/tools/ioemu/hw/ide.c +++ b/tools/ioemu/hw/ide.c @@ -2306,7 +2306,7 @@ static void ide_init2(IDEState *ide_state, for(i = 0; i < 2; i++) { s = ide_state + i; - s->io_buffer = memalign(getpagesize(), MAX_MULT_SECTORS*512 + 4); + s->io_buffer = qemu_memalign(getpagesize(), MAX_MULT_SECTORS*512 + 4); if (i == 0) s->bs = hd0; else diff --git a/tools/ioemu/hw/scsi-disk.c b/tools/ioemu/hw/scsi-disk.c index d62d4d0d95..acbe75fc98 100644 --- a/tools/ioemu/hw/scsi-disk.c +++ b/tools/ioemu/hw/scsi-disk.c @@ -81,7 +81,7 @@ static SCSIRequest *scsi_new_request(SCSIDevice *s, uint32_t tag) free_requests = r->next; } else { r = qemu_malloc(sizeof(SCSIRequest)); - r->dma_buf = memalign(getpagesize(), SCSI_DMA_BUF_SIZE); + r->dma_buf = qemu_memalign(getpagesize(), SCSI_DMA_BUF_SIZE); } r->dev = s; r->tag = tag; diff --git a/tools/ioemu/osdep.c b/tools/ioemu/osdep.c index d1eff8deb5..5ec16b47da 100644 --- a/tools/ioemu/osdep.c +++ b/tools/ioemu/osdep.c @@ -61,6 +61,10 @@ void *qemu_malloc(size_t size) } #if defined(_WIN32) +void *qemu_memalign(size_t alignment, size_t size) +{ + return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); +} void *qemu_vmalloc(size_t size) { @@ -172,6 +176,22 @@ void kqemu_vfree(void *ptr) #endif +void *qemu_memalign(size_t alignment, size_t size) +{ +#if defined(_POSIX_C_SOURCE) + int ret; + void *ptr; + ret = posix_memalign(&ptr, alignment, size); + if (ret != 0) + return NULL; + return ptr; +#elif defined(_BSD) + return valloc(size); +#else + return memalign(alignment, size); +#endif +} + /* alloc shared memory pages */ void *qemu_vmalloc(size_t size) { diff --git a/tools/ioemu/osdep.h b/tools/ioemu/osdep.h index bd6ffc1713..6df1d87d12 100644 --- a/tools/ioemu/osdep.h +++ b/tools/ioemu/osdep.h @@ -14,6 +14,7 @@ void *qemu_mallocz(size_t size); void qemu_free(void *ptr); char *qemu_strdup(const char *str); +void *qemu_memalign(size_t alignment, size_t size); void *qemu_vmalloc(size_t size); void qemu_vfree(void *ptr); -- cgit v1.2.3 From c3a4bb3762c8a24d0ef137b755b038f207888f70 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 14 Feb 2008 10:31:01 +0000 Subject: ioemu: Stub out direct-Linux-boot support for anything other than x86. Signed-off-by: Kouya Shimura --- tools/ioemu/hw/pc.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/ioemu/hw/pc.c b/tools/ioemu/hw/pc.c index 430d932942..c6ebc6780d 100644 --- a/tools/ioemu/hw/pc.c +++ b/tools/ioemu/hw/pc.c @@ -361,6 +361,7 @@ void bochs_bios_init(void) register_ioport_write(0x503, 1, 1, bochs_bios_write, NULL); } +#if defined(__i386__) || defined(__x86_64__) /* Generate an initial boot sector which sets state and jump to a specified vector */ static void generate_bootsect(uint32_t gpr[8], uint16_t segs[6], uint16_t ip) @@ -718,6 +719,14 @@ static void load_linux(const char *kernel_filename, generate_bootsect(gpr, seg, 0); } +#else /* __ia64__ */ +static void load_linux(const char *kernel_filename, + const char *initrd_filename, + const char *kernel_cmdline) +{ + /* Direct Linux boot is unsupported. */ +} +#endif static void main_cpu_reset(void *opaque) { -- cgit v1.2.3 From 2895a506ab24f8db83e6fbf96809d6b1162ec67e Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 14 Feb 2008 10:33:12 +0000 Subject: x86 shadow: Reduce scope of shadow lock. emulate_map_dest doesn't require holding lock, since only shadow related operation possibly involved is to remove shadow which is less frequent and can acquire lock inside. Rest are either guest table walk or per-vcpu monitor table manipulation Signed-off-by Kevin Tian --- xen/arch/x86/mm/shadow/multi.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c index 1be74c70d6..8407beacf7 100644 --- a/xen/arch/x86/mm/shadow/multi.c +++ b/xen/arch/x86/mm/shadow/multi.c @@ -4216,15 +4216,12 @@ sh_x86_emulate_write(struct vcpu *v, unsigned long vaddr, void *src, if ( (vaddr & (bytes - 1)) && !is_hvm_vcpu(v) ) return X86EMUL_UNHANDLEABLE; - shadow_lock(v->domain); addr = emulate_map_dest(v, vaddr, bytes, sh_ctxt); if ( emulate_map_dest_failed(addr) ) - { - shadow_unlock(v->domain); return ((addr == MAPPING_EXCEPTION) ? X86EMUL_EXCEPTION : X86EMUL_UNHANDLEABLE); - } + shadow_lock(v->domain); memcpy(addr, src, bytes); emulate_unmap_dest(v, addr, bytes, sh_ctxt); @@ -4246,16 +4243,12 @@ sh_x86_emulate_cmpxchg(struct vcpu *v, unsigned long vaddr, if ( (vaddr & (bytes - 1)) && !is_hvm_vcpu(v) ) return X86EMUL_UNHANDLEABLE; - shadow_lock(v->domain); - addr = emulate_map_dest(v, vaddr, bytes, sh_ctxt); if ( emulate_map_dest_failed(addr) ) - { - shadow_unlock(v->domain); return ((addr == MAPPING_EXCEPTION) ? X86EMUL_EXCEPTION : X86EMUL_UNHANDLEABLE); - } + shadow_lock(v->domain); switch ( bytes ) { case 1: prev = cmpxchg(((u8 *)addr), old, new); break; @@ -4294,18 +4287,15 @@ sh_x86_emulate_cmpxchg8b(struct vcpu *v, unsigned long vaddr, if ( (vaddr & 7) && !is_hvm_vcpu(v) ) return X86EMUL_UNHANDLEABLE; - shadow_lock(v->domain); - addr = emulate_map_dest(v, vaddr, 8, sh_ctxt); if ( emulate_map_dest_failed(addr) ) - { - shadow_unlock(v->domain); return ((addr == MAPPING_EXCEPTION) ? X86EMUL_EXCEPTION : X86EMUL_UNHANDLEABLE); - } old = (((u64) old_hi) << 32) | (u64) old_lo; new = (((u64) new_hi) << 32) | (u64) new_lo; + + shadow_lock(v->domain); prev = cmpxchg(((u64 *)addr), old, new); if ( prev != old ) -- cgit v1.2.3 From 280e2b125899cbdf268cf24c582a31068ca81a02 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 14 Feb 2008 10:36:47 +0000 Subject: ioemu: Support the WMVi pseudoencoding in the vnc server. If the client implements it, it is supposed to be able to change colour depth when receiving a WMVi message. Signed-off-by: Stefano Stabellini --- tools/ioemu/vl.c | 9 ----- tools/ioemu/vnc.c | 106 +++++++++++++++++++++++++++++++++--------------------- 2 files changed, 66 insertions(+), 49 deletions(-) diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index 6841f07848..703f1bfd6d 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -154,7 +154,6 @@ static DisplayState display_state; int nographic; int vncviewer; int vncunused; -int vncswitchbpp; const char* keyboard_layout = NULL; int64_t ticks_per_sec; char *boot_device = NULL; @@ -6560,7 +6559,6 @@ void help(void) "-vnc display start a VNC server on display\n" "-vncviewer start a vncviewer process for this domain\n" "-vncunused bind the VNC server to an unused port\n" - "-vnc-switch-bpp VNC server closes connections when the guest OS changes colour depth\n" #ifndef NO_DAEMONIZE "-daemonize daemonize QEMU after initializing\n" #endif @@ -6662,7 +6660,6 @@ enum { QEMU_OPTION_acpi, QEMU_OPTION_vncviewer, QEMU_OPTION_vncunused, - QEMU_OPTION_vncswitchbpp, QEMU_OPTION_pci, }; @@ -6746,7 +6743,6 @@ const QEMUOption qemu_options[] = { { "vnc", HAS_ARG, QEMU_OPTION_vnc }, { "vncviewer", 0, QEMU_OPTION_vncviewer }, { "vncunused", 0, QEMU_OPTION_vncunused }, - { "vnc-switch-bpp", 0, QEMU_OPTION_vncswitchbpp }, /* temporary options */ { "usb", 0, QEMU_OPTION_usb }, @@ -7164,7 +7160,6 @@ int main(int argc, char **argv) nographic = 0; vncviewer = 0; vncunused = 0; - vncswitchbpp = 0; kernel_filename = NULL; kernel_cmdline = ""; #ifndef CONFIG_DM @@ -7595,9 +7590,6 @@ int main(int argc, char **argv) case QEMU_OPTION_vncunused: vncunused++; break; - case QEMU_OPTION_vncswitchbpp: - vncswitchbpp++; - break; case QEMU_OPTION_pci: direct_pci = optarg; break; @@ -7830,7 +7822,6 @@ int main(int argc, char **argv) } else if (vnc_display != NULL || vncunused != 0) { int vnc_display_port; char password[20]; - ds->switchbpp = vncswitchbpp; vnc_display_init(ds); xenstore_read_vncpasswd(domid, password, sizeof(password)); vnc_display_password(ds, password); diff --git a/tools/ioemu/vnc.c b/tools/ioemu/vnc.c index f07ce8ca34..7f87f8ed18 100644 --- a/tools/ioemu/vnc.c +++ b/tools/ioemu/vnc.c @@ -157,6 +157,7 @@ struct VncState int has_resize; int has_hextile; int has_pointer_type_change; + int has_WMVi; int absolute; int last_x; int last_y; @@ -1310,6 +1311,7 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings) vs->has_hextile = 0; vs->has_resize = 0; vs->has_pointer_type_change = 0; + vs->has_WMVi = 0; vs->absolute = -1; vs->ds->dpy_copy = NULL; @@ -1330,6 +1332,8 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings) case -257: vs->has_pointer_type_change = 1; break; + case 0x574D5669: + vs->has_WMVi = 1; default: break; } @@ -1410,6 +1414,57 @@ static void set_pixel_format(VncState *vs, vga_hw_update(); } +static void pixel_format_message (VncState *vs) { + char pad[3] = { 0, 0, 0 }; + + vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */ + if (vs->depth == 4) vnc_write_u8(vs, 24); /* depth */ + else vnc_write_u8(vs, vs->depth * 8); /* depth */ + +#ifdef WORDS_BIGENDIAN + vnc_write_u8(vs, 1); /* big-endian-flag */ +#else + vnc_write_u8(vs, 0); /* big-endian-flag */ +#endif + vnc_write_u8(vs, 1); /* true-color-flag */ + if (vs->depth == 4) { + vnc_write_u16(vs, 0xFF); /* red-max */ + vnc_write_u16(vs, 0xFF); /* green-max */ + vnc_write_u16(vs, 0xFF); /* blue-max */ + vnc_write_u8(vs, 16); /* red-shift */ + vnc_write_u8(vs, 8); /* green-shift */ + vnc_write_u8(vs, 0); /* blue-shift */ + vs->send_hextile_tile = send_hextile_tile_32; + } else if (vs->depth == 2) { + vnc_write_u16(vs, 31); /* red-max */ + vnc_write_u16(vs, 63); /* green-max */ + vnc_write_u16(vs, 31); /* blue-max */ + vnc_write_u8(vs, 11); /* red-shift */ + vnc_write_u8(vs, 5); /* green-shift */ + vnc_write_u8(vs, 0); /* blue-shift */ + vs->send_hextile_tile = send_hextile_tile_16; + } else if (vs->depth == 1) { + /* XXX: change QEMU pixel 8 bit pixel format to match the VNC one ? */ + vnc_write_u16(vs, 7); /* red-max */ + vnc_write_u16(vs, 7); /* green-max */ + vnc_write_u16(vs, 3); /* blue-max */ + vnc_write_u8(vs, 5); /* red-shift */ + vnc_write_u8(vs, 2); /* green-shift */ + vnc_write_u8(vs, 0); /* blue-shift */ + vs->send_hextile_tile = send_hextile_tile_8; + } + vs->red_max = vs->red_max1; + vs->green_max = vs->green_max1; + vs->blue_max = vs->blue_max1; + vs->red_shift = vs->red_shift1; + vs->green_shift = vs->green_shift1; + vs->blue_shift = vs->blue_shift1; + vs->pix_bpp = vs->depth * 8; + vs->write_pixels = vnc_write_pixels_copy; + + vnc_write(vs, pad, 3); /* padding */ +} + static void vnc_dpy_colourdepth(DisplayState *ds, int depth) { int host_big_endian_flag; @@ -1457,6 +1512,14 @@ static void vnc_dpy_colourdepth(DisplayState *ds, int depth) } if (ds->switchbpp) { vnc_client_error(vs); + } else if (vs->csock != -1 && vs->has_WMVi) { + /* Sending a WMVi message to notify the client*/ + vnc_write_u8(vs, 0); /* msg id */ + vnc_write_u8(vs, 0); + vnc_write_u16(vs, 1); /* number of rects */ + vnc_framebuffer_update(vs, 0, 0, ds->width, ds->height, 0x574D5669); + pixel_format_message(vs); + vnc_flush(vs); } else { if (vs->pix_bpp == 4 && vs->depth == 4 && host_big_endian_flag == vs->pix_big_endian && @@ -1578,7 +1641,6 @@ static int protocol_client_msg(VncState *vs, uint8_t *data, size_t len) static int protocol_client_init(VncState *vs, uint8_t *data, size_t len) { size_t l; - char pad[3] = { 0, 0, 0 }; vga_hw_update(); @@ -1587,45 +1649,7 @@ static int protocol_client_init(VncState *vs, uint8_t *data, size_t len) vnc_write_u16(vs, vs->ds->width); vnc_write_u16(vs, vs->ds->height); - vnc_write_u8(vs, vs->depth * 8); /* bits-per-pixel */ - if (vs->depth == 4) vnc_write_u8(vs, 24); /* depth */ - else vnc_write_u8(vs, vs->depth * 8); /* depth */ - -#ifdef WORDS_BIGENDIAN - vnc_write_u8(vs, 1); /* big-endian-flag */ -#else - vnc_write_u8(vs, 0); /* big-endian-flag */ -#endif - vnc_write_u8(vs, 1); /* true-color-flag */ - if (vs->depth == 4) { - vnc_write_u16(vs, 0xFF); /* red-max */ - vnc_write_u16(vs, 0xFF); /* green-max */ - vnc_write_u16(vs, 0xFF); /* blue-max */ - vnc_write_u8(vs, 16); /* red-shift */ - vnc_write_u8(vs, 8); /* green-shift */ - vnc_write_u8(vs, 0); /* blue-shift */ - vs->send_hextile_tile = send_hextile_tile_32; - } else if (vs->depth == 2) { - vnc_write_u16(vs, 31); /* red-max */ - vnc_write_u16(vs, 63); /* green-max */ - vnc_write_u16(vs, 31); /* blue-max */ - vnc_write_u8(vs, 11); /* red-shift */ - vnc_write_u8(vs, 5); /* green-shift */ - vnc_write_u8(vs, 0); /* blue-shift */ - vs->send_hextile_tile = send_hextile_tile_16; - } else if (vs->depth == 1) { - /* XXX: change QEMU pixel 8 bit pixel format to match the VNC one ? */ - vnc_write_u16(vs, 7); /* red-max */ - vnc_write_u16(vs, 7); /* green-max */ - vnc_write_u16(vs, 3); /* blue-max */ - vnc_write_u8(vs, 5); /* red-shift */ - vnc_write_u8(vs, 2); /* green-shift */ - vnc_write_u8(vs, 0); /* blue-shift */ - vs->send_hextile_tile = send_hextile_tile_8; - } - vs->write_pixels = vnc_write_pixels_copy; - - vnc_write(vs, pad, 3); /* padding */ + pixel_format_message(vs); l = strlen(domain_name); vnc_write_u32(vs, l); @@ -2436,6 +2460,8 @@ int vnc_display_open(DisplayState *ds, const char *display, int find_unused) options++; if (strncmp(options, "password", 8) == 0) { password = 1; /* Require password auth */ + } else if (strncmp(options, "switchbpp", 9) == 0) { + ds->switchbpp = 1; #if CONFIG_VNC_TLS } else if (strncmp(options, "tls", 3) == 0) { tls = 1; /* Require TLS */ -- cgit v1.2.3 From a43d6abb4b879b46df6682d11f48307d70dfc53e Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 14 Feb 2008 11:14:17 +0000 Subject: x86 iommu: Define vendor-neutral interface for access to IOMMU. Signed-off-by: Wei Wang Signed-off-by: Keir Fraser --- xen/arch/x86/domctl.c | 8 +- xen/arch/x86/hvm/Makefile | 1 + xen/arch/x86/hvm/iommu.c | 135 +++++++++ xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-detect.c | 2 + xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-map.c | 331 ++++++++++++---------- xen/arch/x86/hvm/svm/amd_iommu/pci-amd-iommu.c | 316 ++++++++++++++++----- xen/arch/x86/hvm/svm/intr.c | 41 +++ xen/arch/x86/hvm/vioapic.c | 2 +- xen/arch/x86/hvm/vmx/vtd/intel-iommu.c | 38 +-- xen/arch/x86/hvm/vmx/vtd/io.c | 53 +--- xen/arch/x86/mm/p2m.c | 17 +- xen/include/asm-x86/hvm/iommu.h | 3 + xen/include/asm-x86/hvm/svm/amd-iommu-defs.h | 5 + xen/include/asm-x86/hvm/svm/amd-iommu-proto.h | 18 +- xen/include/asm-x86/hvm/vmx/intel-iommu.h | 8 +- xen/include/asm-x86/iommu.h | 16 +- 16 files changed, 690 insertions(+), 304 deletions(-) create mode 100644 xen/arch/x86/hvm/iommu.c diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index 1460f8e620..abfda3e737 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -530,7 +530,7 @@ long arch_do_domctl( u8 bus, devfn; ret = -EINVAL; - if ( !vtd_enabled ) + if ( !iommu_enabled ) break; bus = (domctl->u.assign_device.machine_bdf >> 16) & 0xff; @@ -553,7 +553,7 @@ long arch_do_domctl( u8 bus, devfn; ret = -EINVAL; - if ( !vtd_enabled ) + if ( !iommu_enabled ) break; if ( unlikely((d = get_domain_by_id(domctl->domain)) == NULL) ) @@ -589,9 +589,9 @@ long arch_do_domctl( if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL ) break; bind = &(domctl->u.bind_pt_irq); - if (vtd_enabled) + if ( iommu_enabled ) ret = pt_irq_create_bind_vtd(d, bind); - if (ret < 0) + if ( ret < 0 ) gdprintk(XENLOG_ERR, "pt_irq_create_bind failed!\n"); rcu_unlock_domain(d); } diff --git a/xen/arch/x86/hvm/Makefile b/xen/arch/x86/hvm/Makefile index bb2e0e42c1..4e6e70e188 100644 --- a/xen/arch/x86/hvm/Makefile +++ b/xen/arch/x86/hvm/Makefile @@ -6,6 +6,7 @@ obj-y += i8254.o obj-y += instrlen.o obj-y += intercept.o obj-y += io.o +obj-y += iommu.o obj-y += irq.o obj-y += mtrr.o obj-y += platform.o diff --git a/xen/arch/x86/hvm/iommu.c b/xen/arch/x86/hvm/iommu.c new file mode 100644 index 0000000000..30c92f42ea --- /dev/null +++ b/xen/arch/x86/hvm/iommu.c @@ -0,0 +1,135 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern struct iommu_ops intel_iommu_ops; +extern struct iommu_ops amd_iommu_ops; + +int iommu_domain_init(struct domain *domain) +{ + struct hvm_iommu *hd = domain_hvm_iommu(domain); + + spin_lock_init(&hd->mapping_lock); + spin_lock_init(&hd->iommu_list_lock); + INIT_LIST_HEAD(&hd->pdev_list); + INIT_LIST_HEAD(&hd->g2m_ioport_list); + + if ( !iommu_enabled ) + return 0; + + switch ( boot_cpu_data.x86_vendor ) + { + case X86_VENDOR_INTEL: + hd->platform_ops = &intel_iommu_ops; + break; + case X86_VENDOR_AMD: + hd->platform_ops = &amd_iommu_ops; + break; + default: + BUG(); + } + + return hd->platform_ops->init(domain); +} + +int assign_device(struct domain *d, u8 bus, u8 devfn) +{ + struct hvm_iommu *hd = domain_hvm_iommu(d); + + if ( !iommu_enabled || !hd->platform_ops) + return 0; + + return hd->platform_ops->assign_device(d, bus, devfn); +} + +void iommu_domain_destroy(struct domain *d) +{ + struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci; + uint32_t i; + struct hvm_iommu *hd = domain_hvm_iommu(d); + struct list_head *ioport_list, *digl_list, *tmp; + struct g2m_ioport *ioport; + struct dev_intx_gsi_link *digl; + + if ( !iommu_enabled || !hd->platform_ops) + return; + + if ( hvm_irq_dpci != NULL ) + { + for ( i = 0; i < NR_IRQS; i++ ) + { + if ( !hvm_irq_dpci->mirq[i].valid ) + continue; + + pirq_guest_unbind(d, i); + kill_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(i)]); + + list_for_each_safe ( digl_list, tmp, + &hvm_irq_dpci->mirq[i].digl_list ) + { + digl = list_entry(digl_list, + struct dev_intx_gsi_link, list); + list_del(&digl->list); + xfree(digl); + } + } + + d->arch.hvm_domain.irq.dpci = NULL; + xfree(hvm_irq_dpci); + } + + if ( hd ) + { + list_for_each_safe ( ioport_list, tmp, &hd->g2m_ioport_list ) + { + ioport = list_entry(ioport_list, struct g2m_ioport, list); + list_del(&ioport->list); + xfree(ioport); + } + } + + return hd->platform_ops->teardown(d); +} + +int iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn) +{ + struct hvm_iommu *hd = domain_hvm_iommu(d); + + if ( !iommu_enabled || !hd->platform_ops) + return 0; + + return hd->platform_ops->map_page(d, gfn, mfn); +} + +int iommu_unmap_page(struct domain *d, unsigned long gfn) +{ + struct hvm_iommu *hd = domain_hvm_iommu(d); + + if ( !iommu_enabled || !hd->platform_ops) + return 0; + + return hd->platform_ops->unmap_page(d, gfn); +} diff --git a/xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-detect.c b/xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-detect.c index 032ac0028d..c94be5f95d 100644 --- a/xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-detect.c +++ b/xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-detect.c @@ -89,12 +89,14 @@ int __init get_iommu_capabilities(u8 bus, u8 dev, u8 func, u8 cap_ptr, u32 cap_header, cap_range; u64 mmio_bar; +#if HACK_BIOS_SETTINGS /* remove it when BIOS available */ write_pci_config(bus, dev, func, cap_ptr + PCI_CAP_MMIO_BAR_HIGH_OFFSET, 0x00000000); write_pci_config(bus, dev, func, cap_ptr + PCI_CAP_MMIO_BAR_LOW_OFFSET, 0x40000001); /* remove it when BIOS available */ +#endif mmio_bar = (u64)read_pci_config(bus, dev, func, cap_ptr + PCI_CAP_MMIO_BAR_HIGH_OFFSET) << 32; diff --git a/xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-map.c b/xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-map.c index cd98ad0c87..7bdd289ca2 100644 --- a/xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-map.c +++ b/xen/arch/x86/hvm/svm/amd_iommu/amd-iommu-map.c @@ -30,22 +30,20 @@ static int queue_iommu_command(struct amd_iommu *iommu, u32 cmd[]) u32 tail, head, *cmd_buffer; int i; - BUG_ON( !iommu || !cmd ); - tail = iommu->cmd_buffer_tail; - if ( ++tail == iommu->cmd_buffer.entries ) { + if ( ++tail == iommu->cmd_buffer.entries ) tail = 0; - } head = get_field_from_reg_u32( - readl(iommu->mmio_base+IOMMU_CMD_BUFFER_HEAD_OFFSET), - IOMMU_CMD_BUFFER_HEAD_MASK, - IOMMU_CMD_BUFFER_HEAD_SHIFT); - if ( head != tail ) { + readl(iommu->mmio_base+IOMMU_CMD_BUFFER_HEAD_OFFSET), + IOMMU_CMD_BUFFER_HEAD_MASK, + IOMMU_CMD_BUFFER_HEAD_SHIFT); + if ( head != tail ) + { cmd_buffer = (u32 *)(iommu->cmd_buffer.buffer + - (iommu->cmd_buffer_tail * IOMMU_CMD_BUFFER_ENTRY_SIZE)); - for ( i = 0; i < IOMMU_CMD_BUFFER_U32_PER_ENTRY; ++i ) { + (iommu->cmd_buffer_tail * + IOMMU_CMD_BUFFER_ENTRY_SIZE)); + for ( i = 0; i < IOMMU_CMD_BUFFER_U32_PER_ENTRY; i++ ) cmd_buffer[i] = cmd[i]; - } iommu->cmd_buffer_tail = tail; return 1; @@ -58,27 +56,25 @@ static void commit_iommu_command_buffer(struct amd_iommu *iommu) { u32 tail; - BUG_ON( !iommu ); - set_field_in_reg_u32(iommu->cmd_buffer_tail, 0, - IOMMU_CMD_BUFFER_TAIL_MASK, - IOMMU_CMD_BUFFER_TAIL_SHIFT, &tail); + IOMMU_CMD_BUFFER_TAIL_MASK, + IOMMU_CMD_BUFFER_TAIL_SHIFT, &tail); writel(tail, iommu->mmio_base+IOMMU_CMD_BUFFER_TAIL_OFFSET); } int send_iommu_command(struct amd_iommu *iommu, u32 cmd[]) { - BUG_ON( !iommu || !cmd ); - - if ( queue_iommu_command(iommu, cmd) ) { + if ( queue_iommu_command(iommu, cmd) ) + { commit_iommu_command_buffer(iommu); return 1; } + return 0; } static void invalidate_iommu_page(struct amd_iommu *iommu, - u64 io_addr, u16 domain_id) + u64 io_addr, u16 domain_id) { u64 addr_lo, addr_hi; u32 cmd[4], entry; @@ -87,51 +83,52 @@ static void invalidate_iommu_page(struct amd_iommu *iommu, addr_hi = io_addr >> 32; set_field_in_reg_u32(domain_id, 0, - IOMMU_INV_IOMMU_PAGES_DOMAIN_ID_MASK, - IOMMU_INV_IOMMU_PAGES_DOMAIN_ID_SHIFT, &entry); + IOMMU_INV_IOMMU_PAGES_DOMAIN_ID_MASK, + IOMMU_INV_IOMMU_PAGES_DOMAIN_ID_SHIFT, &entry); set_field_in_reg_u32(IOMMU_CMD_INVALIDATE_IOMMU_PAGES, entry, - IOMMU_CMD_OPCODE_MASK, IOMMU_CMD_OPCODE_SHIFT, &entry); + IOMMU_CMD_OPCODE_MASK, IOMMU_CMD_OPCODE_SHIFT, + &entry); cmd[1] = entry; set_field_in_reg_u32(IOMMU_CONTROL_DISABLED, 0, - IOMMU_INV_IOMMU_PAGES_S_FLAG_MASK, - IOMMU_INV_IOMMU_PAGES_S_FLAG_SHIFT, &entry); + IOMMU_INV_IOMMU_PAGES_S_FLAG_MASK, + IOMMU_INV_IOMMU_PAGES_S_FLAG_SHIFT, &entry); set_field_in_reg_u32(IOMMU_CONTROL_DISABLED, entry, - IOMMU_INV_IOMMU_PAGES_PDE_FLAG_MASK, - IOMMU_INV_IOMMU_PAGES_PDE_FLAG_SHIFT, &entry); + IOMMU_INV_IOMMU_PAGES_PDE_FLAG_MASK, + IOMMU_INV_IOMMU_PAGES_PDE_FLAG_SHIFT, &entry); set_field_in_reg_u32((u32)addr_lo >> PAGE_SHIFT, entry, - IOMMU_INV_IOMMU_PAGES_ADDR_LOW_MASK, - IOMMU_INV_IOMMU_PAGES_ADDR_LOW_SHIFT, &entry); + IOMMU_INV_IOMMU_PAGES_ADDR_LOW_MASK, + IOMMU_INV_IOMMU_PAGES_ADDR_LOW_SHIFT, &entry); cmd[2] = entry; set_field_in_reg_u32((u32)addr_hi, 0, - IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_MASK, - IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_SHIFT, &entry); + IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_MASK, + IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_SHIFT, &entry); cmd[3] = entry; cmd[0] = 0; send_iommu_command(iommu, cmd); } -static void flush_command_buffer(struct amd_iommu *iommu) +void flush_command_buffer(struct amd_iommu *iommu) { u32 cmd[4], status; int loop_count, comp_wait; /* clear 'ComWaitInt' in status register (WIC) */ set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, 0, - IOMMU_STATUS_COMP_WAIT_INT_MASK, - IOMMU_STATUS_COMP_WAIT_INT_SHIFT, &status); + IOMMU_STATUS_COMP_WAIT_INT_MASK, + IOMMU_STATUS_COMP_WAIT_INT_SHIFT, &status); writel(status, iommu->mmio_base + IOMMU_STATUS_MMIO_OFFSET); /* send an empty COMPLETION_WAIT command to flush command buffer */ cmd[3] = cmd[2] = 0; set_field_in_reg_u32(IOMMU_CMD_COMPLETION_WAIT, 0, - IOMMU_CMD_OPCODE_MASK, - IOMMU_CMD_OPCODE_SHIFT, &cmd[1]); + IOMMU_CMD_OPCODE_MASK, + IOMMU_CMD_OPCODE_SHIFT, &cmd[1]); set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, 0, - IOMMU_COMP_WAIT_I_FLAG_MASK, - IOMMU_COMP_WAIT_I_FLAG_SHIFT, &cmd[0]); + IOMMU_COMP_WAIT_I_FLAG_MASK, + IOMMU_COMP_WAIT_I_FLAG_SHIFT, &cmd[0]); send_iommu_command(iommu, cmd); /* wait for 'ComWaitInt' to signal comp#endifletion? */ @@ -139,34 +136,36 @@ static void flush_command_buffer(struct amd_iommu *iommu) loop_count = amd_iommu_poll_comp_wait; do { status = readl(iommu->mmio_base + - IOMMU_STATUS_MMIO_OFFSET); - comp_wait = get_field_from_reg_u32(status, - IOMMU_STATUS_COMP_WAIT_INT_MASK, - IOMMU_STATUS_COMP_WAIT_INT_SHIFT); + IOMMU_STATUS_MMIO_OFFSET); + comp_wait = get_field_from_reg_u32( + status, + IOMMU_STATUS_COMP_WAIT_INT_MASK, + IOMMU_STATUS_COMP_WAIT_INT_SHIFT); --loop_count; } while ( loop_count && !comp_wait ); - if ( comp_wait ) { + if ( comp_wait ) + { /* clear 'ComWaitInt' in status register (WIC) */ status &= IOMMU_STATUS_COMP_WAIT_INT_MASK; writel(status, iommu->mmio_base + - IOMMU_STATUS_MMIO_OFFSET); - } else - dprintk(XENLOG_WARNING, "AMD IOMMU: %s(): Warning:" - " ComWaitInt bit did not assert!\n", - __FUNCTION__); + IOMMU_STATUS_MMIO_OFFSET); + } + else + dprintk(XENLOG_WARNING, "AMD IOMMU: Warning:" + " ComWaitInt bit did not assert!\n"); } } static void clear_page_table_entry_present(u32 *pte) { set_field_in_reg_u32(IOMMU_CONTROL_DISABLED, pte[0], - IOMMU_PTE_PRESENT_MASK, - IOMMU_PTE_PRESENT_SHIFT, &pte[0]); + IOMMU_PTE_PRESENT_MASK, + IOMMU_PTE_PRESENT_SHIFT, &pte[0]); } static void set_page_table_entry_present(u32 *pte, u64 page_addr, - int iw, int ir) + int iw, int ir) { u64 addr_lo, addr_hi; u32 entry; @@ -175,33 +174,33 @@ static void set_page_table_entry_present(u32 *pte, u64 page_addr, addr_hi = page_addr >> 32; set_field_in_reg_u32((u32)addr_hi, 0, - IOMMU_PTE_ADDR_HIGH_MASK, - IOMMU_PTE_ADDR_HIGH_SHIFT, &entry); + IOMMU_PTE_ADDR_HIGH_MASK, + IOMMU_PTE_ADDR_HIGH_SHIFT, &entry); set_field_in_reg_u32(iw ? IOMMU_CONTROL_ENABLED : - IOMMU_CONTROL_DISABLED, entry, - IOMMU_PTE_IO_WRITE_PERMISSION_MASK, - IOMMU_PTE_IO_WRITE_PERMISSION_SHIFT, &entry); + IOMMU_CONTROL_DISABLED, entry, + IOMMU_PTE_IO_WRITE_PERMISSION_MASK, + IOMMU_PTE_IO_WRITE_PERMISSION_SHIFT, &entry); set_field_in_reg_u32(ir ? IOMMU_CONTROL_ENABLED : - IOMMU_CONTROL_DISABLED, entry, - IOMMU_PTE_IO_READ_PERMISSION_MASK, - IOMMU_PTE_IO_READ_PERMISSION_SHIFT, &entry); + IOMMU_CONTROL_DISABLED, entry, + IOMMU_PTE_IO_READ_PERMISSION_MASK, + IOMMU_PTE_IO_READ_PERMISSION_SHIFT, &entry); pte[1] = entry; set_field_in_reg_u32((u32)addr_lo >> PAGE_SHIFT, 0, - IOMMU_PTE_ADDR_LOW_MASK, - IOMMU_PTE_ADDR_LOW_SHIFT, &entry); + IOMMU_PTE_ADDR_LOW_MASK, + IOMMU_PTE_ADDR_LOW_SHIFT, &entry); set_field_in_reg_u32(IOMMU_PAGING_MODE_LEVEL_0, entry, - IOMMU_PTE_NEXT_LEVEL_MASK, - IOMMU_PTE_NEXT_LEVEL_SHIFT, &entry); + IOMMU_PTE_NEXT_LEVEL_MASK, + IOMMU_PTE_NEXT_LEVEL_SHIFT, &entry); set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry, - IOMMU_PTE_PRESENT_MASK, - IOMMU_PTE_PRESENT_SHIFT, &entry); + IOMMU_PTE_PRESENT_MASK, + IOMMU_PTE_PRESENT_SHIFT, &entry); pte[0] = entry; } static void amd_iommu_set_page_directory_entry(u32 *pde, - u64 next_ptr, u8 next_level) + u64 next_ptr, u8 next_level) { u64 addr_lo, addr_hi; u32 entry; @@ -211,29 +210,31 @@ static void amd_iommu_set_page_directory_entry(u32 *pde, /* enable read/write permissions,which will be enforced at the PTE */ set_field_in_reg_u32((u32)addr_hi, 0, - IOMMU_PDE_ADDR_HIGH_MASK, IOMMU_PDE_ADDR_HIGH_SHIFT, &entry); + IOMMU_PDE_ADDR_HIGH_MASK, + IOMMU_PDE_ADDR_HIGH_SHIFT, &entry); set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry, - IOMMU_PDE_IO_WRITE_PERMISSION_MASK, - IOMMU_PDE_IO_WRITE_PERMISSION_SHIFT, &entry); + IOMMU_PDE_IO_WRITE_PERMISSION_MASK, + IOMMU_PDE_IO_WRITE_PERMISSION_SHIFT, &entry); set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry, - IOMMU_PDE_IO_READ_PERMISSION_MASK, - IOMMU_PDE_IO_READ_PERMISSION_SHIFT, &entry); + IOMMU_PDE_IO_READ_PERMISSION_MASK, + IOMMU_PDE_IO_READ_PERMISSION_SHIFT, &entry); pde[1] = entry; /* mark next level as 'present' */ set_field_in_reg_u32((u32)addr_lo >> PAGE_SHIFT, 0, - IOMMU_PDE_ADDR_LOW_MASK, IOMMU_PDE_ADDR_LOW_SHIFT, &entry); + IOMMU_PDE_ADDR_LOW_MASK, + IOMMU_PDE_ADDR_LOW_SHIFT, &entry); set_field_in_reg_u32(next_level, entry, - IOMMU_PDE_NEXT_LEVEL_MASK, - IOMMU_PDE_NEXT_LEVEL_SHIFT, &entry); + IOMMU_PDE_NEXT_LEVEL_MASK, + IOMMU_PDE_NEXT_LEVEL_SHIFT, &entry); set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry, - IOMMU_PDE_PRESENT_MASK, - IOMMU_PDE_PRESENT_SHIFT, &entry); + IOMMU_PDE_PRESENT_MASK, + IOMMU_PDE_PRESENT_SHIFT, &entry); pde[0] = entry; } void amd_iommu_set_dev_table_entry(u32 *dte, u64 root_ptr, u16 domain_id, - u8 paging_mode) + u8 paging_mode) { u64 addr_hi, addr_lo; u32 entry; @@ -241,54 +242,56 @@ void amd_iommu_set_dev_table_entry(u32 *dte, u64 root_ptr, u16 domain_id, dte[6] = dte[5] = dte[4] = 0; set_field_in_reg_u32(IOMMU_DEV_TABLE_SYS_MGT_MSG_FORWARDED, 0, - IOMMU_DEV_TABLE_SYS_MGT_MSG_ENABLE_MASK, - IOMMU_DEV_TABLE_SYS_MGT_MSG_ENABLE_SHIFT, &entry); + IOMMU_DEV_TABLE_SYS_MGT_MSG_ENABLE_MASK, + IOMMU_DEV_TABLE_SYS_MGT_MSG_ENABLE_SHIFT, &entry); dte[3] = entry; set_field_in_reg_u32(domain_id, 0, - IOMMU_DEV_TABLE_DOMAIN_ID_MASK, - IOMMU_DEV_TABLE_DOMAIN_ID_SHIFT, &entry); + IOMMU_DEV_TABLE_DOMAIN_ID_MASK, + IOMMU_DEV_TABLE_DOMAIN_ID_SHIFT, &entry); dte[2] = entry; addr_lo = root_ptr & DMA_32BIT_MASK; addr_hi = root_ptr >> 32; set_field_in_reg_u32((u32)addr_hi, 0, - IOMMU_DEV_TABLE_PAGE_TABLE_PTR_HIGH_MASK, - IOMMU_DEV_TABLE_PAGE_TABLE_PTR_HIGH_SHIFT, &entry); + IOMMU_DEV_TABLE_PAGE_TABLE_PTR_HIGH_MASK, + IOMMU_DEV_TABLE_PAGE_TABLE_PTR_HIGH_SHIFT, &entry); set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry, - IOMMU_DEV_TABLE_IO_WRITE_PERMISSION_MASK, - IOMMU_DEV_TABLE_IO_WRITE_PERMISSION_SHIFT, &entry); + IOMMU_DEV_TABLE_IO_WRITE_PERMISSION_MASK, + IOMMU_DEV_TABLE_IO_WRITE_PERMISSION_SHIFT, &entry); set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry, - IOMMU_DEV_TABLE_IO_READ_PERMISSION_MASK, - IOMMU_DEV_TABLE_IO_READ_PERMISSION_SHIFT, &entry); + IOMMU_DEV_TABLE_IO_READ_PERMISSION_MASK, + IOMMU_DEV_TABLE_IO_READ_PERMISSION_SHIFT, &entry); dte[1] = entry; set_field_in_reg_u32((u32)addr_lo >> PAGE_SHIFT, 0, - IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_MASK, - IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_SHIFT, &entry); + IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_MASK, + IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_SHIFT, &entry); set_field_in_reg_u32(paging_mode, entry, - IOMMU_DEV_TABLE_PAGING_MODE_MASK, - IOMMU_DEV_TABLE_PAGING_MODE_SHIFT, &entry); + IOMMU_DEV_TABLE_PAGING_MODE_MASK, + IOMMU_DEV_TABLE_PAGING_MODE_SHIFT, &entry); set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry, - IOMMU_DEV_TABLE_TRANSLATION_VALID_MASK, - IOMMU_DEV_TABLE_TRANSLATION_VALID_SHIFT, &entry); + IOMMU_DEV_TABLE_TRANSLATION_VALID_MASK, + IOMMU_DEV_TABLE_TRANSLATION_VALID_SHIFT, &entry); set_field_in_reg_u32(IOMMU_CONTROL_ENABLED, entry, - IOMMU_DEV_TABLE_VALID_MASK, - IOMMU_DEV_TABLE_VALID_SHIFT, &entry); + IOMMU_DEV_TABLE_VALID_MASK, + IOMMU_DEV_TABLE_VALID_SHIFT, &entry); dte[0] = entry; } -static void *amd_iommu_get_vptr_from_page_table_entry(u32 *entry) +void *amd_iommu_get_vptr_from_page_table_entry(u32 *entry) { u64 addr_lo, addr_hi, ptr; - addr_lo = get_field_from_reg_u32(entry[0], - IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_MASK, - IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_SHIFT); + addr_lo = get_field_from_reg_u32( + entry[0], + IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_MASK, + IOMMU_DEV_TABLE_PAGE_TABLE_PTR_LOW_SHIFT); - addr_hi = get_field_from_reg_u32(entry[1], - IOMMU_DEV_TABLE_PAGE_TABLE_PTR_HIGH_MASK, - IOMMU_DEV_TABLE_PAGE_TABLE_PTR_HIGH_SHIFT); + addr_hi = get_field_from_reg_u32( + entry[1], + IOMMU_DEV_TABLE_PAGE_TABLE_PTR_HIGH_MASK, + IOMMU_DEV_TABLE_PAGE_TABLE_PTR_HIGH_SHIFT); ptr = (addr_hi << 32) | (addr_lo << PAGE_SHIFT); return ptr ? maddr_to_virt((unsigned long)ptr) : NULL; @@ -297,42 +300,74 @@ static void *amd_iommu_get_vptr_from_page_table_entry(u32 *entry) static int amd_iommu_is_pte_present(u32 *entry) { return (get_field_from_reg_u32(entry[0], - IOMMU_PDE_PRESENT_MASK, - IOMMU_PDE_PRESENT_SHIFT)); + IOMMU_PDE_PRESENT_MASK, + IOMMU_PDE_PRESENT_SHIFT)); +} + +void invalidate_dev_table_entry(struct amd_iommu *iommu, + u16 device_id) +{ + u32 cmd[4], entry; + + cmd[3] = cmd[2] = 0; + set_field_in_reg_u32(device_id, 0, + IOMMU_INV_DEVTAB_ENTRY_DEVICE_ID_MASK, + IOMMU_INV_DEVTAB_ENTRY_DEVICE_ID_SHIFT, &entry); + cmd[0] = entry; + + set_field_in_reg_u32(IOMMU_CMD_INVALIDATE_DEVTAB_ENTRY, 0, + IOMMU_CMD_OPCODE_MASK, IOMMU_CMD_OPCODE_SHIFT, + &entry); + cmd[1] = entry; + + send_iommu_command(iommu, cmd); +} + +int amd_iommu_is_dte_page_translation_valid(u32 *entry) +{ + return (get_field_from_reg_u32(entry[0], + IOMMU_DEV_TABLE_VALID_MASK, + IOMMU_DEV_TABLE_VALID_SHIFT) && + get_field_from_reg_u32(entry[0], + IOMMU_DEV_TABLE_TRANSLATION_VALID_MASK, + IOMMU_DEV_TABLE_TRANSLATION_VALID_SHIFT)); } static void *get_pte_from_page_tables(void *table, int level, - unsigned long io_pfn) + unsigned long io_pfn) { unsigned long offset; - void *pde = 0; + void *pde = NULL; - BUG_ON( !table ); + BUG_ON(table == NULL); while ( level > 0 ) { - void *next_table = 0; - unsigned long next_ptr; offset = io_pfn >> ((PTE_PER_TABLE_SHIFT * - (level - IOMMU_PAGING_MODE_LEVEL_1))); + (level - IOMMU_PAGING_MODE_LEVEL_1))); offset &= ~PTE_PER_TABLE_MASK; pde = table + (offset * IOMMU_PAGE_TABLE_ENTRY_SIZE); if ( level == 1 ) break; if ( !pde ) - return NULL; - if ( !amd_iommu_is_pte_present(pde) ) { - next_table = alloc_xenheap_page(); + return NULL; + if ( !amd_iommu_is_pte_present(pde) ) + { + void *next_table = alloc_xenheap_page(); if ( next_table == NULL ) return NULL; memset(next_table, 0, PAGE_SIZE); - if ( *(u64*)(pde) == 0 ) { - next_ptr = (u64)virt_to_maddr(next_table); - amd_iommu_set_page_directory_entry((u32 *)pde, - next_ptr, level - 1); - } else + if ( *(u64 *)pde == 0 ) + { + unsigned long next_ptr = (u64)virt_to_maddr(next_table); + amd_iommu_set_page_directory_entry( + (u32 *)pde, next_ptr, level - 1); + } + else + { free_xenheap_page(next_table); + } } table = amd_iommu_get_vptr_from_page_table_entry(pde); level--; @@ -341,8 +376,7 @@ static void *get_pte_from_page_tables(void *table, int level, return pde; } -int amd_iommu_map_page(struct domain *d, unsigned long gfn, - unsigned long mfn) +int amd_iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn) { void *pte; unsigned long flags; @@ -352,7 +386,7 @@ int amd_iommu_map_page(struct domain *d, unsigned long gfn, BUG_ON( !hd->root_table ); - maddr = (u64)(mfn << PAGE_SHIFT); + maddr = (u64)mfn << PAGE_SHIFT; iw = IOMMU_IO_WRITE_ENABLED; ir = IOMMU_IO_READ_ENABLED; @@ -360,18 +394,18 @@ int amd_iommu_map_page(struct domain *d, unsigned long gfn, spin_lock_irqsave(&hd->mapping_lock, flags); pte = get_pte_from_page_tables(hd->root_table, hd->paging_mode, gfn); - - if ( pte != 0 ) { - set_page_table_entry_present((u32 *)pte, maddr, iw, ir); - spin_unlock_irqrestore(&hd->mapping_lock, flags); - return 0; - } else { + if ( pte == 0 ) + { dprintk(XENLOG_ERR, - "%s() AMD IOMMU: Invalid IO pagetable entry gfn = %lx\n", - __FUNCTION__, gfn); + "AMD IOMMU: Invalid IO pagetable entry gfn = %lx\n", gfn); spin_unlock_irqrestore(&hd->mapping_lock, flags); return -EIO; } + + set_page_table_entry_present((u32 *)pte, maddr, iw, ir); + + spin_unlock_irqrestore(&hd->mapping_lock, flags); + return 0; } int amd_iommu_unmap_page(struct domain *d, unsigned long gfn) @@ -386,34 +420,31 @@ int amd_iommu_unmap_page(struct domain *d, unsigned long gfn) BUG_ON( !hd->root_table ); requestor_id = hd->domain_id; - io_addr = (u64)(gfn << PAGE_SHIFT); + io_addr = (u64)gfn << PAGE_SHIFT; spin_lock_irqsave(&hd->mapping_lock, flags); pte = get_pte_from_page_tables(hd->root_table, hd->paging_mode, gfn); - - if ( pte != 0 ) { - /* mark PTE as 'page not present' */ - clear_page_table_entry_present((u32 *)pte); - spin_unlock_irqrestore(&hd->mapping_lock, flags); - - /* send INVALIDATE_IOMMU_PAGES command */ - for_each_amd_iommu(iommu) { - - spin_lock_irqsave(&iommu->lock, flags); - - invalidate_iommu_page(iommu, io_addr, requestor_id); - flush_command_buffer(iommu); - - spin_unlock_irqrestore(&iommu->lock, flags); - } - - return 0; - } else { + if ( pte == 0 ) + { dprintk(XENLOG_ERR, - "%s() AMD IOMMU: Invalid IO pagetable entry gfn = %lx\n", - __FUNCTION__, gfn); + "AMD IOMMU: Invalid IO pagetable entry gfn = %lx\n", gfn); spin_unlock_irqrestore(&hd->mapping_lock, flags); return -EIO; } + + /* mark PTE as 'page not present' */ + clear_page_table_entry_present((u32 *)pte); + spin_unlock_irqrestore(&hd->mapping_lock, flags); + + /* send INVALIDATE_IOMMU_PAGES command */ + for_each_amd_iommu(iommu) + { + spin_lock_irqsave(&iommu->lock, flags); + invalidate_iommu_page(iommu, io_addr, requestor_id); + flush_command_buffer(iommu); + spin_unlock_irqrestore(&iommu->lock, flags); + } + + return 0; } diff --git a/xen/arch/x86/hvm/svm/amd_iommu/pci-amd-iommu.c b/xen/arch/x86/hvm/svm/amd_iommu/pci-amd-iommu.c index 8b99a78257..7caa276f73 100644 --- a/xen/arch/x86/hvm/svm/amd_iommu/pci-amd-iommu.c +++ b/xen/arch/x86/hvm/svm/amd_iommu/pci-amd-iommu.c @@ -51,19 +51,17 @@ static void __init init_cleanup(void) { struct amd_iommu *iommu; - dprintk(XENLOG_ERR, "AMD IOMMU: %s()\n", __FUNCTION__); - - for_each_amd_iommu(iommu) { + for_each_amd_iommu ( iommu ) unmap_iommu_mmio_region(iommu); - } } static void __init deallocate_iommu_table_struct( - struct table_struct *table) + struct table_struct *table) { - if (table->buffer) { + if ( table->buffer ) + { free_xenheap_pages(table->buffer, - get_order_from_bytes(table->alloc_size)); + get_order_from_bytes(table->alloc_size)); table->buffer = NULL; } } @@ -76,11 +74,10 @@ static void __init deallocate_iommu_resources(struct amd_iommu *iommu) static void __init detect_cleanup(void) { - struct amd_iommu *iommu; + struct amd_iommu *iommu, *next; - dprintk(XENLOG_ERR, "AMD IOMMU: %s()\n", __FUNCTION__); - - for_each_amd_iommu(iommu) { + list_for_each_entry_safe ( iommu, next, &amd_iommu_head, list ) + { list_del(&iommu->list); deallocate_iommu_resources(iommu); xfree(iommu); @@ -91,19 +88,21 @@ static int requestor_id_from_bdf(int bdf) { /* HACK - HACK */ /* account for possible 'aliasing' by parent device */ - return bdf; + return bdf; } static int __init allocate_iommu_table_struct(struct table_struct *table, - const char *name) + const char *name) { table->buffer = (void *) alloc_xenheap_pages( get_order_from_bytes(table->alloc_size)); - if ( !table->buffer ) { + if ( !table->buffer ) + { dprintk(XENLOG_ERR, "AMD IOMMU: Error allocating %s\n", name); return -ENOMEM; } + memset(table->buffer, 0, table->alloc_size); return 0; @@ -114,32 +113,32 @@ static int __init allocate_iommu_resources(struct amd_iommu *iommu) /* allocate 'device table' on a 4K boundary */ iommu->dev_table.alloc_size = PAGE_ALIGN(((iommu->last_downstream_bus + 1) * - IOMMU_DEV_TABLE_ENTRIES_PER_BUS) * - IOMMU_DEV_TABLE_ENTRY_SIZE); + IOMMU_DEV_TABLE_ENTRIES_PER_BUS) * + IOMMU_DEV_TABLE_ENTRY_SIZE); iommu->dev_table.entries = iommu->dev_table.alloc_size / IOMMU_DEV_TABLE_ENTRY_SIZE; - if (allocate_iommu_table_struct(&iommu->dev_table, - "Device Table") != 0) + if ( allocate_iommu_table_struct(&iommu->dev_table, + "Device Table") != 0 ) goto error_out; /* allocate 'command buffer' in power of 2 increments of 4K */ iommu->cmd_buffer_tail = 0; iommu->cmd_buffer.alloc_size = PAGE_SIZE << get_order_from_bytes( - PAGE_ALIGN(amd_iommu_cmd_buffer_entries * - IOMMU_CMD_BUFFER_ENTRY_SIZE)); + PAGE_ALIGN(amd_iommu_cmd_buffer_entries * + IOMMU_CMD_BUFFER_ENTRY_SIZE)); - iommu->cmd_buffer.entries = + iommu->cmd_buffer.entries = iommu->cmd_buffer.alloc_size / IOMMU_CMD_BUFFER_ENTRY_SIZE; if ( allocate_iommu_table_struct(&iommu->cmd_buffer, - "Command Buffer") != 0 ) + "Command Buffer") != 0 ) goto error_out; return 0; -error_out: + error_out: deallocate_iommu_resources(iommu); return -ENOMEM; } @@ -149,7 +148,8 @@ int iommu_detect_callback(u8 bus, u8 dev, u8 func, u8 cap_ptr) struct amd_iommu *iommu; iommu = (struct amd_iommu *) xmalloc(struct amd_iommu); - if ( !iommu ) { + if ( !iommu ) + { dprintk(XENLOG_ERR, "AMD IOMMU: Error allocating amd_iommu\n"); return -ENOMEM; } @@ -170,7 +170,7 @@ int iommu_detect_callback(u8 bus, u8 dev, u8 func, u8 cap_ptr) return 0; -error_out: + error_out: xfree(iommu); return -ENODEV; } @@ -180,11 +180,12 @@ static int __init amd_iommu_init(void) struct amd_iommu *iommu; unsigned long flags; - for_each_amd_iommu(iommu) { + for_each_amd_iommu ( iommu ) + { spin_lock_irqsave(&iommu->lock, flags); /* register IOMMU data strucures in MMIO space */ - if (map_iommu_mmio_region(iommu) != 0) + if ( map_iommu_mmio_region(iommu) != 0 ) goto error_out; register_iommu_dev_table_in_mmio_space(iommu); register_iommu_cmd_buffer_in_mmio_space(iommu); @@ -200,7 +201,7 @@ static int __init amd_iommu_init(void) return 0; -error_out: + error_out: init_cleanup(); return -ENODEV; } @@ -209,13 +210,16 @@ struct amd_iommu *find_iommu_for_device(int bus, int devfn) { struct amd_iommu *iommu; - for_each_amd_iommu(iommu) { - if ( bus == iommu->root_bus ) { - if ( devfn >= iommu->first_devfn && - devfn <= iommu->last_devfn ) + for_each_amd_iommu ( iommu ) + { + if ( bus == iommu->root_bus ) + { + if ( (devfn >= iommu->first_devfn) && + (devfn <= iommu->last_devfn) ) return iommu; } - else if ( bus <= iommu->last_downstream_bus ) { + else if ( bus <= iommu->last_downstream_bus ) + { if ( iommu->downstream_bus_present[bus] ) return iommu; } @@ -238,16 +242,21 @@ void amd_iommu_setup_domain_device( dte = iommu->dev_table.buffer + (requestor_id * IOMMU_DEV_TABLE_ENTRY_SIZE); - spin_lock_irqsave(&iommu->lock, flags); + if ( !amd_iommu_is_dte_page_translation_valid((u32 *)dte) ) + { + spin_lock_irqsave(&iommu->lock, flags); - amd_iommu_set_dev_table_entry((u32 *)dte, - root_ptr, hd->domain_id, hd->paging_mode); + amd_iommu_set_dev_table_entry( + (u32 *)dte, + root_ptr, hd->domain_id, hd->paging_mode); + invalidate_dev_table_entry(iommu, requestor_id); + flush_command_buffer(iommu); + dprintk(XENLOG_INFO, "AMD IOMMU: Set DTE req_id:%x, " + "root_ptr:%"PRIx64", domain_id:%d, paging_mode:%d\n", + requestor_id, root_ptr, hd->domain_id, hd->paging_mode); - dprintk(XENLOG_INFO, "AMD IOMMU: Set DTE req_id:%x, " - "root_ptr:%"PRIx64", domain_id:%d, paging_mode:%d\n", - requestor_id, root_ptr, hd->domain_id, hd->paging_mode); - - spin_unlock_irqrestore(&iommu->lock, flags); + spin_unlock_irqrestore(&iommu->lock, flags); + } } void __init amd_iommu_setup_dom0_devices(void) @@ -259,13 +268,16 @@ void __init amd_iommu_setup_dom0_devices(void) u32 l; int req_id, bdf; - for ( bus = 0; bus < 256; bus++ ) { - for ( dev = 0; dev < 32; dev++ ) { - for ( func = 0; func < 8; func++ ) { + for ( bus = 0; bus < 256; bus++ ) + { + for ( dev = 0; dev < 32; dev++ ) + { + for ( func = 0; func < 8; func++ ) + { l = read_pci_config(bus, dev, func, PCI_VENDOR_ID); /* some broken boards return 0 or ~0 if a slot is empty: */ if ( l == 0xffffffff || l == 0x00000000 || - l == 0x0000ffff || l == 0xffff0000 ) + l == 0x0000ffff || l == 0xffff0000 ) continue; pdev = xmalloc(struct pci_dev); @@ -288,29 +300,33 @@ int amd_iommu_detect(void) { unsigned long i; - if ( !enable_amd_iommu ) { + if ( !enable_amd_iommu ) + { printk("AMD IOMMU: Disabled\n"); return 0; } INIT_LIST_HEAD(&amd_iommu_head); - if ( scan_for_iommu(iommu_detect_callback) != 0 ) { + if ( scan_for_iommu(iommu_detect_callback) != 0 ) + { dprintk(XENLOG_ERR, "AMD IOMMU: Error detection\n"); goto error_out; } - if ( !iommu_found() ) { + if ( !iommu_found() ) + { printk("AMD IOMMU: Not found!\n"); return 0; } - if ( amd_iommu_init() != 0 ) { + if ( amd_iommu_init() != 0 ) + { dprintk(XENLOG_ERR, "AMD IOMMU: Error initialization\n"); goto error_out; } - if ( amd_iommu_domain_init(dom0) != 0 ) + if ( iommu_domain_init(dom0) != 0 ) goto error_out; /* setup 1:1 page table for dom0 */ @@ -320,21 +336,31 @@ int amd_iommu_detect(void) amd_iommu_setup_dom0_devices(); return 0; -error_out: - detect_cleanup(); - return -ENODEV; + error_out: + detect_cleanup(); + return -ENODEV; } static int allocate_domain_resources(struct hvm_iommu *hd) { /* allocate root table */ - hd->root_table = (void *)alloc_xenheap_page(); + unsigned long flags; + + spin_lock_irqsave(&hd->mapping_lock, flags); if ( !hd->root_table ) - return -ENOMEM; - memset((u8*)hd->root_table, 0, PAGE_SIZE); + { + hd->root_table = (void *)alloc_xenheap_page(); + if ( !hd->root_table ) + goto error_out; + memset((u8*)hd->root_table, 0, PAGE_SIZE); + } + spin_unlock_irqrestore(&hd->mapping_lock, flags); return 0; + error_out: + spin_unlock_irqrestore(&hd->mapping_lock, flags); + return -ENOMEM; } static int get_paging_mode(unsigned long entries) @@ -346,7 +372,8 @@ static int get_paging_mode(unsigned long entries) if ( entries > max_page ) entries = max_page; - while ( entries > PTE_PER_TABLE_SIZE ) { + while ( entries > PTE_PER_TABLE_SIZE ) + { entries = PTE_PER_TABLE_ALIGN(entries) >> PTE_PER_TABLE_SHIFT; ++level; if ( level > 6 ) @@ -362,14 +389,11 @@ int amd_iommu_domain_init(struct domain *domain) { struct hvm_iommu *hd = domain_hvm_iommu(domain); - spin_lock_init(&hd->mapping_lock); - spin_lock_init(&hd->iommu_list_lock); - INIT_LIST_HEAD(&hd->pdev_list); - /* allocate page directroy */ - if ( allocate_domain_resources(hd) != 0 ) { - dprintk(XENLOG_ERR, "AMD IOMMU: %s()\n", __FUNCTION__); - goto error_out; + if ( allocate_domain_resources(hd) != 0 ) + { + deallocate_domain_resources(hd); + return -ENOMEM; } if ( is_hvm_domain(domain) ) @@ -380,10 +404,168 @@ int amd_iommu_domain_init(struct domain *domain) hd->domain_id = domain->domain_id; return 0; +} -error_out: - deallocate_domain_resources(hd); - return -ENOMEM; +static void amd_iommu_disable_domain_device( + struct domain *domain, struct amd_iommu *iommu, u16 requestor_id) +{ + void *dte; + unsigned long flags; + + dte = iommu->dev_table.buffer + + (requestor_id * IOMMU_DEV_TABLE_ENTRY_SIZE); + + if ( amd_iommu_is_dte_page_translation_valid((u32 *)dte) ) + { + spin_lock_irqsave(&iommu->lock, flags); + memset (dte, 0, IOMMU_DEV_TABLE_ENTRY_SIZE); + invalidate_dev_table_entry(iommu, requestor_id); + flush_command_buffer(iommu); + dprintk(XENLOG_INFO , "AMD IOMMU: disable DTE 0x%x," + " domain_id:%d, paging_mode:%d\n", + requestor_id, domain_hvm_iommu(domain)->domain_id, + domain_hvm_iommu(domain)->paging_mode); + spin_unlock_irqrestore(&iommu->lock, flags); + } +} + +extern void pdev_flr(u8 bus, u8 devfn); + +static int reassign_device( struct domain *source, struct domain *target, + u8 bus, u8 devfn) +{ + struct hvm_iommu *source_hd = domain_hvm_iommu(source); + struct hvm_iommu *target_hd = domain_hvm_iommu(target); + struct pci_dev *pdev; + struct amd_iommu *iommu; + int req_id, bdf; + unsigned long flags; + + for_each_pdev( source, pdev ) + { + if ( (pdev->bus != bus) || (pdev->devfn != devfn) ) + continue; + + pdev->bus = bus; + pdev->devfn = devfn; + + bdf = (bus << 8) | devfn; + req_id = requestor_id_from_bdf(bdf); + iommu = find_iommu_for_device(bus, devfn); + + if ( iommu ) + { + amd_iommu_disable_domain_device(source, iommu, req_id); + /* Move pci device from the source domain to target domain. */ + spin_lock_irqsave(&source_hd->iommu_list_lock, flags); + spin_lock_irqsave(&target_hd->iommu_list_lock, flags); + list_move(&pdev->list, &target_hd->pdev_list); + spin_unlock_irqrestore(&target_hd->iommu_list_lock, flags); + spin_unlock_irqrestore(&source_hd->iommu_list_lock, flags); + + amd_iommu_setup_domain_device(target, iommu, req_id); + gdprintk(XENLOG_INFO , + "AMD IOMMU: reassign %x:%x.%x domain %d -> domain %d\n", + bus, PCI_SLOT(devfn), PCI_FUNC(devfn), + source->domain_id, target->domain_id); + } + else + { + gdprintk(XENLOG_ERR , "AMD IOMMU: fail to find iommu." + " %x:%x.%x cannot be assigned to domain %d\n", + bus, PCI_SLOT(devfn), PCI_FUNC(devfn), target->domain_id); + return -ENODEV; + } + + break; + } + return 0; +} + +int amd_iommu_assign_device(struct domain *d, u8 bus, u8 devfn) +{ + pdev_flr(bus, devfn); + return reassign_device(dom0, d, bus, devfn); } +static void release_domain_devices(struct domain *d) +{ + struct hvm_iommu *hd = domain_hvm_iommu(d); + struct pci_dev *pdev; + + while ( !list_empty(&hd->pdev_list) ) + { + pdev = list_entry(hd->pdev_list.next, typeof(*pdev), list); + pdev_flr(pdev->bus, pdev->devfn); + gdprintk(XENLOG_INFO , + "AMD IOMMU: release devices %x:%x.%x\n", + pdev->bus, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + reassign_device(d, dom0, pdev->bus, pdev->devfn); + } +} + +static void deallocate_next_page_table(void *table, unsigned long index, + int level) +{ + unsigned long next_index; + void *next_table, *pde; + int next_level; + + pde = table + (index * IOMMU_PAGE_TABLE_ENTRY_SIZE); + next_table = amd_iommu_get_vptr_from_page_table_entry((u32 *)pde); + + if ( next_table ) + { + next_level = level - 1; + if ( next_level > 1 ) + { + next_index = 0; + do + { + deallocate_next_page_table(next_table, + next_index, next_level); + ++next_index; + } while (next_index < PTE_PER_TABLE_SIZE); + } + + free_xenheap_page(next_table); + } +} + +static void deallocate_iommu_page_tables(struct domain *d) +{ + unsigned long index; + struct hvm_iommu *hd = domain_hvm_iommu(d); + + if ( hd ->root_table ) + { + index = 0; + do + { + deallocate_next_page_table(hd->root_table, + index, hd->paging_mode); + ++index; + } while ( index < PTE_PER_TABLE_SIZE ); + + free_xenheap_page(hd ->root_table); + } + + hd ->root_table = NULL; +} + +void amd_iommu_domain_destroy(struct domain *d) +{ + if ( !amd_iommu_enabled ) + return; + + deallocate_iommu_page_tables(d); + release_domain_devices(d); +} +struct iommu_ops amd_iommu_ops = { + .init = amd_iommu_domain_init, + .assign_device = amd_iommu_assign_device, + .teardown = amd_iommu_domain_destroy, + .map_page = amd_iommu_map_page, + .unmap_page = amd_iommu_unmap_page, +}; diff --git a/xen/arch/x86/hvm/svm/intr.c b/xen/arch/x86/hvm/svm/intr.c index d2ba799a42..17a9c3bc7b 100644 --- a/xen/arch/x86/hvm/svm/intr.c +++ b/xen/arch/x86/hvm/svm/intr.c @@ -94,6 +94,46 @@ static void enable_intr_window(struct vcpu *v, struct hvm_intack intack) vmcb->general1_intercepts |= GENERAL1_INTERCEPT_VINTR; } +static void svm_dirq_assist(struct vcpu *v) +{ + unsigned int irq; + uint32_t device, intx; + struct domain *d = v->domain; + struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci; + struct dev_intx_gsi_link *digl; + + if ( !amd_iommu_enabled || (v->vcpu_id != 0) || (hvm_irq_dpci == NULL) ) + return; + + for ( irq = find_first_bit(hvm_irq_dpci->dirq_mask, NR_IRQS); + irq < NR_IRQS; + irq = find_next_bit(hvm_irq_dpci->dirq_mask, NR_IRQS, irq + 1) ) + { + stop_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(irq)]); + clear_bit(irq, &hvm_irq_dpci->dirq_mask); + + list_for_each_entry ( digl, &hvm_irq_dpci->mirq[irq].digl_list, list ) + { + device = digl->device; + intx = digl->intx; + hvm_pci_intx_assert(d, device, intx); + spin_lock(&hvm_irq_dpci->dirq_lock); + hvm_irq_dpci->mirq[irq].pending++; + spin_unlock(&hvm_irq_dpci->dirq_lock); + } + + /* + * Set a timer to see if the guest can finish the interrupt or not. For + * example, the guest OS may unmask the PIC during boot, before the + * guest driver is loaded. hvm_pci_intx_assert() may succeed, but the + * guest will never deal with the irq, then the physical interrupt line + * will never be deasserted. + */ + set_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(irq)], + NOW() + PT_IRQ_TIME_OUT); + } +} + asmlinkage void svm_intr_assist(void) { struct vcpu *v = current; @@ -102,6 +142,7 @@ asmlinkage void svm_intr_assist(void) /* Crank the handle on interrupt state. */ pt_update_irq(v); + svm_dirq_assist(v); do { intack = hvm_vcpu_has_pending_irq(v); diff --git a/xen/arch/x86/hvm/vioapic.c b/xen/arch/x86/hvm/vioapic.c index cfc80c5aa1..c01618c69f 100644 --- a/xen/arch/x86/hvm/vioapic.c +++ b/xen/arch/x86/hvm/vioapic.c @@ -458,7 +458,7 @@ void vioapic_update_EOI(struct domain *d, int vector) ent->fields.remote_irr = 0; - if ( vtd_enabled ) + if ( iommu_enabled ) { spin_unlock(&d->arch.hvm_domain.irq_lock); hvm_dpci_eoi(current->domain, gsi, ent); diff --git a/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c b/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c index eb2c5eef8e..c497b9c392 100644 --- a/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c +++ b/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c @@ -1047,7 +1047,7 @@ static void free_iommu(struct iommu *iommu) agaw = 64; \ agaw; }) -int iommu_domain_init(struct domain *domain) +int intel_iommu_domain_init(struct domain *domain) { struct hvm_iommu *hd = domain_hvm_iommu(domain); struct iommu *iommu = NULL; @@ -1056,11 +1056,6 @@ int iommu_domain_init(struct domain *domain) unsigned long sagaw; struct acpi_drhd_unit *drhd; - spin_lock_init(&hd->mapping_lock); - spin_lock_init(&hd->iommu_list_lock); - INIT_LIST_HEAD(&hd->pdev_list); - INIT_LIST_HEAD(&hd->g2m_ioport_list); - if ( !vtd_enabled || list_empty(&acpi_drhd_units) ) return 0; @@ -1550,7 +1545,8 @@ static int domain_context_mapped(struct pci_dev *pdev) return 0; } -int iommu_map_page(struct domain *d, paddr_t gfn, paddr_t mfn) +int intel_iommu_map_page( + struct domain *d, unsigned long gfn, unsigned long mfn) { struct acpi_drhd_unit *drhd; struct iommu *iommu; @@ -1566,12 +1562,12 @@ int iommu_map_page(struct domain *d, paddr_t gfn, paddr_t mfn) return 0; #endif - pg = addr_to_dma_page(d, gfn << PAGE_SHIFT_4K); + pg = addr_to_dma_page(d, (paddr_t)gfn << PAGE_SHIFT_4K); if ( !pg ) return -ENOMEM; pte = (struct dma_pte *)map_domain_page(page_to_mfn(pg)); pte += gfn & LEVEL_MASK; - dma_set_pte_addr(*pte, mfn << PAGE_SHIFT_4K); + dma_set_pte_addr(*pte, (paddr_t)mfn << PAGE_SHIFT_4K); dma_set_pte_prot(*pte, DMA_PTE_READ | DMA_PTE_WRITE); iommu_flush_cache_entry(iommu, pte); unmap_domain_page(pte); @@ -1581,7 +1577,7 @@ int iommu_map_page(struct domain *d, paddr_t gfn, paddr_t mfn) iommu = drhd->iommu; if ( cap_caching_mode(iommu->cap) ) iommu_flush_iotlb_psi(iommu, domain_iommu_domid(d), - gfn << PAGE_SHIFT_4K, 1, 0); + (paddr_t)gfn << PAGE_SHIFT_4K, 1, 0); else if ( cap_rwbf(iommu->cap) ) iommu_flush_write_buffer(iommu); } @@ -1589,7 +1585,7 @@ int iommu_map_page(struct domain *d, paddr_t gfn, paddr_t mfn) return 0; } -int iommu_unmap_page(struct domain *d, dma_addr_t gfn) +int intel_iommu_unmap_page(struct domain *d, unsigned long gfn) { struct acpi_drhd_unit *drhd; struct iommu *iommu; @@ -1603,12 +1599,12 @@ int iommu_unmap_page(struct domain *d, dma_addr_t gfn) return 0; #endif - dma_pte_clear_one(d, gfn << PAGE_SHIFT_4K); + dma_pte_clear_one(d, (paddr_t)gfn << PAGE_SHIFT_4K); return 0; } -int iommu_page_mapping(struct domain *domain, dma_addr_t iova, +int iommu_page_mapping(struct domain *domain, paddr_t iova, void *hpa, size_t size, int prot) { struct acpi_drhd_unit *drhd; @@ -1655,14 +1651,14 @@ int iommu_page_mapping(struct domain *domain, dma_addr_t iova, return 0; } -int iommu_page_unmapping(struct domain *domain, dma_addr_t addr, size_t size) +int iommu_page_unmapping(struct domain *domain, paddr_t addr, size_t size) { dma_pte_clear_range(domain, addr, addr + size); return 0; } -void iommu_flush(struct domain *d, dma_addr_t gfn, u64 *p2m_entry) +void iommu_flush(struct domain *d, unsigned long gfn, u64 *p2m_entry) { struct acpi_drhd_unit *drhd; struct iommu *iommu = NULL; @@ -1673,7 +1669,7 @@ void iommu_flush(struct domain *d, dma_addr_t gfn, u64 *p2m_entry) iommu = drhd->iommu; if ( cap_caching_mode(iommu->cap) ) iommu_flush_iotlb_psi(iommu, domain_iommu_domid(d), - gfn << PAGE_SHIFT_4K, 1, 0); + (paddr_t)gfn << PAGE_SHIFT_4K, 1, 0); else if ( cap_rwbf(iommu->cap) ) iommu_flush_write_buffer(iommu); } @@ -1921,7 +1917,7 @@ int device_assigned(u8 bus, u8 devfn) return 1; } -int assign_device(struct domain *d, u8 bus, u8 devfn) +int intel_iommu_assign_device(struct domain *d, u8 bus, u8 devfn) { struct acpi_rmrr_unit *rmrr; struct pci_dev *pdev; @@ -2151,6 +2147,14 @@ int iommu_resume(void) return 0; } +struct iommu_ops intel_iommu_ops = { + .init = intel_iommu_domain_init, + .assign_device = intel_iommu_assign_device, + .teardown = iommu_domain_teardown, + .map_page = intel_iommu_map_page, + .unmap_page = intel_iommu_unmap_page, +}; + /* * Local variables: * mode: C diff --git a/xen/arch/x86/hvm/vmx/vtd/io.c b/xen/arch/x86/hvm/vmx/vtd/io.c index 39029fab9f..0962757a0e 100644 --- a/xen/arch/x86/hvm/vmx/vtd/io.c +++ b/xen/arch/x86/hvm/vmx/vtd/io.c @@ -141,7 +141,7 @@ int hvm_do_IRQ_dpci(struct domain *d, unsigned int mirq) { struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; - if ( !vtd_enabled || (d == dom0) || (hvm_irq->dpci == NULL) || + if ( !iommu_enabled || (d == dom0) || (hvm_irq->dpci == NULL) || !hvm_irq->dpci->mirq[mirq].valid ) return 0; @@ -167,7 +167,7 @@ static void hvm_dpci_isairq_eoi(struct domain *d, unsigned int isairq) int i; ASSERT(isairq < NR_ISAIRQS); - if ( !vtd_enabled || !dpci || + if ( !iommu_enabled || !dpci || !test_bit(isairq, dpci->isairq_map) ) return; @@ -205,7 +205,7 @@ void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi, struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci; uint32_t device, intx, machine_gsi; - if ( !vtd_enabled || (hvm_irq_dpci == NULL) || + if ( !iommu_enabled || (hvm_irq_dpci == NULL) || (guest_gsi >= NR_ISAIRQS && !hvm_irq_dpci->girq[guest_gsi].valid) ) return; @@ -235,50 +235,3 @@ void hvm_dpci_eoi(struct domain *d, unsigned int guest_gsi, else spin_unlock(&hvm_irq_dpci->dirq_lock); } - -void iommu_domain_destroy(struct domain *d) -{ - struct hvm_irq_dpci *hvm_irq_dpci = d->arch.hvm_domain.irq.dpci; - uint32_t i; - struct hvm_iommu *hd = domain_hvm_iommu(d); - struct list_head *ioport_list, *digl_list, *tmp; - struct g2m_ioport *ioport; - struct dev_intx_gsi_link *digl; - - if ( !vtd_enabled ) - return; - - if ( hvm_irq_dpci != NULL ) - { - for ( i = 0; i < NR_IRQS; i++ ) - if ( hvm_irq_dpci->mirq[i].valid ) - { - pirq_guest_unbind(d, i); - kill_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(i)]); - - list_for_each_safe ( digl_list, tmp, - &hvm_irq_dpci->mirq[i].digl_list ) - { - digl = list_entry(digl_list, - struct dev_intx_gsi_link, list); - list_del(&digl->list); - xfree(digl); - } - } - - d->arch.hvm_domain.irq.dpci = NULL; - xfree(hvm_irq_dpci); - } - - if ( hd ) - { - list_for_each_safe ( ioport_list, tmp, &hd->g2m_ioport_list ) - { - ioport = list_entry(ioport_list, struct g2m_ioport, list); - list_del(&ioport->list); - xfree(ioport); - } - } - - iommu_domain_teardown(d); -} diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c index b82e7ef704..b114de3e80 100644 --- a/xen/arch/x86/mm/p2m.c +++ b/xen/arch/x86/mm/p2m.c @@ -255,8 +255,21 @@ set_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn, p2m_type_t p2mt) /* level 1 entry */ paging_write_p2m_entry(d, gfn, p2m_entry, table_mfn, entry_content, 1); - if ( vtd_enabled && (p2mt == p2m_mmio_direct) && is_hvm_domain(d) ) - iommu_flush(d, gfn, (u64*)p2m_entry); + if ( iommu_enabled && is_hvm_domain(d) ) + { + if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL ) + { + if ( (p2mt == p2m_mmio_direct) ) + iommu_flush(d, gfn, (u64*)p2m_entry); + } + else if ( boot_cpu_data.x86_vendor == X86_VENDOR_AMD ) + { + if ( p2mt == p2m_ram_rw ) + iommu_map_page(d, gfn, mfn_x(mfn)); + else + iommu_unmap_page(d, gfn); + } + } /* Success */ rv = 1; diff --git a/xen/include/asm-x86/hvm/iommu.h b/xen/include/asm-x86/hvm/iommu.h index 210530947f..5ac7aef1c9 100644 --- a/xen/include/asm-x86/hvm/iommu.h +++ b/xen/include/asm-x86/hvm/iommu.h @@ -48,6 +48,9 @@ struct hvm_iommu { int domain_id; int paging_mode; void *root_table; + + /* iommu_ops */ + struct iommu_ops *platform_ops; }; #endif // __ASM_X86_HVM_IOMMU_H__ diff --git a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h index 56089a5317..bece80c5db 100644 --- a/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-defs.h @@ -263,6 +263,10 @@ #define IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_MASK 0xFFFFFFFF #define IOMMU_INV_IOMMU_PAGES_ADDR_HIGH_SHIFT 0 +/* INVALIDATE_DEVTAB_ENTRY command */ +#define IOMMU_INV_DEVTAB_ENTRY_DEVICE_ID_MASK 0x0000FFFF +#define IOMMU_INV_DEVTAB_ENTRY_DEVICE_ID_SHIFT 0 + /* Event Log */ #define IOMMU_EVENT_LOG_BASE_LOW_OFFSET 0x10 #define IOMMU_EVENT_LOG_BASE_HIGH_OFFSET 0x14 @@ -415,5 +419,6 @@ #define IOMMU_PAGE_TABLE_LEVEL_4 4 #define IOMMU_IO_WRITE_ENABLED 1 #define IOMMU_IO_READ_ENABLED 1 +#define HACK_BIOS_SETTINGS 0 #endif /* _ASM_X86_64_AMD_IOMMU_DEFS_H */ diff --git a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h index d9b21a5973..592f908946 100644 --- a/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h +++ b/xen/include/asm-x86/hvm/svm/amd-iommu-proto.h @@ -27,13 +27,15 @@ list_for_each_entry(amd_iommu, \ &amd_iommu_head, list) +#define for_each_pdev(domain, pdev) \ + list_for_each_entry(pdev, \ + &(domain->arch.hvm_domain.hvm_iommu.pdev_list), list) + #define DMA_32BIT_MASK 0x00000000ffffffffULL #define PAGE_ALIGN(addr) (((addr) + PAGE_SIZE - 1) & PAGE_MASK) -#define PAGE_SHIFT_4K (12) -#define PAGE_SIZE_4K (1UL << PAGE_SHIFT_4K) -#define PAGE_MASK_4K (((u64)-1) << PAGE_SHIFT_4K) -typedef int (*iommu_detect_callback_ptr_t)(u8 bus, u8 dev, u8 func, u8 cap_ptr); +typedef int (*iommu_detect_callback_ptr_t)( + u8 bus, u8 dev, u8 func, u8 cap_ptr); /* amd-iommu-detect functions */ int __init scan_for_iommu(iommu_detect_callback_ptr_t iommu_detect_callback); @@ -49,16 +51,20 @@ void __init register_iommu_cmd_buffer_in_mmio_space(struct amd_iommu *iommu); void __init enable_iommu(struct amd_iommu *iommu); /* mapping functions */ -int amd_iommu_map_page(struct domain *d, unsigned long gfn, - unsigned long mfn); +int amd_iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn); int amd_iommu_unmap_page(struct domain *d, unsigned long gfn); +void *amd_iommu_get_vptr_from_page_table_entry(u32 *entry); /* device table functions */ void amd_iommu_set_dev_table_entry(u32 *dte, u64 root_ptr, u16 domain_id, u8 paging_mode); +int amd_iommu_is_dte_page_translation_valid(u32 *entry); +void invalidate_dev_table_entry(struct amd_iommu *iommu, + u16 devic_id); /* send cmd to iommu */ int send_iommu_command(struct amd_iommu *iommu, u32 cmd[]); +void flush_command_buffer(struct amd_iommu *iommu); /* iommu domain funtions */ int amd_iommu_domain_init(struct domain *domain); diff --git a/xen/include/asm-x86/hvm/vmx/intel-iommu.h b/xen/include/asm-x86/hvm/vmx/intel-iommu.h index 0f9c08c50f..07b07c09d3 100644 --- a/xen/include/asm-x86/hvm/vmx/intel-iommu.h +++ b/xen/include/asm-x86/hvm/vmx/intel-iommu.h @@ -422,8 +422,6 @@ struct poll_info { #define VTD_PAGE_TABLE_LEVEL_3 3 #define VTD_PAGE_TABLE_LEVEL_4 4 -typedef paddr_t dma_addr_t; - #define DEFAULT_DOMAIN_ADDRESS_WIDTH 48 #define MAX_IOMMUS 32 #define MAX_IOMMU_REGS 0xc0 @@ -447,8 +445,10 @@ struct ir_ctrl { }; struct iommu_flush { - int (*context)(void *iommu, u16 did, u16 source_id, u8 function_mask, u64 type, int non_present_entry_flush); - int (*iotlb)(void *iommu, u16 did, u64 addr, unsigned int size_order, u64 type, int non_present_entry_flush); + int (*context)(void *iommu, u16 did, u16 source_id, + u8 function_mask, u64 type, int non_present_entry_flush); + int (*iotlb)(void *iommu, u16 did, u64 addr, unsigned int size_order, + u64 type, int non_present_entry_flush); }; struct intel_iommu { diff --git a/xen/include/asm-x86/iommu.h b/xen/include/asm-x86/iommu.h index 1f5e61ee63..6707f94cbe 100644 --- a/xen/include/asm-x86/iommu.h +++ b/xen/include/asm-x86/iommu.h @@ -28,7 +28,9 @@ #include extern int vtd_enabled; +extern int amd_iommu_enabled; +#define iommu_enabled ( amd_iommu_enabled || vtd_enabled ) #define domain_hvm_iommu(d) (&d->arch.hvm_domain.hvm_iommu) #define domain_vmx_iommu(d) (&d->arch.hvm_domain.hvm_iommu.vmx_iommu) #define iommu_qi_ctrl(iommu) (&(iommu->intel.qi_ctrl)); @@ -72,9 +74,9 @@ int iommu_domain_init(struct domain *d); void iommu_domain_destroy(struct domain *d); int device_assigned(u8 bus, u8 devfn); int assign_device(struct domain *d, u8 bus, u8 devfn); -int iommu_map_page(struct domain *d, dma_addr_t gfn, dma_addr_t mfn); -int iommu_unmap_page(struct domain *d, dma_addr_t gfn); -void iommu_flush(struct domain *d, dma_addr_t gfn, u64 *p2m_entry); +int iommu_map_page(struct domain *d, unsigned long gfn, unsigned long mfn); +int iommu_unmap_page(struct domain *d, unsigned long gfn); +void iommu_flush(struct domain *d, unsigned long gfn, u64 *p2m_entry); void iommu_set_pgd(struct domain *d); void iommu_domain_teardown(struct domain *d); int hvm_do_IRQ_dpci(struct domain *d, unsigned int irq); @@ -89,4 +91,12 @@ void io_apic_write_remap_rte(unsigned int apic, #define PT_IRQ_TIME_OUT MILLISECS(8) #define VTDPREFIX "[VT-D]" +struct iommu_ops { + int (*init)(struct domain *d); + int (*assign_device)(struct domain *d, u8 bus, u8 devfn); + void (*teardown)(struct domain *d); + int (*map_page)(struct domain *d, unsigned long gfn, unsigned long mfn); + int (*unmap_page)(struct domain *d, unsigned long gfn); +}; + #endif /* _IOMMU_H_ */ -- cgit v1.2.3 From df5b25e9af9248d8e00d0ef7e4ce3eec9eb44f97 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 14 Feb 2008 11:24:49 +0000 Subject: x86/64: Make BIOS call to declare our intention to enter long mode. Signed-off-by: Keir Fraser --- xen/arch/x86/boot/trampoline.S | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/xen/arch/x86/boot/trampoline.S b/xen/arch/x86/boot/trampoline.S index 2c92dc6a00..143612c91f 100644 --- a/xen/arch/x86/boot/trampoline.S +++ b/xen/arch/x86/boot/trampoline.S @@ -155,6 +155,13 @@ trampoline_boot_cpu_entry: lidt bootsym(rm_idt) sti +#if defined(__x86_64__) + /* Declare that our target operating mode is long mode. */ + movw $0xec00,%ax # declare target operating mode + movw $0x0002,%bx # long mode + int $0x15 +#endif + /* * Do real-mode work: * 1. Get memory map. -- cgit v1.2.3