FreeNOS
CoreServer.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Niek Linnenbank
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <FreeNOS/User.h>
19 #include <ExecutableFormat.h>
20 #include <Lz4Decompressor.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <sys/stat.h>
24 #include <sys/wait.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include "CoreServer.h"
28 
29 const char * CoreServer::kernelPath = "/boot/kernel";
30 
33 {
34  m_numRegions = 0;
35  m_kernel = ZERO;
37  m_coreInfo = ZERO;
38 
39  m_cores = ZERO;
40  m_toMaster = ZERO;
42  m_toSlave = ZERO;
43  m_fromSlave = ZERO;
44 
45  // Register IPC handlers
47 
48  // Because of waitpid() we must send the reply manually before waitpid().
50 }
51 
53 {
54  CoreMessage msg;
55 
56  if (m_info.coreId == 0)
57  return run();
58 
59  while (true)
60  {
61  // wait from a message of the master core
62  receiveFromMaster(&msg);
63 
65  if (h)
66  {
67  const bool sendReply = h->sendReply;
68  (this->*h->exec) (&msg);
69 
70  if (sendReply)
71  {
72  sendToMaster(&msg);
73  }
74  }
75  else
76  {
77  ERROR("invalid action " << (int)msg.action << " from master");
78  }
79  }
80 }
81 
83 {
84  const Size maximumArguments = 64;
85  char cmd[128], *argv[maximumArguments], *arg = ZERO;
86  Memory::Range range;
87  API::Result result = API::Success;
88  Size argc = 0;
89 
90  if (m_info.coreId == 0)
91  {
92  // Find physical address for program buffer
93  range.virt = msg->programAddr;
94  if ((result = VMCtl(msg->from, LookupVirtual, &range)) != API::Success)
95  {
96  ERROR("failed to lookup virtual address at " <<
97  (void *) msg->programAddr << ": " << (int)result);
99  return;
100  }
101  msg->programAddr = range.phys;
102 
103  // Find physical address for command
104  range.virt = (Address) msg->programCmd;
105  if ((result = VMCtl(msg->from, LookupVirtual, &range)) != API::Success)
106  {
107  ERROR("failed to lookup virtual address at " <<
108  (void *) msg->programCmd << ": " << (int)result);
110  return;
111  }
112  msg->programCmd = (char *) range.phys;
113 
114  // Forward message to slave core
115  if (sendToSlave(msg->coreNumber, msg) != Core::Success)
116  {
117  ERROR("failed to write channel on core"<<msg->coreNumber);
118  msg->result = Core::IOError;
119  return;
120  }
121  DEBUG("creating program at phys " << (void *) msg->programAddr << " on core" << msg->coreNumber);
122 
123  // Wait until the slave created the program
124  if (receiveFromSlave(msg->coreNumber, msg) != Core::Success)
125  {
126  ERROR("failed to read channel on core" << msg->coreNumber);
127  msg->result = Core::IOError;
128  return;
129  }
130  DEBUG("program created with result " << (int)msg->result << " at core" << msg->coreNumber);
131  ChannelClient::instance()->syncSendTo(msg, sizeof(*msg), msg->from);
132  }
133  else
134  {
135  // Copy the program command
136  result = VMCopy(SELF, API::ReadPhys, (Address) cmd,
137  (Address) msg->programCmd, sizeof(cmd));
138  if (result != API::Success)
139  {
140  ERROR("failed to copy program command: result = " << (int) result);
142  sendToMaster(msg);
143  return;
144  }
145  // First argument points to start of command
146  arg = cmd;
147 
148  // Translate space separated command to argv[]
149  for (Size i = 0; i < sizeof(cmd) && argc < maximumArguments - 1; i++)
150  {
151  if (cmd[i] == ' ')
152  {
153  cmd[i] = 0;
154  argv[argc++] = arg;
155  arg = &cmd[i+1];
156  }
157  else if (cmd[i] == 0)
158  {
159  argv[argc++] = arg;
160  break;
161  }
162  }
163  // Mark end of the argument list
164  argv[argc] = 0;
165 
166  // Map the program buffer
167  range.phys = msg->programAddr;
168  range.virt = 0;
170  range.size = msg->programSize;
171  if ((result = VMCtl(SELF, MapContiguous, &range)) != API::Success)
172  {
173  ERROR("failed to map program data: " << (int)result);
174  msg->result = Core::IOError;
175  sendToMaster(msg);
176  return;
177  }
178 
179  int pid = spawn(range.virt, msg->programSize, (const char **)argv);
180  if (pid == -1)
181  {
182  ERROR("failed to spawn() program: " << pid);
183  msg->result = Core::IOError;
184  sendToMaster(msg);
185  }
186  else
187  {
188  // reply to master before calling waitpid()
189  msg->result = Core::Success;
190  sendToMaster(msg);
191  }
192 
193  if ((result = VMCtl(SELF, UnMap, &range)) != API::Success)
194  {
195  ERROR("failed to unmap program data: " << (int)result);
196  }
197 
198  // Wait until the spawned process completes
199  if (pid != -1)
200  {
201  int status;
202  waitpid((pid_t)pid, &status, 0);
203  }
204  }
205 }
206 
208 {
209  DEBUG("");
210 
211  if (m_info.coreId == 0)
212  {
213  if (m_cores)
214  msg->coreNumber = m_cores->getCores().count();
215  else
216  msg->coreNumber = 1;
217 
218  msg->result = Core::Success;
219  }
220  else
222 }
223 
225 {
226  const Size pingPongNumber = 0x12345678;
227 
228  if (m_info.coreId != 0)
229  {
230  CoreMessage msg;
233  msg.coreNumber = pingPongNumber;
234 
235  sendToMaster(&msg);
236  }
237  else if (m_cores != NULL)
238  {
239  CoreMessage msg;
240  Size numCores = m_cores->getCores().count();
241 
242  for (Size i = 1; i < numCores; i++)
243  {
244  receiveFromSlave(i, &msg);
245 
246  if (msg.action == Core::PongResponse && msg.coreNumber == pingPongNumber)
247  {
248  NOTICE("core" << i << " send a Pong");
249  }
250  else
251  {
252  ERROR("invalid message received from core" << i);
253  }
254  }
255  }
256 
257  return Core::Success;
258 }
259 
261 {
262  // Only core0 needs to start other coreservers
263  if (m_info.coreId != 0)
264  {
265  if (setupChannels() != Core::Success)
266  {
267  ERROR("failed to setup IPC channels");
268  return IOError;
269  }
270  else
271  {
272  return Success;
273  }
274  }
275 
276  if (loadKernel() != Core::Success)
277  {
278  ERROR("failed to load kernel program");
279  return IOError;
280  }
281 
282  if (discoverCores() != Core::Success)
283  {
284  ERROR("failed to discover cores");
285  return IOError;
286  }
287 
289  {
290  ERROR("failed to prepare CoreInfo data array");
291  return IOError;
292  }
293 
294  if (setupChannels() != Core::Success)
295  {
296  ERROR("failed to setup IPC channels");
297  return IOError;
298  }
299 
300  if (bootAll() != Core::Success)
301  {
302  ERROR("failed to boot all cores");
303  return IOError;
304  }
305 
306  if (unloadKernel() != Core::Success)
307  {
308  ERROR("failed to unload kernel program");
309  return IOError;
310  }
311 
312  return Success;
313 }
314 
316 {
317  struct stat st;
318  int fd, r;
319  API::Result result;
320 
321  DEBUG("Opening : " << kernelPath);
322 
323  // Stat the compressed program image
324  if ((r = stat(kernelPath, &st)) != 0)
325  {
326  ERROR("failed to stat() kernel on path: " << kernelPath <<
327  ": result " << r);
328  return Core::IOError;
329  }
330 
331  // Map memory buffer for the compressed program image
332  Memory::Range compressed;
333  compressed.virt = ZERO;
334  compressed.phys = ZERO;
335  compressed.size = st.st_size;
337 
338  // Allocate compressed memory buffer
339  result = VMCtl(SELF, MapContiguous, &compressed);
340  if (result != API::Success)
341  {
342  ERROR("failed to allocate compressed kernel image with VMCtl: result = " << (int) result);
343  return Core::IOError;
344  }
345 
346  // Open the file
347  if ((fd = open(kernelPath, O_RDONLY)) < 0)
348  {
349  ERROR("failed to open() kernel on path: " << kernelPath <<
350  ": result " << fd);
351  return Core::IOError;
352  }
353 
354  // Read the file
355  if ((r = read(fd, (void *) compressed.virt, st.st_size)) != st.st_size)
356  {
357  ERROR("failed to read() kernel on path: " << kernelPath <<
358  ": result " << r);
359  return Core::IOError;
360  }
361  close(fd);
362 
363  // Initialize decompressor
364  Lz4Decompressor lz4((void *)compressed.virt, st.st_size);
365  Lz4Decompressor::Result decompResult = lz4.initialize();
366  if (decompResult != Lz4Decompressor::Success)
367  {
368  ERROR("failed to initialize LZ4 decompressor: result = " << (int) decompResult);
369  return Core::IOError;
370  }
371 
372  // Map memory buffer for the uncompressed program image
377 
378  // Allocate uncompressed memory buffer
379  result = VMCtl(SELF, MapContiguous, &m_kernelImage);
380  if (result != API::Success)
381  {
382  ERROR("failed to allocate kernel image with VMCtl: result = " << (int) result);
383  return Core::IOError;
384  }
385 
386  // Decompress the kernel program
387  decompResult = lz4.read((void *)m_kernelImage.virt, lz4.getUncompressedSize());
388  if (decompResult != Lz4Decompressor::Success)
389  {
390  ERROR("failed to decompress kernel image: result = " << (int) decompResult);
391  return Core::IOError;
392  }
393 
394  // Attempt to read executable format
396  if (execResult != ExecutableFormat::Success)
397  {
398  ERROR("failed to find ExecutableFormat of kernel on path: " << kernelPath <<
399  ": result " << (int) execResult);
400  return Core::ExecError;
401  }
402 
403  // Retrieve memory regions
404  m_numRegions = 16;
405  execResult = m_kernel->regions(m_regions, &m_numRegions);
406 
407  if (execResult != ExecutableFormat::Success)
408  {
409  ERROR("failed to get ExecutableFormat regions of kernel on path: " << kernelPath <<
410  ": result " << (int) execResult);
411  return Core::ExecError;
412  }
413 
414  // Release compressed kernel image
415  result = VMCtl(SELF, Release, &compressed);
416  if (result != API::Success)
417  {
418  ERROR("failed to release compressed kernel image with VMCtl: result = " << (int) result);
419  return Core::IOError;
420  }
421 
422  DEBUG("kernel loaded");
423  return Core::Success;
424 }
425 
427 {
428  // Cleanup program buffer
430  if (r != API::Success)
431  {
432  ERROR("failed to deallocate kernel image with VMCtl: result = " << (int) r);
433  return Core::IOError;
434  }
435 
437  MemoryBlock::set(&m_regions, 0, sizeof(m_regions));
438  return Core::Success;
439 }
440 
442  ExecutableFormat::Region *regions)
443 {
444  API::Result r;
445  SystemInformation sysInfo;
446 
447  DEBUG("Reserving: " << (void *)info->memory.phys << " size=" <<
448  info->memory.size << " available=" << sysInfo.memoryAvail);
449 
450  // Claim the core's memory
451  if ((r = VMCtl(SELF, ReserveMem, &info->memory)) != API::Success)
452  {
453  ERROR("VMCtl(ReserveMem) failed for core" << coreId <<
454  " at " << (void *)info->memory.phys << ": result " << (int) r);
455  return Core::OutOfMemory;
456  }
457 
458  DEBUG("Starting core" << coreId << " with "
459  << info->memory.size / 1024 / 1024 << "MB");
460 
461  // Map the kernel
462  for (Size i = 0; i < m_numRegions; i++)
463  {
464  Memory::Range range;
465  range.phys = info->memory.phys + (regions[i].virt - RAM_ADDR);
466  range.virt = 0;
467  range.size = regions[i].dataSize;
469  Memory::User;
470 
471  // Map the target kernel's memory for regions[i].size
472  if ((r = VMCtl(SELF, MapContiguous, &range)) != 0)
473  {
474  ERROR("VMCtl(Map) failed for kernel on core" << coreId <<
475  " at " << (void *)range.phys << ": result " << (int) r);
476  return Core::OutOfMemory;
477  }
478 
479  // Copy the kernel to the target core's memory
480  r = VMCopy(SELF, API::Write, m_kernelImage.virt + regions[i].dataOffset,
481  range.virt, regions[i].dataSize);
482  if (r != API::Success)
483  {
484  ERROR("VMCopy failed for kernel regions[" << i << "].dataOffset" <<
485  " at " << (void *)regions[i].dataOffset << ": result " << (int) r);
486  return Core::MemoryError;
487  }
488 
489  // Unmap the target kernel's memory
490  if ((r = VMCtl(SELF, UnMap, &range)) != API::Success)
491  {
492  ERROR("VMCtl(UnMap) failed for kernel on core" << coreId <<
493  " at " << (void *)range.phys << ": result " << (int) r);
494  return Core::MemoryError;
495  }
496 
497  DEBUG(kernelPath << "[" << i << "] = " << (void *) m_regions[i].virt <<
498  " @ " << (void *) range.phys);
499  }
500 
501  // Copy the BootImage after the kernel.
502  Memory::Range range;
503  range.phys = info->bootImageAddress;
504  range.virt = 0;
505  range.size = info->bootImageSize;
507 
508  // Map BootImage buffer
509  if ((r = VMCtl(SELF, MapContiguous, &range)) != API::Success)
510  {
511  ERROR("VMCtl(Map) failed for BootImage on core" << coreId <<
512  " at " << (void *)range.phys << ": result " << (int) r);
513  return Core::OutOfMemory;
514  }
515 
516  // Copy the BootImage
517  r = VMCopy(SELF, API::Write, sysInfo.bootImageAddress,
518  range.virt, sysInfo.bootImageSize);
519  if (r != API::Success)
520  {
521  ERROR("VMCopy failed for BootIage on core" << coreId <<
522  " at " << (void *)sysInfo.bootImageAddress <<
523  ": result " << (int) r);
524  return Core::MemoryError;
525  }
526 
527  // Unmap the BootImage
528  if ((r = VMCtl(SELF, UnMap, &range)) != API::Success)
529  {
530  ERROR("VMCtl(UnMap) failed for BootImage on core" << coreId <<
531  " at " << (void *)range.phys << ": result " << (int) r);
532  return Core::MemoryError;
533  }
534 
535  return Core::Success;
536 }
537 
538 
540 {
541  SystemInformation sysInfo;
542  Size memPerCore = 0;
543 
544  List<uint> & cores = m_cores->getCores();
545  if (cores.count() == 0)
546  {
547  ERROR("no cores found");
548  return Core::NotFound;
549  }
550 
551  memPerCore = sysInfo.memorySize / cores.count();
552  memPerCore /= MegaByte(4);
553  memPerCore *= MegaByte(4);
554 
555  NOTICE("found " << cores.count() << " cores: " <<
556  (memPerCore / 1024 / 1024) << "MB per core");
557 
558  // Allocate CoreInfo for each core
560 
561  // Prepare CoreInfo for each core
562  for (ListIterator<uint> i(cores); i.hasCurrent(); i++)
563  {
564  uint coreId = i.current();
565 
566  if (coreId != 0)
567  {
568  CoreInfo *info = new CoreInfo;
569  m_coreInfo->insertAt(coreId, info);
570  MemoryBlock::set(info, 0, sizeof(CoreInfo));
571 
572  info->coreId = coreId;
573  info->memory.phys = RAM_ADDR + (memPerCore * coreId);
574  info->memory.size = memPerCore - PAGESIZE;
575  info->kernel.phys = sysInfo.kernelAddress + (memPerCore * coreId);
576  info->kernel.size = sysInfo.kernelSize;
577 
578  info->bootImageAddress = info->kernel.phys + info->kernel.size;
579  info->bootImageAddress += PAGESIZE - (info->kernel.size % PAGESIZE);
580  info->bootImageSize = sysInfo.bootImageSize;
581 
582  info->heapAddress = info->bootImageAddress + info->bootImageSize;
583  info->heapAddress += PAGESIZE - (info->bootImageSize % PAGESIZE);
584  info->heapSize = MegaByte(1);
585 
586  info->coreChannelAddress = info->heapAddress + info->heapSize;
587  info->coreChannelAddress += PAGESIZE - (info->heapSize % PAGESIZE);
588  info->coreChannelSize = PAGESIZE * 4;
590 
591  m_kernel->entry(&info->kernelEntry);
592  info->timerCounter = sysInfo.timerCounter;
594  }
595  }
596 
597  return Core::Success;
598 }
599 
601 {
602  List<uint> & cores = m_cores->getCores();
603  if (cores.count() == 0)
604  {
605  ERROR("no cores found");
606  return Core::NotFound;
607  }
608 
609  // Boot each core
610  for (ListIterator<uint> i(cores); i.hasCurrent(); i++)
611  {
612  uint coreId = i.current();
613 
614  if (coreId != 0)
615  {
618  }
619  }
620 
621  return Core::Success;
622 }
623 
625 {
626  Memory::Range range;
627 
628  DEBUG("addr = " << (void*)addr << ", size = " << size);
629 
630  range.phys = addr;
631  range.virt = ZERO;
632  range.size = size;
634  VMCtl(SELF, MapContiguous, &range);
635 
636  MemoryBlock::set((void *) range.virt, 0, size);
637 
638  VMCtl(SELF, UnMap, &range);
639  return Core::Success;
640 }
641 
643 {
644  SystemInformation info;
645 
646  DEBUG("");
647 
648  if (info.coreId == 0)
649  {
650  Size numCores = m_cores->getCores().count();
651 
654 
655  for (Size i = 1; i < numCores; i++)
656  {
661  m_toSlave->insertAt(i, ch);
662 
663  ch = new MemoryChannel(Channel::Consumer, sizeof(CoreMessage));
666  m_fromSlave->insertAt(i, ch);
667  }
668  }
669  else
670  {
674 
677  info.coreChannelAddress + (PAGESIZE * 3));
678  }
679 
680  return Core::Success;
681 }
682 
684 {
686 
687  // wait from a message of the master core
688  while (result != Channel::Success)
689  {
690  for (uint i = 0; i < MaxMessageRetry && result != Channel::Success; i++)
691  {
692  result = m_fromMaster->read(msg);
693  }
694 
695  // Wait for IPI which will wake us
696  waitIPI();
697  }
698 
699  return Core::Success;
700 }
701 
703 {
704  while (m_toMaster->write(msg) != Channel::Success)
705  ;
706 
707  const MemoryChannel::Result result = m_toMaster->flush();
708  if (result != Channel::Success)
709  {
710  ERROR("failed to flush master channel: result = " << (int) result);
711  msg->result = Core::IOError;
712  return Core::IOError;
713  }
714 
715  return Core::Success;
716 }
717 
719 {
721  if (!ch)
722  return Core::IOError;
723 
724  while (ch->read(msg) != Channel::Success)
725  ;
726 
727  return Core::Success;
728 }
729 
731 {
733  if (!ch)
734  {
735  ERROR("cannot retrieve MemoryChannel for core" << coreId);
736  msg->result = Core::NotFound;
737  return Core::IOError;
738  }
739 
740  MemoryChannel::Result result = ch->write(msg);
741  if (result != Channel::Success)
742  {
743  ERROR("failed to write channel on core" << coreId << ": result = " << (int)result);
744  msg->result = Core::IOError;
745  return Core::IOError;
746  }
747 
748  result = ch->flush();
749  if (result != Channel::Success)
750  {
751  ERROR("failed to flush channel on core" << coreId << ": result = " << (int)result);
752  msg->result = Core::IOError;
753  return Core::IOError;
754  }
755 
756  // Send IPI to ensure the slave wakes up for the message
757  if (sendIPI(coreId) != Core::Success)
758  {
759  ERROR("failed to send IPI to core" << coreId);
760  return Core::IOError;
761  }
762 
763  return Core::Success;
764 }
CoreServer::bootCore
virtual Core::Result bootCore(uint coreId, CoreInfo *info)=0
Boot a processor core.
ChannelServer< CoreServer, CoreMessage >::m_ipcHandlers
Index< MessageHandler< IPCHandlerFunction >, MaximumHandlerCount > m_ipcHandlers
IPC handler functions.
Definition: ChannelServer.h:538
ExecutableFormat.h
Core::PongResponse
@ PongResponse
Definition: Core.h:41
Core::OutOfMemory
@ OutOfMemory
Definition: Core.h:54
strlcpy
size_t strlcpy(char *dst, const char *src, size_t siz)
Copy src to string dst of size siz.
Definition: strlcpy.cpp:19
stat::st_size
off_t st_size
For regular files, the file size in bytes.
Definition: stat.h:226
stat
The <sys/stat.h> header shall define the stat structure.
Definition: stat.h:176
CoreServer::createProcess
void createProcess(CoreMessage *msg)
Create a process on the current processor core.
Definition: CoreServer.cpp:82
Index::insertAt
virtual bool insertAt(const Size position, T *item)
Inserts the given item at the given position.
Definition: Index.h:113
Channel::Success
@ Success
Definition: Channel.h:43
Memory::Range
Memory range.
Definition: Memory.h:55
StrictSingleton< ChannelClient >::instance
static ChannelClient * instance()
Retrieve the instance.
Definition: Singleton.h:53
Core::MemoryError
@ MemoryError
Definition: Core.h:56
CoreServer::m_fromMaster
MemoryChannel * m_fromMaster
Definition: CoreServer.h:258
API::Result
Result
Enumeration of generic kernel API result codes.
Definition: API.h:68
fcntl.h
CoreServer::unloadKernel
Core::Result unloadKernel()
Unload operating system kernel program.
Definition: CoreServer.cpp:426
CoreMessage::programAddr
Address programAddr
Contains the virtual address of a loaded program.
Definition: CoreMessage.h:43
CoreServer::m_coreInfo
Index< CoreInfo, MaxCores > * m_coreInfo
Definition: CoreServer.h:251
NOTICE
#define NOTICE(msg)
Output a notice message.
Definition: Log.h:75
CoreMessage
Message format for communication with the CoreServer.
Definition: CoreMessage.h:38
ChannelServer< CoreServer, CoreMessage >::Success
@ Success
Definition: ChannelServer.h:101
CoreServer::prepareCoreInfo
Core::Result prepareCoreInfo()
Prepare the CoreInfo array.
Definition: CoreServer.cpp:539
CoreInfo::bootImageSize
Address bootImageSize
Boot image size in bytes.
Definition: CoreInfo.h:84
MemoryBlock::set
static void * set(void *dest, int ch, unsigned count)
Fill memory with a constant byte.
Definition: MemoryBlock.cpp:25
Core::IOError
@ IOError
Definition: Core.h:55
string.h
MemoryChannel::setPhysical
Result setPhysical(const Address data, const Address feedback, const bool hardReset=true)
Set memory pages by physical address.
Definition: MemoryChannel.cpp:64
CoreServer::m_kernelImage
Memory::Range m_kernelImage
Definition: CoreServer.h:245
CoreInfo::heapAddress
Address heapAddress
Physical memory address of the kernel heap.
Definition: CoreInfo.h:93
Core::NotFound
@ NotFound
Definition: Core.h:51
ExecutableFormat::Region
Memory region.
Definition: ExecutableFormat.h:55
Memory::Writable
@ Writable
Definition: Memory.h:42
SystemInformation::coreChannelAddress
Address coreChannelAddress
Definition: SystemInfo.h:113
Memory::User
@ User
Definition: Memory.h:44
Lz4Decompressor::getUncompressedSize
u64 getUncompressedSize() const
Get size of the uncompressed data.
Definition: Lz4Decompressor.cpp:125
SystemInformation::kernelSize
Size kernelSize
Size of the kernel program in bytes.
Definition: SystemInfo.h:99
PAGESIZE
#define PAGESIZE
ARM uses 4K pages.
Definition: ARMConstant.h:97
CoreServer::initialize
virtual Result initialize()
Initialize the server.
Definition: CoreServer.cpp:260
API::Write
@ Write
Definition: API.h:99
CoreServer::loadKernel
Core::Result loadKernel()
Load operating system kernel program.
Definition: CoreServer.cpp:315
CoreServer::sendToSlave
Core::Result sendToSlave(uint coreId, CoreMessage *msg)
Send message to slave.
Definition: CoreServer.cpp:730
ChannelMessage::type
Type type
Message type is either a request or response.
Definition: ChannelMessage.h:48
Lz4Decompressor::initialize
Result initialize()
Initialize the decompressor.
Definition: Lz4Decompressor.cpp:35
Index< CoreInfo, MaxCores >
CoreServer::runCore
int runCore()
Routine for the slave processor core.
Definition: CoreServer.cpp:52
MessageHandler< IPCHandlerFunction >
Address
unsigned long Address
A memory address.
Definition: Types.h:131
ChannelServer< CoreServer, CoreMessage >::run
int run()
Enters an infinite loop, serving incoming requests.
Definition: ChannelServer.h:161
CoreInfo::memory
Memory::Range memory
Defines the physical memory available to the core.
Definition: CoreInfo.h:69
CoreMessage::result
Core::Result result
Result code.
Definition: CoreMessage.h:41
List::count
Size count() const
Get the number of items on the list.
Definition: List.h:402
ExecutableFormat::regions
virtual Result regions(Region *regions, Size *count) const =0
Memory regions a program needs at runtime.
VMCtl
API::Result VMCtl(const ProcessID procID, const MemoryOperation op, Memory::Range *range=ZERO)
Prototype for user applications.
Definition: VMCtl.h:61
CoreInfo::coreChannelAddress
Address coreChannelAddress
Physical memory address of IPC channel for CoreServer of this core.
Definition: CoreInfo.h:87
open
int open(const char *path, int oflag,...)
Open file relative to directory file descriptor.
Definition: open.cpp:26
UnMap
@ UnMap
Definition: VMCtl.h:39
SystemInformation::coreId
uint coreId
Core Identifier.
Definition: SystemInfo.h:105
MessageHandler::sendReply
const bool sendReply
Whether to send a reply or not.
Definition: ChannelServer.h:71
Memory::Readable
@ Readable
Definition: Memory.h:41
read
ssize_t read(int fildes, void *buf, size_t nbyte)
Read from a file.
Definition: read.cpp:22
CoreMessage::action
Core::Action action
Action to perform.
Definition: CoreMessage.h:40
ExecutableFormat::find
static Result find(const u8 *image, const Size size, ExecutableFormat **fmt)
Find a ExecutableFormat which can handle the given format.
Definition: ExecutableFormat.cpp:32
wait.h
ExecutableFormat::Region::dataOffset
Address dataOffset
Definition: ExecutableFormat.h:58
uint
unsigned int uint
Unsigned integer number.
Definition: Types.h:44
Lz4Decompressor::Success
@ Success
Definition: Lz4Decompressor.h:72
CoreServer::m_toSlave
Index< MemoryChannel, MaxCores > * m_toSlave
Definition: CoreServer.h:255
ExecutableFormat::Region::virt
Address virt
Definition: ExecutableFormat.h:57
CoreServer::waitIPI
virtual void waitIPI() const =0
Wait for Inter-Processor-Interrupt.
CoreInfo::coreId
uint coreId
Core identifier.
Definition: CoreInfo.h:66
ExecutableFormat::Result
Result
Result code.
Definition: ExecutableFormat.h:68
MegaByte
#define MegaByte(v)
Convert megabytes to bytes.
Definition: Macros.h:57
MessageHandler::exec
const Func exec
Handler function.
Definition: ChannelServer.h:68
SELF
#define SELF
Definition: ProcessID.h:35
CoreServer
Represents a single Core in a Central Processing Unit (CPU).
Definition: CoreServer.h:49
Lz4Decompressor.h
CoreInfo
struct CoreInfo CoreInfo
Per-Core information structure.
CoreServer::m_kernel
ExecutableFormat * m_kernel
Definition: CoreServer.h:244
DEBUG
#define DEBUG(msg)
Output a debug message to standard output.
Definition: Log.h:89
CoreInfo::kernelCommand
char kernelCommand[KERNEL_PATHLEN]
Kernel command.
Definition: CoreInfo.h:78
Release
@ Release
Definition: VMCtl.h:40
CoreServer.h
CoreServer::CoreServer
CoreServer()
Class constructor function.
Definition: CoreServer.cpp:31
ChannelServer< CoreServer, CoreMessage >::Result
Result
Result codes.
Definition: ChannelServer.h:99
Memory::Range::phys
Address phys
Physical address.
Definition: Memory.h:58
close
int close(int fildes)
Close a file descriptor.
Definition: close.cpp:22
ListIterator::hasCurrent
virtual bool hasCurrent() const
Check if there is a current item on the List.
Definition: ListIterator.h:104
CoreServer::bootAll
Core::Result bootAll()
Boot all processor cores.
Definition: CoreServer.cpp:600
ChannelServer< CoreServer, CoreMessage >::IOError
@ IOError
Definition: ChannelServer.h:104
CoreInfo::kernelEntry
Address kernelEntry
Kernel entry point.
Definition: CoreInfo.h:72
Channel::NotFound
@ NotFound
Definition: Channel.h:49
CoreServer::m_info
SystemInformation m_info
Definition: CoreServer.h:252
CoreMessage::programCmd
const char * programCmd
Command-line string for a loaded program.
Definition: CoreMessage.h:45
CoreServer::m_cores
CoreManager * m_cores
Definition: CoreServer.h:240
CoreMessage::coreNumber
Size coreNumber
Indicates a number of cores or a specific coreId.
Definition: CoreMessage.h:42
CoreServer::discoverCores
virtual Core::Result discoverCores()=0
Discover processor cores.
stdio.h
KERNEL_PATHLEN
#define KERNEL_PATHLEN
Definition: CoreInfo.h:29
ChannelClient::syncSendTo
virtual Result syncSendTo(const void *buffer, const Size msgSize, const ProcessID pid)
Synchronous send to one process.
Definition: ChannelClient.cpp:292
CoreServer::clearPages
Core::Result clearPages(Address addr, Size size)
Clear memory pages with zeroes.
Definition: CoreServer.cpp:624
NULL
#define NULL
NULL means zero.
Definition: Macros.h:39
Channel::Consumer
@ Consumer
Definition: Channel.h:59
Size
unsigned int Size
Any sane size indicator cannot go negative.
Definition: Types.h:128
CoreMessage::programSize
Size programSize
Contains the size of a loaded program.
Definition: CoreMessage.h:44
MemoryChannel::write
virtual Result write(const void *buffer)
Write a message.
Definition: MemoryChannel.cpp:138
CoreServer::getCoreCount
void getCoreCount(CoreMessage *msg)
Get and fill the number of processor cores.
Definition: CoreServer.cpp:207
CoreInfo::bootImageAddress
Address bootImageAddress
Boot image physical memory address.
Definition: CoreInfo.h:81
MemoryChannel
Unidirectional point-to-point channel using shared memory.
Definition: MemoryChannel.h:43
Index::get
virtual T * get(const Size position) const
Returns the item at the given position.
Definition: Index.h:187
stat
int stat(const char *path, struct stat *buf)
Get file status.
Definition: stat.cpp:25
SystemInformation::bootImageSize
Size bootImageSize
BootImage size.
Definition: SystemInfo.h:111
Channel::Producer
@ Producer
Definition: Channel.h:58
CoreServer::setupChannels
Core::Result setupChannels()
Setup communication channels between CoreServers.
Definition: CoreServer.cpp:642
pid_t
ProcessID pid_t
Used for process IDs and process group IDs.
Definition: types.h:32
Lz4Decompressor::Result
Result
Result codes.
Definition: Lz4Decompressor.h:70
MemoryChannel::flush
virtual Result flush()
Flush message buffers.
Definition: MemoryChannel.cpp:158
MemoryChannel::read
virtual Result read(void *buffer)
Read a message.
Definition: MemoryChannel.cpp:116
CoreInfo
Per-Core information structure.
Definition: CoreInfo.h:60
Core::Result
Result
Result code for Actions.
Definition: Core.h:47
LookupVirtual
@ LookupVirtual
Definition: VMCtl.h:42
coreInfo
CoreInfo coreInfo
Local CoreInfo instance.
stat.h
CoreServer::m_fromSlave
Index< MemoryChannel, MaxCores > * m_fromSlave
Definition: CoreServer.h:254
CoreInfo::timerCounter
uint timerCounter
Arch-specific timer counter.
Definition: CoreInfo.h:99
ChannelServer
Template class which serves incoming messages from Channels using MessageHandlers.
Definition: ChannelServer.h:79
unistd.h
ExecutableFormat::entry
virtual Result entry(Address *entry) const =0
Lookup the program entry point.
Lz4Decompressor::read
Result read(void *buffer, const Size size) const
Reads compressed data.
Definition: Lz4Decompressor.cpp:130
ERROR
#define ERROR(msg)
Output an error message.
Definition: Log.h:61
SystemInformation
System information structure.
Definition: SystemInfo.h:79
u8
unsigned char u8
Unsigned 8-bit number.
Definition: Types.h:59
CoreInfo::coreChannelSize
Size coreChannelSize
Size of the IPC channel in bytes.
Definition: CoreInfo.h:90
SystemInformation::timerCounter
uint timerCounter
Timer counter.
Definition: SystemInfo.h:117
Lz4Decompressor
Decompress data using the LZ4 algorithm created by Yann Collet.
Definition: Lz4Decompressor.h:39
CoreInfo::kernel
Memory::Range kernel
Kernel memory range.
Definition: CoreInfo.h:75
CoreServer::test
Core::Result test()
Run a ping-pong test.
Definition: CoreServer.cpp:224
Channel::Result
Result
Result codes.
Definition: Channel.h:41
spawn
int spawn(Address program, Size programSize, const char *argv[])
Create a new process using in-memory image.
Definition: spawn.cpp:29
Core::CreateProcess
@ CreateProcess
Definition: Core.h:39
ExecutableFormat::Region::dataSize
Size dataSize
Definition: ExecutableFormat.h:59
CoreManager::getCores
List< uint > & getCores()
Get list of core identities.
Definition: CoreManager.cpp:24
Core::ExecError
@ ExecError
Definition: Core.h:53
API::Success
@ Success
Definition: API.h:70
SystemInformation::memorySize
Size memorySize
Total and available memory in bytes.
Definition: SystemInfo.h:102
ChannelMessage::from
ProcessID from
Source process of the message.
Definition: ChannelMessage.h:54
ChannelServer< CoreServer, CoreMessage >::addIPCHandler
void addIPCHandler(const Size slot, IPCHandlerFunction h, const bool sendReply=true)
Register a new IPC message action handler.
Definition: ChannelServer.h:203
CoreServer::prepareCore
Core::Result prepareCore(uint coreId, CoreInfo *info, ExecutableFormat::Region *regions)
Prepare processor core for booting.
Definition: CoreServer.cpp:441
CoreServer::sendToMaster
Core::Result sendToMaster(CoreMessage *msg)
Send message to master.
Definition: CoreServer.cpp:702
Core::Success
@ Success
Definition: Core.h:49
Memory::Range::virt
Address virt
Virtual address.
Definition: Memory.h:57
CoreServer::MaxMessageRetry
static const Size MaxMessageRetry
Number of times to busy wait on receiving a message.
Definition: CoreServer.h:58
CoreServer::kernelPath
static const char * kernelPath
The default kernel for starting new cores.
Definition: CoreServer.h:61
List< uint >
ChannelMessage::Response
@ Response
Definition: ChannelMessage.h:44
waitpid
pid_t waitpid(pid_t pid, int *stat_loc, int options)
Wait for a child process to stop or terminate.
Definition: waitpid.cpp:23
CoreInfo::heapSize
Size heapSize
Size in bytes of the kernel heap.
Definition: CoreInfo.h:96
CoreServer::sendIPI
virtual Core::Result sendIPI(uint coreId)=0
Send Inter-Processor-Interrupt.
VMCopy
API::Result VMCopy(const ProcessID proc, const API::Operation how, const Address ours, const Address theirs, const Size sz)
Prototype for user applications.
Definition: VMCopy.h:42
Memory::Range::size
Size size
Size in number of bytes.
Definition: Memory.h:59
Core::InvalidArgument
@ InvalidArgument
Definition: Core.h:50
Memory::Range::access
Access access
Page access flags.
Definition: Memory.h:60
CoreServer::m_numRegions
Size m_numRegions
Definition: CoreServer.h:249
CoreServer::m_toMaster
MemoryChannel * m_toMaster
Definition: CoreServer.h:257
ZERO
#define ZERO
Zero value.
Definition: Macros.h:43
coreId
u8 coreId
Definition: IntelACPI.h:64
MapContiguous
@ MapContiguous
Definition: VMCtl.h:37
API::ReadPhys
@ ReadPhys
Definition: API.h:100
CoreServer::receiveFromSlave
Core::Result receiveFromSlave(uint coreId, CoreMessage *msg)
Receive message from slave.
Definition: CoreServer.cpp:718
ReserveMem
@ ReserveMem
Definition: VMCtl.h:44
SystemInformation::kernelAddress
Address kernelAddress
Physical start address of the kernel program.
Definition: SystemInfo.h:96
CoreServer::receiveFromMaster
Core::Result receiveFromMaster(CoreMessage *msg)
Receive message from master.
Definition: CoreServer.cpp:683
O_RDONLY
#define O_RDONLY
Open for reading only.
Definition: fcntl.h:81
SystemInformation::memoryAvail
Size memoryAvail
Definition: SystemInfo.h:102
CoreServer::m_regions
ExecutableFormat::Region m_regions[16]
Definition: CoreServer.h:247
ExecutableFormat::Success
@ Success
Definition: ExecutableFormat.h:70
Core::GetCoreCount
@ GetCoreCount
Definition: Core.h:38
SystemInformation::bootImageAddress
Address bootImageAddress
BootImage physical address.
Definition: SystemInfo.h:108
ListIterator
Iterate through a List.
Definition: ListIterator.h:37