00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <l4/l4con/l4con.h>
00017 #include <l4/l4con/l4con_ev.h>
00018 #include <l4/l4con/l4con-client.h>
00019 #include <l4/l4con/l4con-server.h>
00020 #include <l4/l4con/stream-client.h>
00021 #include <l4/sys/kdebug.h>
00022 #include <l4/sys/syscalls.h>
00023 #include <l4/sigma0/kip.h>
00024 #include <l4/thread/thread.h>
00025 #include <l4/util/parse_cmd.h>
00026 #include <l4/util/macros.h>
00027 #include <l4/lock/lock.h>
00028 #include <l4/env/errno.h>
00029 #include <l4/log/l4log.h>
00030 #include <l4/names/libnames.h>
00031 #include <l4/dm_mem/dm_mem.h>
00032 #if defined(ARCH_x86) || defined(ARCH_amd64)
00033 #include <l4/util/rdtsc.h>
00034 #endif
00035
00036
00037 #include <stdio.h>
00038 #include <stdlib.h>
00039 #include <string.h>
00040 #include <setjmp.h>
00041
00042
00043 #include "config.h"
00044 #include "ev.h"
00045 #include "events.h"
00046 #include "gmode.h"
00047 #include "l4con.h"
00048 #include "main.h"
00049 #include "vc.h"
00050
00051 char LOG_tag[9] = "con";
00052 l4_ssize_t l4libc_heapsize = CONFIG_MALLOC_MAX_SIZE;
00053
00054 int noaccel;
00055 int nolog;
00056 int pan;
00057 int use_fastmemcpy = 1;
00058 int cpu_load;
00059 int cpu_load_history;
00060 int vbemode;
00061
00062 struct l4con_vc *vc[MAX_NR_L4CONS];
00063 int fg_vc = -1;
00064 int want_vc = 0;
00065
00066
00067
00068
00069 int update_id;
00070 l4lock_t want_vc_lock = L4LOCK_UNLOCKED;
00071 l4_threadid_t ev_partner_l4id = L4_NIL_ID;
00072 l4_threadid_t vc_partner_l4id = L4_NIL_ID;
00073 l4_uint8_t vc_mode = CON_CLOSED;
00074
00075 static void do_switch(int i_new, int i_old);
00076
00077 static void
00078 fast_memcpy(l4_uint8_t *dst, l4_uint8_t *src, l4_size_t size)
00079 {
00080 #if defined(ARCH_x86) || defined(ARCH_amd64)
00081 l4_umword_t dummy;
00082
00083 asm volatile ("cld ; rep movsl"
00084 :"=S"(dummy), "=D"(dummy), "=c"(dummy)
00085 :"S"(src), "D"(dst),"c"(size/sizeof(l4_umword_t)));
00086 #else
00087 memcpy(dst, src, size);
00088 #endif
00089 }
00090
00091
00092
00093 static void
00094 fast_memcpy_mmx2_32(l4_uint8_t *dst, l4_uint8_t *src, l4_size_t size)
00095 {
00096 #if defined(ARCH_x86) || defined(ARCH_amd64)
00097 l4_mword_t dummy;
00098
00099
00100
00101 asm ("emms");
00102
00103 asm volatile ("lea (%%esi,%%edx,8),%%esi \n\t"
00104 "lea (%%edi,%%edx,8),%%edi \n\t"
00105 "neg %%edx \n\t"
00106 ".align 8 \n\t"
00107 "0: \n\t"
00108 "mov $64,%%ecx \n\t"
00109 ".align 16 \n\t"
00110 "# block prefetch 4096 bytes \n\t"
00111 "1: \n\t"
00112 "movl (%%esi,%%edx,8),%%eax \n\t"
00113 "movl 32(%%esi,%%edx,8),%%eax \n\t"
00114 "add $8,%%edx \n\t"
00115 "dec %%ecx \n\t"
00116 "jnz 1b \n\t"
00117 "sub $(32*16),%%edx \n\t"
00118 "mov $128,%%ecx \n\t"
00119 ".align 16 \n\t"
00120 "2: # copy 4096 bytes \n\t"
00121 "movq (%%esi,%%edx,8),%%mm0 \n\t"
00122 "movq 8(%%esi,%%edx,8),%%mm1 \n\t"
00123 "movq 16(%%esi,%%edx,8),%%mm2 \n\t"
00124 "movq 24(%%esi,%%edx,8),%%mm3 \n\t"
00125 "movntq %%mm0,(%%edi,%%edx,8) \n\t"
00126 "movntq %%mm1,8(%%edi,%%edx,8) \n\t"
00127 "movntq %%mm2,16(%%edi,%%edx,8) \n\t"
00128 "movntq %%mm3,24(%%edi,%%edx,8) \n\t"
00129 "add $4,%%edx \n\t"
00130 "dec %%ecx \n\t"
00131 "jnz 2b \n\t"
00132 "or %%edx,%%edx \n\t"
00133 "jnz 0b \n\t"
00134 "sfence \n\t"
00135 "emms \n\t"
00136 : "=d" (dummy)
00137 : "S" (src), "D" (dst), "d" (size/8)
00138 : "eax", "ebx", "ecx", "memory");
00139 #else
00140 memcpy(dst, src, size);
00141 #endif
00142 }
00143
00144
00145 static int
00146 get_free_vc(void)
00147 {
00148 int i;
00149
00150 for (i=0; i < MAX_NR_L4CONS; i++)
00151 {
00152 if (vc[i]->mode == CON_CLOSED)
00153 return i;
00154 }
00155
00156 LOG("Ooops, all vcs occupied");
00157 return -CON_EFREE;
00158 }
00159
00160
00161
00162 static int
00163 redraw_vc(void)
00164 {
00165 int ret = 0;
00166
00167 if (!l4_is_nil_id(ev_partner_l4id))
00168 {
00169 static stream_io_input_event_t ev_struct;
00170 CORBA_Environment env = dice_default_environment;
00171
00172
00173 ev_struct.type = EV_CON;
00174 ev_struct.code = EV_CON_REDRAW;
00175 ev_struct.value = 0;
00176
00177 env.timeout = EVENT_TIMEOUT;
00178 stream_io_push_send(&ev_partner_l4id, &ev_struct, &env);
00179
00180 if (DICE_EXCEPTION_MAJOR(&env) == CORBA_SYSTEM_EXCEPTION &&
00181 DICE_EXCEPTION_MINOR(&env) == CORBA_DICE_EXCEPTION_IPC_ERROR)
00182 {
00183 if (DICE_IPC_ERROR(&env) == L4_IPC_ENOT_EXISTENT)
00184 {
00185 printf("redraw_vc: Target thread "l4util_idfmt" dead?\n",
00186 l4util_idstr(ev_partner_l4id));
00187 ret = -1;
00188 }
00189 else
00190 {
00191 printf("redraw_vc("l4util_idfmt"): IPC error %02x\n",
00192 l4util_idstr(ev_partner_l4id), DICE_IPC_ERROR(&env));
00193 }
00194 }
00195 }
00196
00197 return ret;
00198 }
00199
00200
00201
00202 static int
00203 background_vc(void)
00204 {
00205 static stream_io_input_event_t ev_struct;
00206 CORBA_Environment env = dice_default_environment;
00207
00208 l4lock_lock(&want_vc_lock);
00209 if (!l4_is_nil_id(ev_partner_l4id))
00210 {
00211
00212 ev_struct.type = EV_CON;
00213 ev_struct.code = EV_CON_BACKGROUND;
00214 ev_struct.value = 0;
00215
00216 env.timeout = EVENT_TIMEOUT;
00217 stream_io_push_send(&ev_partner_l4id, &ev_struct, &env);
00218 if (DICE_HAS_EXCEPTION(&env) &&
00219 DICE_EXCEPTION_MAJOR(&env) == CORBA_SYSTEM_EXCEPTION &&
00220 DICE_EXCEPTION_MINOR(&env) == CORBA_DICE_EXCEPTION_IPC_ERROR)
00221 LOG("exception %d.%d sending background event to "l4util_idfmt,
00222 DICE_EXCEPTION_MAJOR(&env), DICE_EXCEPTION_MINOR(&env),
00223 l4util_idstr(ev_partner_l4id));
00224
00225
00226 vc[fg_vc]->fb_mapped = 0;
00227 }
00228 l4lock_unlock(&want_vc_lock);
00229
00230 return 0;
00231 }
00232
00233
00234
00235 void
00236 request_vc(int nr)
00237 {
00238 l4lock_lock(&want_vc_lock);
00239 want_vc = nr;
00240 l4lock_unlock(&want_vc_lock);
00241 }
00242
00243
00244
00245 void
00246 request_vc_delta(int delta)
00247 {
00248 int new_vc;
00249
00250 if (delta == 0)
00251 return;
00252 l4lock_lock(&want_vc_lock);
00253 new_vc = fg_vc + delta;
00254 for (;;)
00255 {
00256 if (new_vc <= 0)
00257 new_vc = MAX_NR_L4CONS-1;
00258 else if (new_vc >= MAX_NR_L4CONS)
00259 new_vc = 1;
00260 if (new_vc == fg_vc || (vc[new_vc]->mode & CON_OUT))
00261 break;
00262 new_vc += delta < 0 ? -1 : +1;
00263 }
00264 want_vc = new_vc;
00265 l4lock_unlock(&want_vc_lock);
00266 }
00267
00268
00269
00270 static void
00271 switch_vc(void)
00272 {
00273 int i;
00274
00275 retry:
00276 if ((want_vc > 0) && (want_vc & 0x1000))
00277 {
00278
00279 CORBA_Environment env = dice_default_environment;
00280 l4lock_unlock(&want_vc_lock);
00281 con_vc_close_call(&(vc[want_vc & ~0x1000]->vc_l4id), &env);
00282 l4lock_lock(&want_vc_lock);
00283 want_vc = -1;
00284 }
00285
00286 if (want_vc < 0)
00287 {
00288 struct l4con_vc *new;
00289
00290 if ((new = vc[fg_vc]))
00291 {
00292 for (; (new = new->prev); )
00293 {
00294 if ((new->mode & CON_OUT) && !(new->mode & CON_MASTER))
00295 {
00296 i = new->vc_number;
00297 goto found;
00298 }
00299 }
00300 }
00301
00302 for (i=0; i<MAX_NR_L4CONS; i++)
00303 {
00304 if ((vc[i]->mode & CON_OUT) && !(vc[i]->mode & CON_MASTER))
00305 {
00306 found:
00307 LOG("switch to vc %02d", i);
00308
00309
00310 do_switch(i, 0);
00311 if (redraw_vc() != 0)
00312 {
00313
00314 CORBA_Environment env = dice_default_environment;
00315 printf("Closing vc %d\n", i);
00316 l4lock_unlock(&want_vc_lock);
00317 con_vc_close_call(&vc[i]->vc_l4id, &env);
00318 l4lock_lock(&want_vc_lock);
00319 continue;
00320 }
00321
00322 want_vc = fg_vc = i;
00323 break;
00324 }
00325 }
00326 if (i == MAX_NR_L4CONS)
00327 {
00328 LOG("All vc's closed");
00329
00330 do_switch(0, -1);
00331 want_vc = fg_vc;
00332 }
00333 }
00334 else
00335 {
00336
00337 if (want_vc >= MAX_NR_L4CONS)
00338 {
00339
00340 want_vc = fg_vc;
00341 ev_partner_l4id = vc[fg_vc]->ev_partner_l4id;
00342 vc_partner_l4id = vc[fg_vc]->vc_partner_l4id;
00343 vc_mode = vc[fg_vc]->mode;
00344 return;
00345 }
00346
00347
00348 if (vc[want_vc]->mode & CON_OUT)
00349 {
00350 do_switch(want_vc, fg_vc);
00351 if (redraw_vc() != 0)
00352 {
00353
00354 CORBA_Environment env = dice_default_environment;
00355 printf("Closing vc %d\n", want_vc);
00356 l4lock_unlock(&want_vc_lock);
00357 con_vc_close_call(&(vc[want_vc]->vc_l4id), &env);
00358 l4lock_lock(&want_vc_lock);
00359
00360 want_vc = -1;
00361 goto retry;
00362 }
00363
00364
00365 fg_vc = want_vc;
00366 }
00367 else
00368 {
00369
00370 want_vc = fg_vc;
00371 }
00372 }
00373 }
00374
00375 static void
00376 do_switch(int i_new, int i_old)
00377 {
00378 struct l4con_vc *old = (i_old >= 0) ? vc[i_old] : 0;
00379 struct l4con_vc *new = (i_new >= 0) ? vc[i_new] : 0;
00380
00381
00382 if (old != 0)
00383 {
00384 l4lock_lock(&old->fb_lock);
00385 if (old->save_restore && old->vfb)
00386 {
00387
00388 if (use_fastmemcpy && (new->vfb_size % 4096 == 0))
00389 fast_memcpy_mmx2_32(old->vfb, vis_vmem, old->vfb_size);
00390 else
00391 fast_memcpy (old->vfb, vis_vmem, old->vfb_size);
00392 }
00393 old->fb = old->vfb_in_server ? old->vfb : 0;
00394 old->pan_xofs = old->vfb_in_server ? 0 : pan_offs_x;
00395 old->pan_yofs = old->vfb_in_server ? 0 : pan_offs_y;
00396 old->do_copy = bg_do_copy;
00397 old->do_fill = bg_do_fill;
00398 old->do_sync = bg_do_sync;
00399 old->do_drty = 0;
00400 old->next = new;
00401 l4lock_unlock(&old->fb_lock);
00402 }
00403
00404
00405 if (new != 0)
00406 {
00407 l4lock_lock(&new->fb_lock);
00408 new->fb = gr_vmem;
00409 new->pan_xofs = pan_offs_x;
00410 new->pan_yofs = pan_offs_y;
00411 new->do_copy = fg_do_copy;
00412 new->do_fill = fg_do_fill;
00413 new->do_sync = fg_do_sync;
00414 new->do_drty = fg_do_drty;
00415 new->prev = old;
00416
00417 if (i_new == 0 || !new->save_restore || !new->vfb)
00418 {
00419
00420
00421
00422
00423 vc_clear(new);
00424 }
00425
00426 if (new->save_restore && new->vfb)
00427 {
00428
00429 if (use_fastmemcpy && (new->vfb_size % 4096 == 0))
00430 fast_memcpy_mmx2_32(vis_vmem, new->vfb, new->vfb_size);
00431 else
00432 fast_memcpy (vis_vmem, new->vfb, new->vfb_size);
00433 }
00434
00435
00436 if (new->do_drty)
00437 new->do_drty(0, 0, VESA_XRES, VESA_YRES);
00438
00439 update_id = 1;
00440 l4lock_unlock(&new->fb_lock);
00441 }
00442
00443
00444 background_vc();
00445
00446 if (old && old->fb_mapped)
00447 {
00448
00449
00450
00451
00452 l4_addr_t map_addr;
00453
00454 for (map_addr=(l4_addr_t)gr_vmem;
00455 map_addr+L4_SUPERPAGESIZE < (l4_addr_t)gr_vmem_maxmap;
00456 map_addr+=L4_SUPERPAGESIZE)
00457 {
00458 l4_fpage_unmap(l4_fpage(map_addr, L4_LOG2_SUPERPAGESIZE, 0, 0),
00459 L4_FP_FLUSH_PAGE | L4_FP_OTHER_SPACES);
00460 }
00461 }
00462 ev_partner_l4id = vc[i_new]->ev_partner_l4id;
00463 vc_partner_l4id = vc[i_new]->vc_partner_l4id;
00464 vc_mode = vc[i_new]->mode;
00465 }
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479 long
00480 con_if_openqry_component (CORBA_Object _dice_corba_obj,
00481 unsigned long sbuf1_size,
00482 unsigned long sbuf2_size,
00483 unsigned long sbuf3_size,
00484 unsigned char priority,
00485 l4_threadid_t *vcid,
00486 short vfbmode,
00487 CORBA_Server_Environment *_dice_corba_env)
00488 {
00489 l4thread_t vc_tid;
00490 l4_threadid_t vc_l4id, dummy;
00491 l4dm_dataspace_t ds;
00492 l4_offs_t ds_offs;
00493 l4_addr_t ds_map_addr;
00494 l4_size_t ds_map_size;
00495 int vc_num;
00496 char name[32];
00497
00498
00499 if (!sbuf1_size
00500 || (sbuf2_size != 0 && sbuf3_size == 0)
00501 || (sbuf2_size == 0 && sbuf3_size != 0)
00502 || (sbuf1_size + sbuf2_size + sbuf3_size) > CONFIG_MAX_SBUF_SIZE)
00503 {
00504 LOG("Wrong string buffer size");
00505 return -CON_EXPARAM;
00506 }
00507
00508
00509 if ((vc_num = get_free_vc()) == -CON_EFREE)
00510 return vc_num;
00511
00512
00513 sprintf(name, "ipcbuf1 for "l4util_idfmt"", l4util_idstr(*_dice_corba_obj));
00514 if (!(vc[vc_num]->sbuf1 =
00515 l4dm_mem_allocate_named(sbuf1_size, L4RM_MAP, name)))
00516 {
00517 LOG("Ooops, not enough memory for 1st string buffer");
00518 return -CON_ENOMEM;
00519 }
00520
00521 vc[vc_num]->sbuf2 = 0;
00522 if (sbuf2_size > 0)
00523 {
00524 sprintf(name, "ipcbuf2 for "l4util_idfmt"",
00525 l4util_idstr(*_dice_corba_obj));
00526 if (sbuf2_size)
00527 {
00528 if (!(vc[vc_num]->sbuf2 =
00529 l4dm_mem_allocate_named(sbuf2_size, L4RM_MAP, name)))
00530 {
00531 LOG("Ooops, not enough memory for 2nd string buffer");
00532 l4dm_mem_release(vc[vc_num]->sbuf1);
00533 return -CON_ENOMEM;
00534 }
00535 }
00536 }
00537
00538 vc[vc_num]->sbuf3 = 0;
00539 if (sbuf3_size > 0)
00540 {
00541 sprintf(name, "ipcbuf3 for "l4util_idfmt"",
00542 l4util_idstr(*_dice_corba_obj));
00543 if (sbuf3_size)
00544 {
00545 if (!(vc[vc_num]->sbuf3 =
00546 l4dm_mem_allocate_named(sbuf3_size, L4RM_MAP, name)))
00547 {
00548 LOG("Ooops, not enough memory for 3rd string buffer");
00549 l4dm_mem_release(vc[vc_num]->sbuf1);
00550 l4dm_mem_release(vc[vc_num]->sbuf2);
00551 return -CON_ENOMEM;
00552 }
00553 }
00554 }
00555
00556 vc[vc_num]->fb = 0;
00557 vc[vc_num]->vfb = 0;
00558 vc[vc_num]->vfb_in_server = vfbmode;
00559 vc[vc_num]->mode = CON_OPENING;
00560 vc[vc_num]->vc_partner_l4id = *_dice_corba_obj;
00561 vc[vc_num]->sbuf1_size = sbuf1_size;
00562 vc[vc_num]->sbuf2_size = sbuf2_size;
00563 vc[vc_num]->sbuf3_size = sbuf3_size;
00564 vc[vc_num]->fb_mapped = 0;
00565
00566 if (vfbmode)
00567 vc[vc_num]->save_restore = 1;
00568
00569 sprintf(name, ".vc-%.2d", vc_num);
00570 vc_tid = l4thread_create_long(L4THREAD_INVALID_ID,
00571 (l4thread_fn_t) vc_loop, name,
00572 L4THREAD_INVALID_SP, L4THREAD_DEFAULT_SIZE,
00573
00574
00575 priority == 0xff ? L4THREAD_DEFAULT_PRIO : priority,
00576 (void *) vc[vc_num],
00577 L4THREAD_CREATE_SYNC);
00578
00579 vc_l4id = l4thread_l4_id(vc_tid);
00580
00581 vc[vc_num]->vc_l4id = vc_l4id;
00582 vc[vc_num]->ev_partner_l4id = L4_NIL_ID;
00583
00584
00585 if (L4RM_REGION_DATASPACE == l4rm_lookup(vc[vc_num]->sbuf1, &ds_map_addr,
00586 &ds_map_size, &ds, &ds_offs, &dummy))
00587 l4dm_transfer(&ds, vc_l4id);
00588 if (L4RM_REGION_DATASPACE == l4rm_lookup(vc[vc_num]->sbuf2, &ds_map_addr,
00589 &ds_map_size, &ds, &ds_offs, &dummy))
00590 l4dm_transfer(&ds, vc_l4id);
00591 if (L4RM_REGION_DATASPACE == l4rm_lookup(vc[vc_num]->sbuf3, &ds_map_addr,
00592 &ds_map_size, &ds, &ds_offs, &dummy))
00593 l4dm_transfer(&ds, vc_l4id);
00594
00595
00596 *vcid = vc_l4id;
00597
00598 return 0;
00599 }
00600
00601 long
00602 con_if_screenshot_component (CORBA_Object _dice_corba_obj,
00603 short vc_nr,
00604 l4dm_dataspace_t *ds,
00605 l4_uint32_t *xres,
00606 l4_uint32_t *yres,
00607 l4_uint32_t *bpp,
00608 CORBA_Server_Environment *_dice_corba_env)
00609 {
00610 void *addr;
00611 struct l4con_vc *vc_shoot;
00612
00613 if (vc_nr >= MAX_NR_L4CONS)
00614 return -L4_EINVAL;
00615
00616 if (vc_nr == 0)
00617 vc_nr = fg_vc;
00618
00619 vc_shoot = vc[vc_nr];
00620
00621 if (!(vc_shoot->mode & CON_INOUT))
00622 return -L4_EINVAL;
00623
00624 if (!vc_shoot->vfb_in_server && vc_nr != fg_vc)
00625 return -L4_EINVAL;
00626
00627 l4lock_lock(&vc_shoot->fb_lock);
00628
00629 if (!(addr = l4dm_mem_ds_allocate_named(vc_shoot->vfb_size, 0, "screenshot",
00630 (l4dm_dataspace_t*)ds)))
00631 {
00632 printf("Allocating dataspace failed\n");
00633 return -CON_ENOMEM;
00634 }
00635
00636
00637
00638 memcpy(addr, vc_shoot->vfb_in_server ? vc_shoot->vfb : vc_shoot->fb,
00639 vc_shoot->vfb_size);
00640
00641 l4lock_unlock(&vc_shoot->fb_lock);
00642
00643 *xres = VESA_XRES;
00644 *yres = VESA_YRES;
00645 *bpp = VESA_BITS;
00646
00647 l4rm_detach(addr);
00648
00649
00650 l4dm_transfer((l4dm_dataspace_t*)ds, *_dice_corba_obj);
00651
00652 return 0;
00653 }
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663 long
00664 con_if_close_all_component (CORBA_Object _dice_corba_obj,
00665 const l4_threadid_t *client,
00666 CORBA_Server_Environment *_dice_corba_env)
00667 {
00668 int i;
00669
00670 for (i=0; i<MAX_NR_L4CONS; i++)
00671 {
00672 if (vc[i]->mode != CON_CLOSED && vc[i]->mode != CON_CLOSING)
00673 {
00674
00675 if (vc[i]->vc_partner_l4id.id.task == client->id.task)
00676 {
00677
00678 CORBA_Environment env = dice_default_environment;
00679 int ret = con_vc_close_call(&(vc[i]->vc_l4id), &env);
00680 if (ret || DICE_HAS_EXCEPTION(&env))
00681 printf("Error %d (env=%02x) closing app "l4util_idfmt
00682 " service thread "l4util_idfmt,
00683 ret, DICE_IPC_ERROR(&env), l4util_idstr(*client),
00684 l4util_idstr(vc[i]->vc_l4id));
00685 }
00686 }
00687 }
00688
00689 return 0;
00690 }
00691
00692 static void
00693 test_periodic(void)
00694 {
00695 static l4_umword_t last_active_fast;
00696 static l4_umword_t last_active_slow;
00697 l4_umword_t clock = l4sigma0_kip()->clock;
00698 l4_umword_t _utcb[L4_UTCB_GENERIC_DATA_SIZE];
00699 l4_utcb_t *utcb = l4_utcb_get();
00700
00701 if (clock - last_active_fast >= 25000)
00702 {
00703
00704 memcpy(_utcb, utcb->values, L4_UTCB_GENERIC_DATA_SIZE * sizeof(l4_umword_t));
00705
00706 l4lock_lock(&want_vc_lock);
00707 if (want_vc != fg_vc)
00708 switch_vc();
00709 l4lock_unlock(&want_vc_lock);
00710
00711
00712 if (update_id && fg_vc >= 0)
00713 {
00714 l4lock_lock(&vc[fg_vc]->fb_lock);
00715 vc_show_id(vc[fg_vc]);
00716 l4lock_unlock(&vc[fg_vc]->fb_lock);
00717 update_id = 0;
00718
00719 last_active_slow = clock - 1000000;
00720 }
00721
00722
00723 if (vc[fg_vc]->logo_x != 100000)
00724 {
00725 l4lock_lock(&vc[fg_vc]->fb_lock);
00726 vc_show_drops_cscs_logo();
00727 l4lock_unlock(&vc[fg_vc]->fb_lock);
00728 }
00729
00730 last_active_fast = clock;
00731
00732 memcpy(utcb->values, _utcb, L4_UTCB_GENERIC_DATA_SIZE * sizeof(l4_umword_t));
00733 }
00734
00735 if (clock - last_active_slow >= 1000000)
00736 {
00737
00738 memcpy(_utcb, utcb->values, L4_UTCB_GENERIC_DATA_SIZE * sizeof(l4_umword_t));
00739
00740 l4lock_lock(&vc[fg_vc]->fb_lock);
00741
00742
00743 vc_show_dmphys_poolsize(vc[fg_vc]);
00744
00745 if (cpu_load)
00746
00747 vc_show_cpu_load(vc[fg_vc]);
00748
00749 l4lock_unlock(&vc[fg_vc]->fb_lock);
00750 last_active_slow = clock;
00751
00752 memcpy(utcb->values, _utcb, L4_UTCB_GENERIC_DATA_SIZE * sizeof(l4_umword_t));
00753 }
00754 }
00755
00756 void
00757 switch_vc_on_timer(l4_msgdope_t result, CORBA_Server_Environment* env)
00758 {
00759 if (L4_IPC_ERROR(result) == L4_IPC_RETIMEOUT)
00760 test_periodic();
00761
00762 else if (L4_IPC_ERROR(result) == L4_IPC_SETIMEOUT)
00763
00764 LOG("Timeout replying last client");
00765
00766 else
00767
00768 Panic("IDL IPC error (%#lx, %s)",
00769 L4_IPC_ERROR(result), l4env_strerror(L4_IPC_ERROR(result)));
00770 }
00771
00772 static void
00773 server_loop(void)
00774 {
00775 CORBA_Server_Environment corba_env = dice_default_server_environment;
00776 CORBA_Object_base corba_obj;
00777 con_if_msg_buffer_t msg_buffer;
00778 l4_msgtag_t tag = l4_msgtag(0, 0, 0, 0);
00779 l4_int16_t reply;
00780 l4_int32_t opcode;
00781
00782 corba_env.timeout = REQUEST_TIMEOUT;
00783 DICE_SIZE_DOPE(&msg_buffer) = L4_IPC_DOPE(8, 0);
00784
00785 for (;;)
00786 {
00787 opcode = con_if_srv_wait_any(&corba_obj, &tag, &msg_buffer, &corba_env);
00788 for (;;)
00789 {
00790 reply = con_if_dispatch(&corba_obj, opcode, &tag, &msg_buffer, &corba_env);
00791
00792
00793 test_periodic();
00794 if (reply != DICE_REPLY)
00795 break;
00796 if (DICE_EXCEPTION_MAJOR(&corba_env) == CORBA_SYSTEM_EXCEPTION &&
00797 DICE_EXCEPTION_MINOR(&corba_env) ==
00798 CORBA_DICE_EXCEPTION_WRONG_OPCODE)
00799 {
00800
00801
00802 printf("Wrong opcode %08x from "l4util_idfmt" -- ignoring\n",
00803 opcode, l4util_idstr(corba_obj));
00804 break;
00805 }
00806 opcode = con_if_reply_and_wait(&corba_obj, &tag, &msg_buffer, &corba_env);
00807 }
00808 }
00809 }
00810
00811 #ifdef ARCH_x86
00812 static int sse_faulted;
00813
00814 static int
00815 rm_fault_sse(l4_msgtag_t tag, l4_utcb_t *utcb, l4_threadid_t src)
00816 {
00817 extern char after_sse_insn[];
00818 sse_faulted = 1;
00819 utcb->exc.eip = (l4_umword_t)after_sse_insn;
00820 return L4RM_REPLY_EMPTY;
00821 }
00822 #endif // ARCH_x86
00823
00824 static void
00825 check_fast_memcpy(void)
00826 {
00827 #if defined(ARCH_x86) || defined(ARCH_amd64)
00828 if (use_fastmemcpy)
00829 {
00830
00831 # ifdef ARCH_x86
00832 l4_uint64_t src, dst;
00833 l4rm_set_unkown_fault_callback(rm_fault_sse);
00834 asm volatile("emms; movq (%0),%%mm0; movntq %%mm0,(%1); sfence; emms"
00835 : : "r"(&src), "r"(&dst) , "m"(src) : "memory");
00836 asm volatile(".global after_sse_insn; after_sse_insn:" ::: "memory");
00837 l4rm_set_unkown_fault_callback(NULL);
00838 if (!sse_faulted)
00839 {
00840 # endif
00841 printf("Using fast memcpy.\n");
00842 # ifdef ARCH_x86
00843 }
00844 else
00845 {
00846 printf("Fast memcpy not supported by this CPU.\n");
00847 use_fastmemcpy = 0;
00848 }
00849 # endif
00850 return;
00851 }
00852 #else
00853 use_fastmemcpy = 0;
00854 #endif
00855 printf("Not using fast memcpy\n");
00856 }
00857
00858 #if defined(ARCH_x86) || defined(ARCH_amd64)
00859 static int rdpmc_faulted;
00860
00861 static int
00862 rm_fault_rdpmc(l4_msgtag_t tag, l4_utcb_t *utcb, l4_threadid_t src)
00863 {
00864 extern char after_rdpmc_insn[];
00865 if (*(l4_uint16_t *)utcb->exc.eip != 0x330f)
00866 {
00867 printf("Not faulted at rdpmc function (pc = %lx)", utcb->exc.eip);
00868 return L4RM_REPLY_NO_REPLY;
00869 }
00870 utcb->exc.eip = (l4_umword_t)after_rdpmc_insn;
00871 rdpmc_faulted = 1;
00872 return L4RM_REPLY_EMPTY;
00873 }
00874
00875 static void
00876 check_cpuload(void)
00877 {
00878 if (cpu_load)
00879 {
00880 l4rm_set_unkown_fault_callback(rm_fault_rdpmc);
00881 asm volatile("" ::: "memory");
00882 l4_rdpmc_32(0);
00883 asm volatile(".global after_rdpmc_insn; after_rdpmc_insn:" ::: "memory");
00884 l4rm_set_unkown_fault_callback(NULL);
00885 if (!rdpmc_faulted)
00886 {
00887 printf("Enabling CPU load indicator\n"
00888 "\033[32mALTGR+PAUSE switches CPU load indicator!\033[m\n");
00889 }
00890 else
00891 {
00892 printf("Disabling CPU load indicator since rdpmc not available\n");
00893 cpu_load = 0;
00894 }
00895 }
00896 }
00897 #else
00898 static void
00899 check_cpuload(void)
00900 {
00901 cpu_load = 0;
00902 }
00903 #endif
00904
00905 extern int console_puts(const char *s);
00906 static void
00907 my_LOG_outstring(const char *s)
00908 {
00909 console_puts(s);
00910 }
00911
00912
00913 asm (".globl jiffies");
00914
00915
00916
00917 int
00918 main(int argc, const char *argv[])
00919 {
00920 l4_threadid_t me = l4thread_l4_id(l4thread_myself());
00921 int error;
00922 int use_events = 0;
00923
00924 #ifdef ARCH_arm
00925 noaccel = 1;
00926 #endif
00927
00928 l4sigma0_kip_map(L4_INVALID_ID);
00929
00930 if ((error = parse_cmdline(&argc, &argv,
00931 'a', "noaccel", "disable hardware acceleration",
00932 PARSE_CMD_SWITCH, 1, &noaccel,
00933 #ifndef ARCH_arm
00934 'c', "cpuload", "show CPU load using rdtsc and rdpmc(0)",
00935 PARSE_CMD_SWITCH, 1, &cpu_load,
00936 #endif
00937 'e', "events", "use event server to free resources",
00938 PARSE_CMD_SWITCH, 1, &use_events,
00939 'l', "nolog", "don't connect to logserver",
00940 PARSE_CMD_SWITCH, 1, &nolog,
00941 'm', "nomouse", "don't transmit mouse events to clients",
00942 PARSE_CMD_SWITCH, 1, &nomouse,
00943 'n', "nofastmemcpy", "force to not use fast memcpy",
00944 PARSE_CMD_SWITCH, 0, &use_fastmemcpy,
00945 'p', "pan", "use panning to restrict client window",
00946 PARSE_CMD_SWITCH, 1, &pan,
00947 ' ', "noshift", "no shift key for console switching",
00948 PARSE_CMD_SWITCH, 1, &noshift,
00949 'v', "vbemode", "set VESA mode",
00950 PARSE_CMD_INT, 0, &vbemode,
00951 0)))
00952 {
00953 switch (error)
00954 {
00955 case -1: printf("Bad parameter for parse_cmdline()\n"); break;
00956 case -2: printf("Out of memory in parse_cmdline()\n"); break;
00957 case -4: return 1;
00958 default: printf("Error %d in parse_cmdline()\n", error); break;
00959 }
00960 }
00961
00962 cpu_load_history = 1;
00963
00964
00965 if (nolog)
00966 LOG_outstring = my_LOG_outstring;
00967
00968
00969 check_fast_memcpy();
00970 check_cpuload();
00971
00972 vc_init();
00973
00974
00975 do_switch(0, -1);
00976 vc_show_id(vc[0]);
00977 fg_vc = want_vc = 0;
00978 update_id = 0;
00979
00980 ev_init();
00981
00982
00983 if (use_events)
00984 init_events();
00985
00986
00987 if (!names_register(CON_NAMES_STR))
00988 Panic("can't register at names");
00989
00990 printf("Running as "l4util_idfmt". Video mode is %dx%d@%d.\n",
00991 l4util_idstr(me), VESA_XRES, VESA_YRES, VESA_BITS);
00992
00993
00994 server_loop();
00995
00996 exit(0);
00997 }