コード例 #1
0
void
xen_set_segment_base(int reg, ulong_t value)
{
	long err;

	if ((err = HYPERVISOR_set_segment_base(reg, value)) != 0) {
		/*
		 * X_EFAULT:	bad address
		 * X_EINVAL:	bad type
		 */
		panic("xen_set_segment_base(%d, %lx): error %d",
		    reg, value, -(int)err);
	}
}
コード例 #2
0
static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high)
{
    int ret;

    ret = 0;

    switch (msr) {
#ifdef CONFIG_X86_64
        unsigned which;
        u64 base;

    case MSR_FS_BASE:
        which = SEGBASE_FS;
        goto set;
    case MSR_KERNEL_GS_BASE:
        which = SEGBASE_GS_USER;
        goto set;
    case MSR_GS_BASE:
        which = SEGBASE_GS_KERNEL;
        goto set;

set:
        base = ((u64)high << 32) | low;
        if (HYPERVISOR_set_segment_base(which, base) != 0)
            ret = -EIO;
        break;
#endif

    case MSR_STAR:
    case MSR_CSTAR:
    case MSR_LSTAR:
    case MSR_SYSCALL_MASK:
    case MSR_IA32_SYSENTER_CS:
    case MSR_IA32_SYSENTER_ESP:
    case MSR_IA32_SYSENTER_EIP:
        /* Fast syscall setup is all done in hypercalls, so
           these are all ignored.  Stub them out here to stop
           Xen console noise. */
        break;

    default:
        ret = native_write_msr_safe(msr, low, high);
    }

    return ret;
}
コード例 #3
0
static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high)
{
	int ret;

	ret = 0;

	switch (msr) {
#ifdef CONFIG_X86_64
		unsigned which;
		u64 base;

	case MSR_FS_BASE:		which = SEGBASE_FS; goto set;
	case MSR_KERNEL_GS_BASE:	which = SEGBASE_GS_USER; goto set;
	case MSR_GS_BASE:		which = SEGBASE_GS_KERNEL; goto set;

	set:
		base = ((u64)high << 32) | low;
		if (HYPERVISOR_set_segment_base(which, base) != 0)
			ret = -EIO;
		break;
#endif

	case MSR_STAR:
	case MSR_CSTAR:
	case MSR_LSTAR:
	case MSR_SYSCALL_MASK:
	case MSR_IA32_SYSENTER_CS:
	case MSR_IA32_SYSENTER_ESP:
	case MSR_IA32_SYSENTER_EIP:
		/*                                                 
                                                       
                        */
		break;

	case MSR_IA32_CR_PAT:
		if (smp_processor_id() == 0)
			xen_set_pat(((u64)high << 32) | low);
		break;

	default:
		ret = native_write_msr_safe(msr, low, high);
	}

	return ret;
}
コード例 #4
0
ファイル: enlighten.c プロジェクト: argentinos/o2droid
static void xen_load_gs_index(unsigned int idx)
{
	if (HYPERVISOR_set_segment_base(SEGBASE_GS_USER_SEL, idx))
		BUG();
}
コード例 #5
0
ファイル: sundep.c プロジェクト: pcd1193182/openzfs
/*
 * Update the segment registers with new values from the pcb.
 *
 * We have to do this carefully, and in the following order,
 * in case any of the selectors points at a bogus descriptor.
 * If they do, we'll catch trap with on_trap and return 1.
 * returns 0 on success.
 *
 * This is particularly tricky for %gs.
 * This routine must be executed under a cli.
 */
int
update_sregs(struct regs *rp,  klwp_t *lwp)
{
	pcb_t *pcb = &lwp->lwp_pcb;
	ulong_t	kgsbase;
	on_trap_data_t	otd;
	int rc = 0;

	if (!on_trap(&otd, OT_SEGMENT_ACCESS)) {

#if defined(__xpv)
		/*
		 * On the hyervisor this is easy. The hypercall below will
		 * swapgs and load %gs with the user selector. If the user
		 * selector is bad the hypervisor will catch the fault and
		 * load %gs with the null selector instead. Either way the
		 * kernel's gsbase is not damaged.
		 */
		kgsbase = (ulong_t)CPU;
		if (HYPERVISOR_set_segment_base(SEGBASE_GS_USER_SEL,
		    pcb->pcb_gs) != 0) {
				no_trap();
				return (1);
		}

		rp->r_gs = pcb->pcb_gs;
		ASSERT((cpu_t *)kgsbase == CPU);

#else	/* __xpv */

		/*
		 * A little more complicated running native.
		 */
		kgsbase = (ulong_t)CPU;
		__set_gs(pcb->pcb_gs);

		/*
		 * If __set_gs fails it's because the new %gs is a bad %gs,
		 * we'll be taking a trap but with the original %gs and %gsbase
		 * undamaged (i.e. pointing at curcpu).
		 *
		 * We've just mucked up the kernel's gsbase.  Oops.  In
		 * particular we can't take any traps at all.  Make the newly
		 * computed gsbase be the hidden gs via __swapgs, and fix
		 * the kernel's gsbase back again. Later, when we return to
		 * userland we'll swapgs again restoring gsbase just loaded
		 * above.
		 */
		__swapgs();
		rp->r_gs = pcb->pcb_gs;

		/*
		 * restore kernel's gsbase
		 */
		wrmsr(MSR_AMD_GSBASE, kgsbase);

#endif	/* __xpv */

		/*
		 * Only override the descriptor base address if
		 * r_gs == LWPGS_SEL or if r_gs == NULL. A note on
		 * NULL descriptors -- 32-bit programs take faults
		 * if they deference NULL descriptors; however,
		 * when 64-bit programs load them into %fs or %gs,
		 * they DONT fault -- only the base address remains
		 * whatever it was from the last load.   Urk.
		 *
		 * XXX - note that lwp_setprivate now sets %fs/%gs to the
		 * null selector for 64 bit processes. Whereas before
		 * %fs/%gs were set to LWP(FS|GS)_SEL regardless of
		 * the process's data model. For now we check for both
		 * values so that the kernel can also support the older
		 * libc. This should be ripped out at some point in the
		 * future.
		 */
		if (pcb->pcb_gs == LWPGS_SEL || pcb->pcb_gs == 0) {
#if defined(__xpv)
			if (HYPERVISOR_set_segment_base(SEGBASE_GS_USER,
			    pcb->pcb_gsbase)) {
				no_trap();
				return (1);
			}
#else
			wrmsr(MSR_AMD_KGSBASE, pcb->pcb_gsbase);
#endif
		}

		__set_ds(pcb->pcb_ds);
		rp->r_ds = pcb->pcb_ds;

		__set_es(pcb->pcb_es);
		rp->r_es = pcb->pcb_es;

		__set_fs(pcb->pcb_fs);
		rp->r_fs = pcb->pcb_fs;

		/*
		 * Same as for %gs
		 */
		if (pcb->pcb_fs == LWPFS_SEL || pcb->pcb_fs == 0) {
#if defined(__xpv)
			if (HYPERVISOR_set_segment_base(SEGBASE_FS,
			    pcb->pcb_fsbase)) {
				no_trap();
				return (1);
			}
#else
			wrmsr(MSR_AMD_FSBASE, pcb->pcb_fsbase);
#endif
		}

	} else {
		cli();
		rc = 1;
	}
	no_trap();
	return (rc);
}