Beispiel #1
0
func (vcpu *Vcpu) SetFpuState(state Fpu) error {

	// Prepare our data.
	var kvm_fpu C.struct_kvm_fpu
	for i := 0; i < len(state.FPR); i += 1 {
		for j := 0; j < len(state.FPR[i]); j += 1 {
			kvm_fpu.fpr[i][j] = C.__u8(state.FPR[i][j])
		}
	}
	kvm_fpu.fcw = C.__u16(state.FCW)
	kvm_fpu.fsw = C.__u16(state.FSW)
	kvm_fpu.ftwx = C.__u8(state.FTWX)
	kvm_fpu.last_opcode = C.__u16(state.LastOpcode)
	kvm_fpu.last_ip = C.__u64(state.LastIp)
	kvm_fpu.last_dp = C.__u64(state.LastDp)
	for i := 0; i < len(state.XMM); i += 1 {
		for j := 0; j < len(state.XMM[i]); j += 1 {
			kvm_fpu.xmm[i][j] = C.__u8(state.XMM[i][j])
		}
	}
	kvm_fpu.mxcsr = C.__u32(state.MXCSR)

	// Execute the ioctl.
	_, _, e := syscall.Syscall(
		syscall.SYS_IOCTL,
		uintptr(vcpu.fd),
		uintptr(C.IoctlSetFpu),
		uintptr(unsafe.Pointer(&kvm_fpu)))
	if e != 0 {
		return e
	}

	return nil
}
Beispiel #2
0
// This command selects a device register (through the cmd byte), sends
// 1 to 31 bytes of data to it, and reads 1 to 31 bytes of data in return.
func (smb SMBus) Block_process_call(cmd byte, buf []byte) ([]byte, error) {
	smb.Set_addr(smb.addr)
	ret, err := C.i2c_smbus_block_process_call(C.int(smb.bus.Fd()), C.__u8(cmd), C.__u8(len(buf)), ((*C.__u8)(&buf[0])))
	if err != nil {
		return nil, err
	} else {
		return buf[:ret], nil
	}
}
Beispiel #3
0
// This command selects a device register (through the cmd byte), sends
// 16 bits of data to it, and reads 16 bits of data in return.
func (smb SMBus) Process_call(cmd byte, value uint16) (uint16, error) {
	smb.Set_addr(smb.addr)
	ret, err := C.i2c_smbus_process_call(C.int(smb.bus.Fd()), C.__u8(cmd), C.__u16(value))
	if err != nil {
		ret = 0
	}
	return uint16(ret & 0x0FFFF), err
}
Beispiel #4
0
// This operation is very like Read Byte; again, data is read from a
// device, from a designated register that is specified through the cmd
// byte. But this time, the data is a complete word (16 bits).
func (smb *SMBus) Read_word_data(cmd byte) (uint16, error) {
	smb.Set_addr(smb.addr)
	ret, err := C.i2c_smbus_read_word_data(C.int(smb.bus.Fd()), C.__u8(cmd))
	if err != nil {
		ret = 0
	}
	return uint16(ret & 0x0FFFF), err
}
Beispiel #5
0
// Reads a single byte from a device, from a designated register.
// The register is specified through the cmd byte
func (smb SMBus) Read_byte_data(cmd byte) (byte, error) {
	smb.Set_addr(smb.addr)
	ret, err := C.i2c_smbus_read_byte_data(C.int(smb.bus.Fd()), C.__u8(cmd))
	if err != nil {
		ret = 0
	}
	return byte(ret & 0x0FF), err
}
Beispiel #6
0
// This command reads a block of up to 32 bytes from a device, from a
// designated register that is specified through the cmd byte. The amount
// of data in byte is specified by the length of the buf slice.
// To read 4 bytes of data, pass a slice created like this: make([]byte, 4)
func (smb SMBus) Read_block_data(cmd byte, buf []byte) (int, error) {
	smb.Set_addr(smb.addr)
	ret, err := C.i2c_smbus_read_block_data(
		C.int(smb.bus.Fd()),
		C.__u8(cmd),
		(*C.__u8)(unsafe.Pointer(&buf[0])),
	)
	return int(ret), err
}
func (vcpu *Vcpu) Translate(
	vaddr Vaddr) (Paddr, bool, bool, bool, error) {

	// Perform the translation.
	var translation C.struct_kvm_translation
	translation.linear_address = C.__u64(vaddr)
	_, _, e := syscall.Syscall(
		syscall.SYS_IOCTL,
		uintptr(vcpu.fd),
		uintptr(C.IoctlTranslate),
		uintptr(unsafe.Pointer(&translation)))
	if e != 0 {
		return Paddr(0), false, false, false, e
	}

	paddr := Paddr(translation.physical_address)
	valid := translation.valid != C.__u8(0)
	writeable := translation.writeable != C.__u8(0)
	usermode := translation.valid != C.__u8(0)

	return paddr, valid, writeable, usermode, nil
}
Beispiel #8
0
func (i2c *I2C) smbusAccess(readWrite, register uint8, size int, data unsafe.Pointer) (uintptr, error) {
	args := C.struct_i2c_smbus_ioctl_data{
		read_write: C.char(readWrite),
		command:    C.__u8(register),
		size:       C.int(size),
		data:       (*C.union_i2c_smbus_data)(data),
	}
	result, _, errno := syscall.Syscall(syscall.SYS_IOCTL, i2c.file.Fd(), C.I2C_SMBUS, uintptr(unsafe.Pointer(&args)))
	if int(result) == -1 {
		return 0, errno
	}
	return result, nil
}
func (vcpu *Vcpu) GetEvents() (Events, error) {

	// Execute the ioctl.
	var kvm_events C.struct_kvm_vcpu_events
	_, _, e := syscall.Syscall(
		syscall.SYS_IOCTL,
		uintptr(vcpu.fd),
		uintptr(C.IoctlGetVcpuEvents),
		uintptr(unsafe.Pointer(&kvm_events)))
	if e != 0 {
		return Events{}, e
	}

	// Prepare our state.
	events := Events{
		NmiPending: kvm_events.nmi.pending != C.__u8(0),
		NmiMasked:  kvm_events.nmi.masked != C.__u8(0),
		SipiVector: uint32(kvm_events.sipi_vector),
		Flags:      uint32(kvm_events.flags),
	}
	if kvm_events.exception.injected != C.__u8(0) {
		events.Exception = &ExceptionEvent{
			Number: uint8(kvm_events.exception.nr),
		}
		if kvm_events.exception.has_error_code != C.__u8(0) {
			error_code := uint32(kvm_events.exception.error_code)
			events.Exception.ErrorCode = &error_code
		}
	}
	if kvm_events.interrupt.injected != C.__u8(0) {
		events.Interrupt = &InterruptEvent{
			Number: uint8(kvm_events.interrupt.nr),
			Soft:   kvm_events.interrupt.soft != C.__u8(0),
			Shadow: kvm_events.interrupt.shadow != C.__u8(0),
		}
	}

	return events, nil
}
Beispiel #10
0
func (vcpu *Vcpu) SetSegment(
	seg Segment,
	val SegmentValue,
	sync bool) error {

	err := vcpu.refreshSRegs(true)
	if err != nil {
		return err
	}

	switch seg {
	case CS:
		vcpu.sregs.cs.base = C.__u64(val.Base)
		vcpu.sregs.cs.limit = C.__u32(val.Limit)
		vcpu.sregs.cs.selector = C.__u16(val.Selector)
		vcpu.sregs.cs._type = C.__u8(val.Type)
		vcpu.sregs.cs.present = C.__u8(val.Present)
		vcpu.sregs.cs.dpl = C.__u8(val.Dpl)
		vcpu.sregs.cs.db = C.__u8(val.Db)
		vcpu.sregs.cs.s = C.__u8(val.S)
		vcpu.sregs.cs.l = C.__u8(val.L)
		vcpu.sregs.cs.g = C.__u8(val.G)
		vcpu.sregs.cs.avl = C.__u8(val.Avl)
		vcpu.sregs.cs.unusable = C.__u8(^val.Present & 0x1)
	case DS:
		vcpu.sregs.ds.base = C.__u64(val.Base)
		vcpu.sregs.ds.limit = C.__u32(val.Limit)
		vcpu.sregs.ds.selector = C.__u16(val.Selector)
		vcpu.sregs.ds._type = C.__u8(val.Type)
		vcpu.sregs.ds.present = C.__u8(val.Present)
		vcpu.sregs.ds.dpl = C.__u8(val.Dpl)
		vcpu.sregs.ds.db = C.__u8(val.Db)
		vcpu.sregs.ds.s = C.__u8(val.S)
		vcpu.sregs.ds.l = C.__u8(val.L)
		vcpu.sregs.ds.g = C.__u8(val.G)
		vcpu.sregs.ds.avl = C.__u8(val.Avl)
		vcpu.sregs.ds.unusable = C.__u8(^val.Present & 0x1)
	case ES:
		vcpu.sregs.es.base = C.__u64(val.Base)
		vcpu.sregs.es.limit = C.__u32(val.Limit)
		vcpu.sregs.es.selector = C.__u16(val.Selector)
		vcpu.sregs.es._type = C.__u8(val.Type)
		vcpu.sregs.es.present = C.__u8(val.Present)
		vcpu.sregs.es.dpl = C.__u8(val.Dpl)
		vcpu.sregs.es.db = C.__u8(val.Db)
		vcpu.sregs.es.s = C.__u8(val.S)
		vcpu.sregs.es.l = C.__u8(val.L)
		vcpu.sregs.es.g = C.__u8(val.G)
		vcpu.sregs.es.avl = C.__u8(val.Avl)
		vcpu.sregs.es.unusable = C.__u8(^val.Present & 0x1)
	case FS:
		vcpu.sregs.fs.base = C.__u64(val.Base)
		vcpu.sregs.fs.limit = C.__u32(val.Limit)
		vcpu.sregs.fs.selector = C.__u16(val.Selector)
		vcpu.sregs.fs._type = C.__u8(val.Type)
		vcpu.sregs.fs.present = C.__u8(val.Present)
		vcpu.sregs.fs.dpl = C.__u8(val.Dpl)
		vcpu.sregs.fs.db = C.__u8(val.Db)
		vcpu.sregs.fs.s = C.__u8(val.S)
		vcpu.sregs.fs.l = C.__u8(val.L)
		vcpu.sregs.fs.g = C.__u8(val.G)
		vcpu.sregs.fs.avl = C.__u8(val.Avl)
		vcpu.sregs.fs.unusable = C.__u8(^val.Present & 0x1)
	case GS:
		vcpu.sregs.gs.base = C.__u64(val.Base)
		vcpu.sregs.gs.limit = C.__u32(val.Limit)
		vcpu.sregs.gs.selector = C.__u16(val.Selector)
		vcpu.sregs.gs._type = C.__u8(val.Type)
		vcpu.sregs.gs.present = C.__u8(val.Present)
		vcpu.sregs.gs.dpl = C.__u8(val.Dpl)
		vcpu.sregs.gs.db = C.__u8(val.Db)
		vcpu.sregs.gs.s = C.__u8(val.S)
		vcpu.sregs.gs.l = C.__u8(val.L)
		vcpu.sregs.gs.g = C.__u8(val.G)
		vcpu.sregs.gs.avl = C.__u8(val.Avl)
		vcpu.sregs.gs.unusable = C.__u8(^val.Present & 0x1)
	case SS:
		vcpu.sregs.ss.base = C.__u64(val.Base)
		vcpu.sregs.ss.limit = C.__u32(val.Limit)
		vcpu.sregs.ss.selector = C.__u16(val.Selector)
		vcpu.sregs.ss._type = C.__u8(val.Type)
		vcpu.sregs.ss.present = C.__u8(val.Present)
		vcpu.sregs.ss.dpl = C.__u8(val.Dpl)
		vcpu.sregs.ss.db = C.__u8(val.Db)
		vcpu.sregs.ss.s = C.__u8(val.S)
		vcpu.sregs.ss.l = C.__u8(val.L)
		vcpu.sregs.ss.g = C.__u8(val.G)
		vcpu.sregs.ss.avl = C.__u8(val.Avl)
		vcpu.sregs.ss.unusable = C.__u8(^val.Present & 0x1)
	case TR:
		vcpu.sregs.tr.base = C.__u64(val.Base)
		vcpu.sregs.tr.limit = C.__u32(val.Limit)
		vcpu.sregs.tr.selector = C.__u16(val.Selector)
		vcpu.sregs.tr._type = C.__u8(val.Type)
		vcpu.sregs.tr.present = C.__u8(val.Present)
		vcpu.sregs.tr.dpl = C.__u8(val.Dpl)
		vcpu.sregs.tr.db = C.__u8(val.Db)
		vcpu.sregs.tr.s = C.__u8(val.S)
		vcpu.sregs.tr.l = C.__u8(val.L)
		vcpu.sregs.tr.g = C.__u8(val.G)
		vcpu.sregs.tr.avl = C.__u8(val.Avl)
		vcpu.sregs.tr.unusable = C.__u8(^val.Present & 0x1)
	case LDT:
		vcpu.sregs.ldt.base = C.__u64(val.Base)
		vcpu.sregs.ldt.limit = C.__u32(val.Limit)
		vcpu.sregs.ldt.selector = C.__u16(val.Selector)
		vcpu.sregs.ldt._type = C.__u8(val.Type)
		vcpu.sregs.ldt.present = C.__u8(val.Present)
		vcpu.sregs.ldt.dpl = C.__u8(val.Dpl)
		vcpu.sregs.ldt.db = C.__u8(val.Db)
		vcpu.sregs.ldt.s = C.__u8(val.S)
		vcpu.sregs.ldt.l = C.__u8(val.L)
		vcpu.sregs.ldt.g = C.__u8(val.G)
		vcpu.sregs.ldt.avl = C.__u8(val.Avl)
		vcpu.sregs.ldt.unusable = C.__u8(^val.Present & 0x1)
	default:
		return UnknownRegister
	}

	if sync {
		err = vcpu.flushSRegs()
		if err != nil {
			return err
		}
	}

	return nil
}
func SetupLinuxBootParams(
	model *machine.Model,
	boot_params_data []byte,
	orig_boot_params_data []byte,
	cmdline_addr platform.Paddr,
	initrd_addr platform.Paddr,
	initrd_len uint64) error {

	// Grab a reference to our boot params struct.
	boot_params := (*C.struct_boot_params)(unsafe.Pointer(&boot_params_data[0]))

	// The setup header.
	// First step is to copy the existing setup_header
	// out of the given kernel image. We copy only the
	// header, and not the rest of the setup page.
	setup_start := 0x01f1
	setup_end := 0x0202 + int(orig_boot_params_data[0x0201])
	if setup_end > platform.PageSize {
		return InvalidSetupHeader
	}
	C.memcpy(
		unsafe.Pointer(&boot_params_data[setup_start]),
		unsafe.Pointer(&orig_boot_params_data[setup_start]),
		C.size_t(setup_end-setup_start))

	// Setup our BIOS memory map.
	// NOTE: We have to do this via C bindings. This is really
	// annoying, but basically because of the unaligned structures
	// in the struct_boot_params, the Go code generated here is
	// actually *incompatible* with the actual C layout.

	// First, the count.
	C.e820_set_count(boot_params, C.int(len(model.MemoryMap)))

	// Then, fill out the region information.
	for index, region := range model.MemoryMap {

		var memtype C.int
		switch region.MemoryType {
		case machine.MemoryTypeUser:
			memtype = C.E820Ram
		case machine.MemoryTypeReserved:
			memtype = C.E820Reserved
		case machine.MemoryTypeSpecial:
			memtype = C.E820Reserved
		case machine.MemoryTypeAcpi:
			memtype = C.E820Acpi
		}

		C.e820_set_region(
			boot_params,
			C.int(index),
			C.__u64(region.Start),
			C.__u64(region.Size),
			C.__u8(memtype))
	}

	// Set necessary setup header bits.
	C.set_header(
		boot_params,
		C.__u64(initrd_addr),
		C.__u64(initrd_len),
		C.__u64(cmdline_addr))

	// All done!
	return nil
}
Beispiel #12
0
// Sends a single bit to the device, at the place of the Rd/Wr bit.
func (smb SMBus) Write_quick(value byte) error {
	smb.Set_addr(smb.addr)
	_, err := C.i2c_smbus_write_quick(C.int(smb.bus.Fd()), C.__u8(value))
	return err
}
Beispiel #13
0
// Block write method for devices without SMBus support. Uses plain i2c interface
func (smb SMBus) Write_i2c_block_data(cmd byte, buf []byte) (int, error) {
	smb.Set_addr(smb.addr)
	ret, err := C.i2c_smbus_write_i2c_block_data(C.int(smb.bus.Fd()), C.__u8(cmd), C.__u8(len(buf)), ((*C.__u8)(&buf[0])))
	return int(ret), err
}
Beispiel #14
0
// This is the opposite of the Read Word operation. 16 bits
// of data is written to a device, to the designated register that is
// specified through the cmd byte.
func (smb SMBus) Write_word_data(cmd byte, value uint16) error {
	smb.Set_addr(smb.addr)
	_, err := C.i2c_smbus_write_word_data(C.int(smb.bus.Fd()), C.__u8(cmd), C.__u16(value))
	return err
}
func (vcpu *Vcpu) SetEvents(events Events) error {

	// Prepare our state.
	var kvm_events C.struct_kvm_vcpu_events

	if events.NmiPending {
		kvm_events.nmi.pending = C.__u8(1)
	} else {
		kvm_events.nmi.pending = C.__u8(0)
	}
	if events.NmiMasked {
		kvm_events.nmi.masked = C.__u8(1)
	} else {
		kvm_events.nmi.masked = C.__u8(0)
	}

	kvm_events.sipi_vector = C.__u32(events.SipiVector)
	kvm_events.flags = C.__u32(events.Flags)

	if events.Exception != nil {
		kvm_events.exception.injected = C.__u8(1)
		kvm_events.exception.nr = C.__u8(events.Exception.Number)
		if events.Exception.ErrorCode != nil {
			kvm_events.exception.has_error_code = C.__u8(1)
			kvm_events.exception.error_code = C.__u32(*events.Exception.ErrorCode)
		} else {
			kvm_events.exception.has_error_code = C.__u8(0)
			kvm_events.exception.error_code = C.__u32(0)
		}
	} else {
		kvm_events.exception.injected = C.__u8(0)
		kvm_events.exception.nr = C.__u8(0)
		kvm_events.exception.has_error_code = C.__u8(0)
		kvm_events.exception.error_code = C.__u32(0)
	}
	if events.Interrupt != nil {
		kvm_events.interrupt.injected = C.__u8(1)
		kvm_events.interrupt.nr = C.__u8(events.Interrupt.Number)
		if events.Interrupt.Soft {
			kvm_events.interrupt.soft = C.__u8(1)
		} else {
			kvm_events.interrupt.soft = C.__u8(0)
		}
		if events.Interrupt.Shadow {
			kvm_events.interrupt.shadow = C.__u8(1)
		} else {
			kvm_events.interrupt.shadow = C.__u8(0)
		}
	} else {
		kvm_events.interrupt.injected = C.__u8(0)
		kvm_events.interrupt.nr = C.__u8(0)
		kvm_events.interrupt.soft = C.__u8(0)
		kvm_events.interrupt.shadow = C.__u8(0)
	}

	// Execute the ioctl.
	_, _, e := syscall.Syscall(
		syscall.SYS_IOCTL,
		uintptr(vcpu.fd),
		uintptr(C.IoctlSetVcpuEvents),
		uintptr(unsafe.Pointer(&kvm_events)))
	if e != 0 {
		return e
	}

	return nil
}