Public Member Functions |
char * | map_self (Utcb *utcb, unsigned long physmem, unsigned long size, unsigned rights, bool frame=false) |
char * | map_string (Utcb *utcb, unsigned long src) |
| Command lines need to be mapped.
|
bool | attach_irq (unsigned gsi, unsigned cap_sm, bool unlocked, phy_cpu_no cpunr, char const *_name=0) |
void * | get_config_space (uint16 rid) |
| Returns a pointer to the memory-mapped config space of a PCI device.
|
unsigned | attach_msi (MessageHostOp *msg, phy_cpu_no cpunr) |
template<class CONSUMER , class PRODUCER > |
void | handle_attach (ModuleInfo *modinfo, PRODUCER &res, Utcb *utcb) |
| Handle an attach request.
|
void | postinit (Hip *hip) |
unsigned | create_host_devices (Utcb *utcb, Hip *hip) |
| Create the needed host devices aka instantiate the drivers.
|
unsigned | alloc_crd () |
| Prepare UTCB for receiving a new cap.
|
unsigned long | exception_handler_address (unsigned vector) |
unsigned | create_worker_threads (Hip *hip, phy_cpu_no cpunr) |
| Create exception and startup handling portals.
|
unsigned | __attribute__ ((noinline)) preinit(Utcb *utcb |
| Init the pager, console and map initial resources.
|
unsigned Hip *hip | Logging::init (putc, 0) |
| Logging::printf ("s0: preinit %p\n\n", hip) |
| check1 (1, init(hip)) |
| assert (_cap_start==0 &&_cap_order==16) |
| assert (reserve and reserve->virt<=CLIENT_PT_OFFSET and reserve->size-(reserve->virt-CLIENT_PT_OFFSET) >=(1<< (CLIENT_PT_ORDER+1))) |
_cap_region | del (Region(CLIENT_PT_OFFSET, 1U<< (CLIENT_PT_ORDER+1))) |
| assert (!_cap_region.find(CLIENT_PT_OFFSET)&&!_cap_region.find(CLIENT_PT_OFFSET+(1U<< CLIENT_PT_ORDER)-1U)) |
| assert (!_cap_region.find(CLIENT_PT_OFFSET+(2U<< CLIENT_PT_ORDER)-1U)) |
| assert (!_cap_region.find(0)) |
| assert (!_cap_region.find(ParentProtocol::CAP_PT_PERCPU-1U)) |
| assert (!_cap_region.find(ParentProtocol::CAP_PT_PERCPU+Config::MAX_CPUS-1U)) |
| Logging::printf ("s0: create locks\n") |
| check1 (2, nova_create_sm(_lock_gsi.sm())||nova_create_sm(_lock_mem.sm())) |
_lock_mem | up () |
| Logging::printf ("s0: create pf echo+worker threads\n") |
| check1 (3, create_worker_threads(hip, utcb->head.nul_cpunr)) |
| Logging::printf ("s0: map vga memory\n") |
| memcpy (_vga+0x1a000, _vga+0x18000, 0x1000) |
putcd sem | up () |
| check1 (6, nova_create_sm(putcd.sem.sm())) |
| Logging::init (putc,&putcd) |
| check1 (7, nova_create_sm(CLIENT_PT_OFFSET+ParentProtocol::CAP_PARENT_ID)) |
| Utcb::TypedMapCap (CLIENT_PT_OFFSET+ParentProtocol::CAP_PARENT_ID, DESC_CAP_ALL, ParentProtocol::CAP_PARENT_ID).fill_words(utcb->msg) |
*utcb<< Crd(0,
31, DESC_CAP_ALL);utcb-> | set_header (2, 0) |
| for (unsigned gsi=0;gsi< hip->cfg_gsi;gsi++) |
| check1 (8, nova_call(_percpu[utcb->head.nul_cpunr].cap_pt_echo)) |
*utcb<< Crd(0, 0, 0);utcb-> | reset () |
unsigned | init_memmap (Utcb *utcb) |
| Init the memory map from the Hip.
|
void | free_module (ModuleInfo *modinfo) |
ModuleInfo * | get_module (unsigned id) |
ModuleInfo * | alloc_module (char const *cmdline, unsigned sigma0_cmdlen, bool s0_reserved=false) |
unsigned | boot_s0_services (Utcb *utcb) |
unsigned | start_config (Utcb *utcb, unsigned short which, unsigned &internal_id) |
| Starts a configuration loaded during boottime.
|
unsigned | start_config (Utcb *utcb, char const *mconfig, unsigned &internal_id, unsigned &sc_usage_cap, unsigned long &usage_mem, bool bswitch, bool part_of_s0=false) |
| Start a configuration from a stable memory region (mconfig).
|
bool | idle_sc_sanity_check (unsigned pt) |
bool | map_idle_scs (Utcb *utcb, unsigned pt) |
bool | map_exc_pts (const ModuleInfo *modinfo, unsigned pt) |
unsigned | _start_config (Utcb *utcb, char *elf, unsigned long mod_size, char const *client_cmdline, ModuleInfo *modinfo, unsigned &sc_usage_cap, bool bswitch) |
unsigned | kill_module (ModuleInfo *modinfo) |
| Kill the given module.
|
bool | assign_pci_device (unsigned pd_cap, unsigned bdf, unsigned hint) |
| Assign a PCI device to a PD.
|
NORETURN void | internal_error (unsigned pid, Utcb *utcb) |
| PT_FUNC (do_breakpoint, if(consolesem) consolesem->up();Logging::printf(">>> Break EIP %08x ESP %08x EFLAGS %08x\n", utcb->eip, utcb->esp, utcb->efl);if(consolesem) consolesem->down();) PT_FUNC(do_singlestep |
| if (consolesem) consolesem->up() |
| Logging::printf (">>> Step EIP %08x ESP %08x EFLAGS %08x\n", utcb->eip, utcb->esp, utcb->efl) |
| if (consolesem) consolesem->down() |
| PT_FUNC (do_recall, utcb->efl^=0x100;Logging::printf("RECALL EFLAGS %08x EIP %08x\n", utcb->efl, utcb->eip);utcb->mtd=MTD_RFLAGS;) PT_FUNC(do_map |
| assert (~utcb->head.untyped &1) |
utcb | set_header (0, utcb->head.untyped/2) |
| memmove (utcb->item_start(), utcb->msg, sizeof(unsigned)*utcb->head.typed *2) |
| PT_FUNC_NORETURN (do_gsi, unsigned char res;unsigned gsi=utcb->msg[1]&0xff;bool shared=(utcb->msg[1] >> 8)&1;bool locked=!(utcb->msg[1]&0x200);unsigned cap_irq=utcb->msg[0];MessageIrq msg(shared?MessageIrq::ASSERT_NOTIFY:MessageIrq::ASSERT_IRQ, gsi);while(!(res=nova_semdownmulti(cap_irq))){COUNTER_INC("GSI");if(locked) _lock_gsi.down();_mb->bus_hostirq.send(msg);if(locked) _lock_gsi.up();}Logging::panic("s0: %s(%x, %x) request failed with %x\n", __func__, gsi, cap_irq, res);) PT_FUNC(do_startup |
| Handle startup exception of spawned childs.
|
| assert (modinfo) |
bool | translate_client_fault (ModuleInfo *modinfo, mword fault, mword err, mword &translated, mword &begin, mword &size, unsigned &rights) |
| Translate a page fault (given by fault and err) into a memory region [begin, begin+size).
|
| PT_FUNC (do_request, ModuleInfo *modinfo=get_module((pid-CLIENT_PT_OFFSET) >> CLIENT_PT_SHIFT);assert(modinfo);COUNTER_INC("request");if(utcb->head.untyped==EXCEPTION_WORDS){assert(MEM_OFFSET+modinfo->physsize<=CLIENT_BOOT_UTCB);LOG_VERBOSE("s0: [%2u, %02x] pagefault %x/%x for %llx err %llx at %x\n", modinfo->id, pid, utcb->head.untyped, utcb->head.typed, utcb->qual[1], utcb->qual[0], utcb->eip);mword fault=utcb->qual[1];mword begin;mword size;mword translated;unsigned rights;if(not translate_client_fault(modinfo, fault, utcb->qual[0], translated, begin, size, rights)){Logging::printf("s0: [%2u, %02x] pagefault %x/%x for %llx err %llx at %x\n", modinfo->id, pid, utcb->head.untyped, utcb->head.typed, utcb->qual[1], utcb->qual[0], utcb->eip);Logging::printf("s0: [%2u] unresolvable pagefault - killing client ...\n", modinfo->id);utcb->reset();kill_module(modinfo);return;}assert((begin<=translated)&&(translated< (begin+size)));const mword page_mask=((1UL<< Utcb::MINSHIFT)-1);assert((size >=0x1000) and((begin &page_mask)==0));unsigned order=Cpu::maxalign(translated-begin, begin, fault-(translated-begin), size);LOG_VERBOSE("s0: [%2u, %02x] %lx %lx+%lx -> order %u: %lx+%lx\n", modinfo->id, pid, translated, begin, size, order, translated &~((1UL<< order)-1), 1UL<< order);assert(order >=Utcb::MINSHIFT);assert((1UL<< order)<=size);mword aligned_begin=translated &~((1UL<< order)-1);const Crd region=Crd(aligned_begin >> Utcb::MINSHIFT, order-Utcb::MINSHIFT, rights);if(utcb->qual[0]&1){Logging::printf("s0: potential overmap. revoke!\n");nova_revoke(region, false);}utcb->reset();*utcb<< Utcb::TypedMapCap(region,(fault &~page_mask));utcb->set_header(0, 0);if((utcb->qual[1]&CLIENT_HIP)==CLIENT_HIP){unsigned long rest=utcb->add_mappings(reinterpret_cast< unsigned long >(modinfo->hip), 0x1000, CLIENT_HIP|MAP_MAP, DESC_MEM_ALL);assert(!rest);}else{unsigned long rest=utcb->add_mappings(reinterpret_cast< unsigned long >(modinfo->mem), modinfo->physsize, MEM_OFFSET|MAP_MAP, DESC_MEM_ALL);if(rest){utcb->set_header(0, 0);unsigned long offset=(utcb->qual[1]&~((1UL<< Utcb::MINSHIFT)-1))-MEM_OFFSET;rest=utcb->add_mappings(reinterpret_cast< unsigned long >(modinfo->mem)+offset, 1UL<< Utcb::MINSHIFT,(MEM_OFFSET+offset)|MAP_MAP, DESC_MEM_ALL);assert(!rest);}}LOG_VERBOSE("s0: [%2u, %02x] map %x/%x for %llx err %llx at %x\n", modinfo->id, pid, utcb->head.untyped, utcb->head.typed, utcb->qual[1], utcb->qual[0], utcb->eip);return;}SemaphoreGuard l(_lock_gsi);if(request_pcicfg(modinfo->id, utcb)) return;if(!request_disks(modinfo, utcb)&&!request_console(modinfo, utcb)&&!request_network(modinfo, utcb)) switch(utcb->msg[0]){case REQUEST_HOSTOP:{MessageHostOp *msg=reinterpret_cast< MessageHostOp * >(utcb->msg+1);if(utcb->head.untyped *sizeof(unsigned)< sizeof(unsigned)+sizeof(*msg)) goto fail;switch(msg->type){case MessageHostOp::OP_GET_MAC:msg->mac=get_mac(modinfo->mac++*MAXMODULES+modinfo->id);utcb->msg[0]=0;break;case MessageHostOp::OP_ASSIGN_PCI:if(modinfo->dma){if(assign_pci_device(NOVA_DEFAULT_PD_CAP+(modinfo->id<< CLIENT_PT_SHIFT)+CLIENT_PT_OFFSET, msg->value, msg->len)) utcb->msg[0]=0;else goto fail;}else{Logging::printf("s0: [%2u] DMA access denied.\n", modinfo->id);goto fail;}break;case MessageHostOp::OP_ATTACH_IRQ:if((msg->value &0xff)< _hip->cfg_gsi){unsigned gsi_cap=_irq_cap_base+(msg->value &0xff);unsigned res=nova_assign_gsi(gsi_cap, modinfo->cpunr);if(res!=NOVA_ESUCCESS) goto fail;Logging::printf("s0: [%2u] gsi %lx granted\n", modinfo->id, msg->value);utcb->set_header(1, 0);utcb->msg[0]=utcb->add_mappings(gsi_cap<< Utcb::MINSHIFT, 1<< Utcb::MINSHIFT, MAP_MAP, DESC_CAP_ALL);if(utcb->msg[0]) goto fail;}else{Logging::printf("s0: [%2u] irq request dropped %x nr %x\n", modinfo->id, utcb->msg[2], utcb->msg[2] >> Utcb::MINSHIFT);goto fail;}break;case MessageHostOp::OP_ATTACH_MSI:{if(msg->is_hpet){Logging::printf("s0: Client tried to map HPET MSI. He can do that himself!\n");goto fail;}unsigned cap=attach_msi(msg, modinfo->cpunr);if(!cap){Logging::printf("s0: [%2u] granting msi to cpu %u failed\n", modinfo->id, modinfo->cpunr);goto fail;}utcb->set_header(1+sizeof(*msg)/sizeof(unsigned), 0);unsigned long res=utcb->add_mappings(cap<< Utcb::MINSHIFT, 1<< Utcb::MINSHIFT, MAP_MAP, DESC_CAP_ALL);assert(res==0);utcb->msg[0]=0;Logging::printf("s0: [%2u] msi granted to cpu %u\n", modinfo->id, modinfo->cpunr);}break;case MessageHostOp::OP_ALLOC_IOIO_REGION:map_self(utcb,(msg->value >> 8)<< Utcb::MINSHIFT, 1<< (Utcb::MINSHIFT+msg->value &0xff), DESC_IO_ALL);utcb->set_header(1, 0);utcb->msg[0]=utcb->add_mappings((msg->value >> 8)<< Utcb::MINSHIFT,(1<< (Utcb::MINSHIFT+msg->value &0xff)), MAP_MAP, DESC_IO_ALL);if(utcb->msg[0]) goto fail;break;case MessageHostOp::OP_ALLOC_IOMEM:{unsigned long addr=msg->value &~0xffful;char *ptr=map_self(utcb, addr, msg->len, DESC_MEM_ALL);utcb->set_header(1, 0);utcb->msg[0]=utcb->add_mappings(reinterpret_cast< unsigned long >(ptr), msg->len, MAP_MAP, DESC_MEM_ALL);if(utcb->msg[0]==0) Logging::printf("s0: [%2u] iomem %lx+%lx granted from %p\n", modinfo->id, addr, msg->len, ptr);else{Logging::printf("s0: [%2u] iomem mapping failed.\n", modinfo->id);goto fail;}}break;case MessageHostOp::OP_ALLOC_SEMAPHORE:case MessageHostOp::OP_ALLOC_SERVICE_THREAD:case MessageHostOp::OP_ALLOC_SERVICE_PORTAL:case MessageHostOp::OP_GUEST_MEM:case MessageHostOp::OP_ALLOC_FROM_GUEST:case MessageHostOp::OP_VIRT_TO_PHYS:case MessageHostOp::OP_NOTIFY_IRQ:case MessageHostOp::OP_VCPU_CREATE_BACKEND:case MessageHostOp::OP_VCPU_BLOCK:case MessageHostOp::OP_VCPU_RELEASE:case MessageHostOp::OP_REGISTER_SERVICE:case MessageHostOp::OP_GET_MODULE:case MessageHostOp::OP_WAIT_CHILD:case MessageHostOp::OP_CREATE_EC4PT:default:Logging::printf("s0: [%2u] unknown request (%x,%x,%x) dropped \n", modinfo->id, utcb->msg[0], utcb->msg[1], utcb->msg[2]);goto fail;}}break;case REQUEST_ACPI:{MessageAcpi *msg=reinterpret_cast< MessageAcpi * >(utcb->msg+1);if(utcb->head.untyped *sizeof(unsigned)< sizeof(unsigned)+sizeof(*msg)) goto fail;if(msg->type==MessageAcpi::ACPI_GET_IRQ) utcb->msg[0]=!_mb->bus_acpi.send(*msg, true);}break;default:Logging::printf("s0: [%2u] unknown request (%x,%x,%x) dropped \n", modinfo->id, utcb->msg[0], utcb->msg[1], utcb->msg[2]);goto fail;}return;fail:utcb->msg[0]=~0x10u;utcb->set_header(1, 0);) bool receive(MessageHostOp &msg) |
| Handle child page-faults and "legacy call interface" requests.
|
void | init_network () |
bool | request_network (ModuleInfo *modinfo, Utcb *utcb) |
| Handle network requests from other PDs.
|
bool | receive (MessageNetwork &msg) |
void | init_disks () |
| Global init.
|
void | attach_drives (char const *cmdline, unsigned long cmdlen, unsigned client) |
| Attach drives to a module.
|
unsigned long | find_free_tag (unsigned short client, unsigned char disknr, unsigned long usertag, unsigned long &tag) |
| Find a free disk tag for a client.
|
bool | request_disks (ModuleInfo *modinfo, Utcb *utcb) |
| Handle disk requests from other PDs.
|
bool | receive (MessageDiskCommit &msg) |
void | init_console () |
| Init the console subsystem.
|
void | alloc_console (ModuleInfo const *modinfo, const char *cmdline, bool bswitch) |
void | switch_view (Motherboard *mb, int view, unsigned short consoleid) |
| Switch to our view.
|
bool | request_console (ModuleInfo *modinfo, Utcb *utcb) |
| Handle console requests from other PDs.
|
bool | receive (MessageConsole &msg) |
bool | request_pcicfg (unsigned client, Utcb *utcb) |
unsigned | generate_hostmac () |
| Generate a pseudo-random but persistent hostmac by hashing all PCI device IDs, their BDFs and the serial numbers of devices.
|
unsigned long long | get_mac (unsigned clientnr) |
| Return a MAC by adding the MAC-prefix, the host-MAC and a client specific number.
|
void | run (Utcb *utcb, Hip *hip) NORETURN |
| Sigma0 () |
| NovaProgram () |
| CapAllocator (unsigned long cap_, unsigned long cap_start, unsigned long cap_order) |
unsigned | alloc_cap (unsigned count=1) |
void | dealloc_cap (unsigned cap, unsigned count=1) |
| StaticReceiver () |
void | debug_dump () |
| Device (const char *debug_name) |