vcpu example problem

雷雷健 raylei0825ssdut at gmail.com
Thu Aug 2 05:14:34 CEST 2012


Hi,
       I  am trying  to modify the vcpu example of l4re-snapshot to
switch registers to execute my C function.But It doesn't work.
       I have read some papers about l4linux tranplantion.and follow it .
       To switch the process, I fill the vcpu_state_t structure with
its registers.and call vcpu_resume_commit action.Then Jump to the ASM
Code.
       But problem arises when I want to jump from asm code to C
function. What's the Problem? The Code is as following:
/*
 * (c) 2009 Technische Universität Dresden
 * This file is part of TUD:OS, which is distributed under the terms of the
 * GNU General Public License 2. Please see the COPYING file for details.
 */
#include <l4/sys/ipc.h>
#include <l4/sys/thread>
#include <l4/sys/factory>
#include <l4/sys/scheduler>
#include <l4/sys/utcb.h>
#include <l4/sys/kdebug.h>
#include <l4/util/util.h>
#include <l4/re/env>
#include <l4/re/util/cap_alloc>
#include <l4/re/util/kumem_alloc>
#include <l4/sys/debugger.h>
#include <l4/vcpu/vcpu>
#include <l4/cxx/iostream>

#include <l4/re/error_helper>

#include <l4/sys/task>
#include <l4/sys/irq>
#include <l4/sys/vcpu.h>

#include <cstdlib>
#include <cstdio>
#include <cstring>
#define PSR_T_BIT       0x00000000
#define SVC_MODE	0x00000013
#define PSR_E_BIT	0x00000200
#define PSR_I_BIT	0x00000000
#define USR_MODE	0x00000010
using L4Re::chksys;
using L4Re::chkcap;

static L4::Cap<L4::Irq> irq;

static char thread_stack[8 << 10];
static char hdl_stack[8 << 10];
static char idle_stack[8<<10];
static L4::Cap<L4::Task> vcpu_task;
static L4vcpu::Vcpu *vcpu;

const l4_addr_t super_code_map_addr = 0x10000;
const l4_addr_t idle_code_map_addr  = 0x20000;
const l4_addr_t stack_map_addr = 0x12000;
const l4_addr_t exit_map_addr=0x13000;
extern char my_super_code[];
extern char my_super_code_excp[];
extern char my_super_code_excp_after[];
extern char exit_code[];



void idle_code(void)
{
;
while(1)
{
__asm__ volatile("swi 0");
 l4_sleep(500);
}
}
asm(
".global exit_code \t\n"
"exit_code: \t\n"
"b exit_code \t\n"
);

asm volatile
(
  ".pushsection .text\n"
  ".p2align 12         \t\n"
  ".global my_super_code  \t\n"
  "my_super_code:   \t\n"
"	msr	cpsr_c, r7\t\n"
"	mov	lr, r6   \t\n"
"	mov	pc, r5   \t\n"
//"       b       my_super_code \t\n"
".popsection"
);
static void setup_user_state_arch(L4vcpu::Vcpu *) { }
static void handler_prolog() {}




static void handler(void)
{
  handler_prolog();

  vcpu->state()->clear(L4_VCPU_F_EXCEPTIONS);
  printf("hello handler\n");
    //vcpu->print_state();

  // very simple page-fault handling
  // we're just replying with the only page we have, without checking any
  // values
  if (vcpu->is_page_fault_entry())
    {
      printf("page fault\n");
      vcpu_task->map(L4Re::This_task, l4_fpage((l4_addr_t)my_super_code,
                                                L4_PAGESHIFT, L4_FPAGE_RWX),
                                               super_code_map_addr);

     vcpu_task->map(L4Re::This_task, l4_fpage((l4_addr_t)idle_code,
                                                L4_PAGESHIFT, L4_FPAGE_RWX),
                                               idle_code_map_addr);
      vcpu_task->map(L4Re::This_task, l4_fpage((l4_addr_t)exit_code,
                                                L4_PAGESHIFT, L4_FPAGE_RWX),
                                               exit_map_addr);

      vcpu->saved_state()->add(L4_VCPU_F_PAGE_FAULTS);
    }
  else if (vcpu->is_irq_entry())
    {
      // We use the label 2000 for our IRQ
      if (vcpu->i()->label == 2000)
        printf("Our triggered IRQ\n");
      else if (vcpu->i()->label == 0)
        // direct IPC message to vCPU without
        // going through an IPCgate, label is set to 0
        printf("IPC: %lx\n", vcpu->i()->tag.label());
      else
        printf("Unclassifiable message\n");
    }
    else
        printf("unhandled exception\n");


  printf("resume\n");
  L4::Cap<L4::Thread> self;
  self->vcpu_resume_commit(self->vcpu_resume_start());
  //vcpu->state()->set(0);
  while(1)
    ;
}

static void vcpu_thread(void)
{
  printf("Hello vCPU\n");
    l4_umword_t label;
  memset(hdl_stack, 0, sizeof(hdl_stack));
  //memset(super_stack,0,sizeof(super_stack));
//  memset(idle_stack,0,sizeof(idle_stack));
  setup_user_state_arch(vcpu);
  l4_touch_rw(stack,sizeof(stack));
  l4_touch_rw(idle_stack,sizeof(idle_stack));
  vcpu->saved_state()->set(L4_VCPU_F_USER_MODE
                           | L4_VCPU_F_EXCEPTIONS
                           | L4_VCPU_F_PAGE_FAULTS
                           | L4_VCPU_F_IRQ);
  vcpu->r()->flags=(l4_umword_t)SVC_MODE;
  vcpu->r()->r[7]=(l4_umword_t)SVC_MODE;
  vcpu->r()->r[0]=(l4_umword_t)0;
  vcpu->r()->r[4]=(l4_umword_t)(idle_stack+sizeof(idle_stack)-1);
  vcpu->r()->r[6]=(l4_umword_t)exit_map_addr;
  vcpu->r()->ip =(l4_umword_t)super_code_map_addr;
  vcpu->r()->r[5] = (l4_umword_t)idle_code_map_addr;
  vcpu->r()->sp = (l4_umword_t)0x30000;
  L4::Cap<L4::Thread> self;
  printf("IRET\n");
  vcpu->task(vcpu_task);
  self->vcpu_resume_commit(self->vcpu_resume_start());
  printf("IRET: failed!\n");
  while(1);

}

int run(void)
{
  l4_utcb_t *u = l4_utcb();
  L4::Cap<L4::Thread> vcpu_cap;

  printf("vCPU example\n");

  l4_debugger_set_object_name(l4re_env()->main_thread, "vcputest");

  // new task
  vcpu_task = chkcap(L4Re::Util::cap_alloc.alloc<L4::Task>(),
                     "Task cap alloc");

  chksys(L4Re::Env::env()->factory()->create_task(vcpu_task,
                                                  l4_fpage_invalid()),
         "create task");
  l4_debugger_set_object_name(vcpu_task.cap(), "vcpu 'user' task");

  /* new thread/vCPU */
  vcpu_cap = chkcap(L4Re::Util::cap_alloc.alloc<L4::Thread>(),
                    "vCPU cap alloc");

  l4_touch_rw(thread_stack, sizeof(thread_stack));
  //l4_touch_rw(hdl_stack,sizeof(hdl_stack));
  chksys(L4Re::Env::env()->factory()->create_thread(vcpu_cap), "create thread");
  l4_debugger_set_object_name(vcpu_cap.cap(), "vcpu thread");

  // get an IRQ
  irq = chkcap(L4Re::Util::cap_alloc.alloc<L4::Irq>(),
               "Irq cap alloc");
  chksys(L4Re::Env::env()->factory()->create_irq(irq), "irq");
  l4_debugger_set_object_name(irq.cap(), "some irq");

  // get memory for vCPU state
  l4_addr_t kumem;
  if (0)
    kumem = (l4_addr_t)l4re_env()->first_free_utcb;
  else
    {
      if (L4Re::Util::kumem_alloc(&kumem, 0))
        exit(1);
    }
  l4_utcb_t *vcpu_utcb = (l4_utcb_t *)kumem;
  vcpu = L4vcpu::Vcpu::cast(kumem + L4_UTCB_OFFSET);
  vcpu->entry_sp((l4_umword_t)hdl_stack + sizeof(hdl_stack));
  vcpu->entry_ip((l4_umword_t)handler);

  printf("VCPU: utcb = %p, vcpu = %p\n", vcpu_utcb, vcpu);

  // Create and start vCPU thread
  L4::Thread::Attr attr;
  attr.pager(L4::cap_reinterpret_cast<L4::Thread>(L4Re::Env::env()->rm()));
  attr.exc_handler(L4Re::Env::env()->main_thread());
  attr.bind(vcpu_utcb, L4Re::This_task);
  chksys(vcpu_cap->control(attr), "control");
  chksys(vcpu_cap->vcpu_control((l4_addr_t)vcpu), "enable VCPU");

  chksys(vcpu_cap->ex_regs((l4_umword_t)vcpu_thread,
                           (l4_umword_t)thread_stack + sizeof(thread_stack),
                           0));

  chksys(L4Re::Env::env()->scheduler()->run_thread(vcpu_cap,
                                                   l4_sched_param(2)));

  // Attach irq to our vCPU thread
  chksys(irq->attach(2000, vcpu_cap));

  // Send some IPCs to the vCPU
   l4_sleep(10);
  while (1)
    {
   //  printf("triger irq\n");
     // irq->trigger();
      l4_sleep(500);
    }


  l4_sleep_forever();
  return 0;
}

int main()
{
  try { return run(); }
  catch (L4::Runtime_error &e)
    {
      L4::cerr << "FATAL uncought exception: " << e
               << "\nterminating...\n";
    }
  catch (...)
    {
      L4::cerr << "FATAL uncought exception of unknown type\n"
               << "terminating...\n";
    }
  return 1;
}




More information about the l4-hackers mailing list