[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] Re: [RFC, PATCH 5/24] i386 Vmi code patching
On Mar 16, 2006, at 00:00 , Pavel Machek wrote: The question of licensing of such ROM code is a completely separate issue. We are not trying to hide some proprietary code by putting it inside of a ROM to keep it hidden. In fact, you can disassemble the ROM code and see it quite readily - and you know all of the entry points.Could you disassemble one entry point for us and describe how it works? Here is how I construct my ROM. My apologies if my email client wraps any of the lines. I have a set of boundary functions between assembler and C code, identified by a suffix on the function names: _ext (stands for "extended" in response to the evolution of my ROM). They accept a parameter called burn_clobbers_frame_t: struct burn_clobbers_frame_t { word_t burn_ret_address; /* Return address to the ROM */ word_t frame_pointer; /* This parameter. */ word_t edx; word_t ecx; word_t eax; word_t guest_ret_address; word_t params[0]; /* Anything the guest pushed on the stack */ }; I use this structure for the non-performance critical functions. Here are some of the assembler macros for constructing the ROM: vmi_stub_simple WRMSR, afterburn_cpu_write_msr_ext vmi_stub_simple RDMSR, afterburn_cpu_read_msr_ext vmi_stub_simple SetGDT, afterburn_cpu_write_gdt32_ext vmi_stub_simple SetLDT, afterburn_cpu_lldt_ext vmi_stub_simple SetIDT, afterburn_cpu_write_idt32_ext vmi_stub_simple SetTR, afterburn_cpu_ltr_ext macro vmi_stub_simple name func /* Invoke a front-end C function that expects a burn_clobbers_frame_t as * the parameter. */ vmi_stub_begin \name __afterburn_save_clobbers push %esp subl $8, 0(%esp) vmi_call_relocatable \func __afterburn_restore_clobbers 4 ret vmi_stub_end .endm .macro vmi_stub_begin name /* Define the prolog of a VMI stub. */ vmi_area_begin \name burn_counter VMI_\name burn_counter_inc VMI_\name .endm .macro vmi_stub_end /* Define the epilog of a VMI stub. */ .previous .endm .macro vmi_area_begin name /* Define the start of a VMI area. */ .section .vmi_rom, "ax" .org vmi_rom_offset_\name .globl VMI_\name .type VMI_\name,@function VMI_\name: .endm .macro vmi_call_relocatable func 9191: call \func .pushsection .vmi_patchups, "aw" .balign 4 .long 9191b .popsection .endm .macro vmi_jmp_relocatable target 9191: jmp \target .pushsection .vmi_patchups, "aw" .balign 4 .long 9191b .popsection .endm extern "C" void afterburn_cpu_write_gdt32_ext( burn_clobbers_frame_t *frame ) { get_cpu()->gdtr = *(dtr_t *)frame->eax; }The ROM entry points are only half the solution. The other half involves Xen callbacks and traps. The system call trap is constructed to directly activate Linux's system call trap. Everything else jumps directly into the ROM for filtering reasons. The page-fault handler stays in assembler (because page faults are a performance issue; on a linux kernel build, they occur almost as frequently as system calls). The remaining traps enter C code, and look like this: trap_wrapper id=8, use_error_code=1 /* Double fault exception */trap_wrapper id=9, use_error_code=0 /* Coprocessor segment overrun */ trap_wrapper id=10, use_error_code=1 /* Invalid TSS exception */ trap_wrapper id=11, use_error_code=1 /* Segment not present */ trap_wrapper id=12, use_error_code=1 /* Stack fault exception */ trap_wrapper id=13, use_error_code=1 /* general protection fault */ .macro trap_wrapper id, use_error_code entry trap_wrapper_\id .if \use_error_code subl $4, %esp /* Fault addr. */ .else subl $8, %esp /* Error code, fault addr. */ .endif pushl $(\id | (\use_error_code << 31)) /* Frame ID. */ cpu_save_all movl %esp, %eax /* A pointer to the CPU save frame. */ call trap jmp afterburn_exit .endm entry afterburn_exit cpu_restore_all 0, 12 /* Error code, fault addr, frame id. */ iret extern "C" void __attribute__(( regparm(1) )) trap( xen_frame_t *frame ) { if( EXPECT_FALSE(frame->iret.ip >= CONFIG_WEDGE_VIRT) ) {con << "Unexpected fault in the ROM, ip " << (void *)frame- >iret.ip << '\n'; DEBUGGER_ENTER(frame); panic(); } u8_t *opstream = (u8_t *)frame->iret.ip; if( cpu_t::get_segment_privilege(frame->iret.cs) == 3 ) { // A user-level fault. ... check for TLS issues ... }// Update virtual CPU state, and deliver the trap to the guest kernel. xen_deliver_async_vector( frame->get_id(), frame, frame->uses_error_code()); } _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |