CAMLprim value ml_interface_get_server_features(value interface) { CAMLparam1(interface); struct xenstore_domain_interface *intf = GET_C_STRUCT(interface)->addr; CAMLreturn(Val_int (intf->server_features)); }
CAMLprim value stub_mmap_init(value fd, value pflag, value mflag, value len, value offset) { CAMLparam5(fd, pflag, mflag, len, offset); CAMLlocal1(result); int c_pflag, c_mflag; switch (Int_val(pflag)) { case 0: c_pflag = PROT_READ; break; case 1: c_pflag = PROT_WRITE; break; case 2: c_pflag = PROT_READ|PROT_WRITE; break; default: caml_invalid_argument("protectiontype"); } switch (Int_val(mflag)) { case 0: c_mflag = MAP_SHARED; break; case 1: c_mflag = MAP_PRIVATE; break; default: caml_invalid_argument("maptype"); } result = caml_alloc(sizeof(struct mmap_interface), Abstract_tag); if (mmap_interface_init(GET_C_STRUCT(result), Int_val(fd), c_pflag, c_mflag, Int_val(len), Int_val(offset))) caml_failwith("mmap"); CAMLreturn(result); }
CAMLprim value ml_interface_write(value ml_interface, value ml_buffer, value ml_len) { CAMLparam3(ml_interface, ml_buffer, ml_len); CAMLlocal1(ml_result); struct mmap_interface *interface = GET_C_STRUCT(ml_interface); char *buffer = String_val(ml_buffer); int len = Int_val(ml_len); int result; struct xenstore_domain_interface *intf = interface->addr; XENSTORE_RING_IDX cons, prod; int total_space, space; uint32_t connection; cons = *(volatile uint32_t*)&intf->rsp_cons; prod = *(volatile uint32_t*)&intf->rsp_prod; connection = *(volatile uint32_t*)&intf->connection; if (connection != XENSTORE_CONNECTED) caml_raise_constant(*caml_named_value("Xb.Reconnect")); xen_mb(); if ((prod - cons) > XENSTORE_RING_SIZE) caml_failwith("bad connection"); /* Check for space to write the full message. */ total_space = XENSTORE_RING_SIZE - (prod - cons); if (total_space == 0) { /* No space at all - exit having done nothing. */ result = 0; goto exit; } else if (total_space < len) /* Some space - make a partial write. */ len = total_space; /* Check for space until the ring wraps. */ space = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod); if (len < space) /* Message fits inside the remaining part of the ring. */ memcpy(intf->rsp + MASK_XENSTORE_IDX(prod), buffer, len); else { /* Message wraps around the end of the ring. Write both halves. */ memcpy(intf->rsp + MASK_XENSTORE_IDX(prod), buffer, space); memcpy(intf->rsp, buffer + space, len - space); } xen_mb(); intf->rsp_prod += len; result = len; exit: ml_result = Val_int(result); CAMLreturn(ml_result); }
CAMLprim value ml_interface_read(value ml_interface, value ml_buffer, value ml_len) { CAMLparam3(ml_interface, ml_buffer, ml_len); CAMLlocal1(ml_result); struct mmap_interface *interface = GET_C_STRUCT(ml_interface); char *buffer = String_val(ml_buffer); int len = Int_val(ml_len); int result; struct xenstore_domain_interface *intf = interface->addr; XENSTORE_RING_IDX cons, prod; /* offsets only */ int total_data, data; uint32_t connection; cons = *(volatile uint32_t*)&intf->req_cons; prod = *(volatile uint32_t*)&intf->req_prod; connection = *(volatile uint32_t*)&intf->connection; if (connection != XENSTORE_CONNECTED) caml_raise_constant(*caml_named_value("Xb.Reconnect")); xen_mb(); if ((prod - cons) > XENSTORE_RING_SIZE) caml_failwith("bad connection"); /* Check for any pending data at all. */ total_data = prod - cons; if (total_data == 0) { /* No pending data at all. */ result = 0; goto exit; } else if (total_data < len) /* Some data - make a partial read. */ len = total_data; /* Check whether data crosses the end of the ring. */ data = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons); if (len < data) /* Data within the remaining part of the ring. */ memcpy(buffer, intf->req + MASK_XENSTORE_IDX(cons), len); else { /* Data crosses the ring boundary. Read both halves. */ memcpy(buffer, intf->req + MASK_XENSTORE_IDX(cons), data); memcpy(buffer + data, intf->req, len - data); } xen_mb(); intf->req_cons += len; result = len; exit: ml_result = Val_int(result); CAMLreturn(ml_result); }
CAMLprim value ml_interface_set_server_features(value interface, value v) { CAMLparam2(interface, v); struct xenstore_domain_interface *intf = GET_C_STRUCT(interface)->addr; intf->server_features = Int_val(v); CAMLreturn(Val_unit); }
CAMLprim value stub_mmap_final(value interface) { CAMLparam1(interface); struct mmap_interface *intf; intf = GET_C_STRUCT(interface); if (intf->addr != MAP_FAILED) munmap(intf->addr, intf->len); intf->addr = MAP_FAILED; CAMLreturn(Val_unit); }
CAMLprim value ml_interface_read(value ml_interface, value ml_buffer, value ml_len) { CAMLparam3(ml_interface, ml_buffer, ml_len); CAMLlocal1(ml_result); struct mmap_interface *interface = GET_C_STRUCT(ml_interface); char *buffer = String_val(ml_buffer); int len = Int_val(ml_len); int result; struct xenstore_domain_interface *intf = interface->addr; XENSTORE_RING_IDX cons, prod; /* offsets only */ int to_read; uint32_t connection; cons = *(volatile uint32_t*)&intf->req_cons; prod = *(volatile uint32_t*)&intf->req_prod; connection = *(volatile uint32_t*)&intf->connection; if (connection != XENSTORE_CONNECTED) caml_raise_constant(*caml_named_value("Xb.Reconnect")); xen_mb(); if ((prod - cons) > XENSTORE_RING_SIZE) caml_failwith("bad connection"); if (prod == cons) { result = 0; goto exit; } cons = MASK_XENSTORE_IDX(cons); prod = MASK_XENSTORE_IDX(prod); if (prod > cons) to_read = prod - cons; else to_read = XENSTORE_RING_SIZE - cons; if (to_read < len) len = to_read; memcpy(buffer, intf->req + cons, len); xen_mb(); intf->req_cons += len; result = len; exit: ml_result = Val_int(result); CAMLreturn(ml_result); }
CAMLprim value ml_interface_close(value interface) { CAMLparam1(interface); struct xenstore_domain_interface *intf = GET_C_STRUCT(interface)->addr; int i; intf->req_cons = intf->req_prod = intf->rsp_cons = intf->rsp_prod = 0; /* Ensure the unused space is full of invalid xenstore packets. */ for (i = 0; i < XENSTORE_RING_SIZE; i++) { intf->req[i] = 0xff; /* XS_INVALID = 0xffff */ intf->rsp[i] = 0xff; } xen_mb (); intf->connection = XENSTORE_CONNECTED; CAMLreturn(Val_unit); }
CAMLprim value ml_interface_write(value ml_interface, value ml_buffer, value ml_len) { CAMLparam3(ml_interface, ml_buffer, ml_len); CAMLlocal1(ml_result); struct mmap_interface *interface = GET_C_STRUCT(ml_interface); char *buffer = String_val(ml_buffer); int len = Int_val(ml_len); int result; struct xenstore_domain_interface *intf = interface->addr; XENSTORE_RING_IDX cons, prod; int can_write; uint32_t connection; cons = *(volatile uint32_t*)&intf->rsp_cons; prod = *(volatile uint32_t*)&intf->rsp_prod; connection = *(volatile uint32_t*)&intf->connection; if (connection != XENSTORE_CONNECTED) caml_raise_constant(*caml_named_value("Xb.Reconnect")); xen_mb(); if ( (prod - cons) >= XENSTORE_RING_SIZE ) { result = 0; goto exit; } if (MASK_XENSTORE_IDX(prod) >= MASK_XENSTORE_IDX(cons)) can_write = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod); else can_write = MASK_XENSTORE_IDX(cons) - MASK_XENSTORE_IDX(prod); if (can_write < len) len = can_write; memcpy(intf->rsp + MASK_XENSTORE_IDX(prod), buffer, len); xen_mb(); intf->rsp_prod += len; result = len; exit: ml_result = Val_int(result); CAMLreturn(ml_result); }
CAMLprim value stub_mmap_write(value interface, value data, value start, value len) { CAMLparam4(interface, data, start, len); struct mmap_interface *intf; int c_start; int c_len; c_start = Int_val(start); c_len = Int_val(len); intf = GET_C_STRUCT(interface); if (c_start > intf->len) caml_invalid_argument("start invalid"); if (c_start + c_len > intf->len) caml_invalid_argument("len invalid"); memcpy(intf->addr + c_start, (char *) data, c_len); CAMLreturn(Val_unit); }
CAMLprim value stub_mmap_read(value interface, value start, value len) { CAMLparam3(interface, start, len); CAMLlocal1(data); struct mmap_interface *intf; int c_start; int c_len; c_start = Int_val(start); c_len = Int_val(len); intf = GET_C_STRUCT(interface); if (c_start > intf->len) caml_invalid_argument("start invalid"); if (c_start + c_len > intf->len) caml_invalid_argument("len invalid"); data = caml_alloc_string(c_len); memcpy((char *) data, intf->addr + c_start, c_len); CAMLreturn(data); }