x86 vmm: add general multiprocessor support

* repos/ports/include/vmm
 - add support to specify cpu location during vCPU construction
* seoul
 - update to latest seoul branch supporting smp
 - adjust to vmm interface changes
 - vCPUs will be put in a round robin fashion on the available host CPUs,
   beginning with the next CPU after the default (boot) CPU
 - number of vCPUs can be specified in run script
* virtualbox
 - adjust to vmm interface changes
 - uses still one vCPU, placed on default (boot) CPU

Fixes #1212
This commit is contained in:
Alexander Boettcher 2014-07-16 21:43:41 +02:00 committed by Norman Feske
parent 40fc64e24f
commit 5d06078d27
19 changed files with 123 additions and 60 deletions

View File

@ -57,13 +57,18 @@ class Vmm::Vcpu_dispatcher : public T
public:
Vcpu_dispatcher(size_t stack_size, Cap_connection &cap)
Vcpu_dispatcher(size_t stack_size, Cap_connection &cap,
Cpu_session * cpu_session,
Genode::Affinity::Location location)
:
T("vCPU dispatcher", stack_size),
_cap(cap)
{
using namespace Genode;
/* place the thread on CPU described by location object */
cpu_session->affinity(T::cap(), location);
/* request creation of a 'local' EC */
T::_tid.ec_sel = Native_thread::INVALID_INDEX - 1;
T::start();
@ -72,12 +77,17 @@ class Vmm::Vcpu_dispatcher : public T
template <typename X>
Vcpu_dispatcher(size_t stack_size, Cap_connection &cap,
Cpu_session * cpu_session,
Genode::Affinity::Location location,
X attr, void *(*start_routine) (void *), void *arg)
: T(attr, start_routine, arg, stack_size, "vCPU dispatcher", nullptr),
_cap(cap)
{
using namespace Genode;
/* place the thread on CPU described by location object */
cpu_session->affinity(T::cap(), location);
/* request creation of a 'local' EC */
T::_tid.ec_sel = Native_thread::INVALID_INDEX - 1;
T::start();

View File

@ -43,16 +43,18 @@ class Vmm::Vcpu_other_pd : public Vmm::Vcpu_thread
{
private:
Genode::Pd_connection _pd_session;
Genode::Cpu_session *_cpu_session;
Genode::Pd_connection _pd_session;
Genode::Affinity::Location _location;
Genode::Cpu_session *_cpu_session;
Genode::addr_t _exc_pt_sel;
public:
Vcpu_other_pd(Cpu_session * cpu_session)
Vcpu_other_pd(Cpu_session * cpu_session,
Genode::Affinity::Location location)
:
_pd_session("VM"), _cpu_session(cpu_session),
_pd_session("VM"), _location(location), _cpu_session(cpu_session),
_exc_pt_sel(Genode::cap_map()->insert(Nova::NUM_INITIAL_VCPU_PT_LOG2))
{ }
@ -83,6 +85,9 @@ class Vmm::Vcpu_other_pd : public Vmm::Vcpu_thread
*/
delegate_vcpu_portals(pager_cap, exc_base());
/* place the thread on CPU described by location object */
_cpu_session->affinity(vcpu_vm, _location);
/* start vCPU in separate PD */
_cpu_session->start(vcpu_vm, 0, 0);
@ -101,7 +106,8 @@ class Vmm::Vcpu_same_pd : public Vmm::Vcpu_thread, Genode::Thread_base
{
public:
Vcpu_same_pd(size_t stack_size, Cpu_session * cpu_session)
Vcpu_same_pd(size_t stack_size, Cpu_session * cpu_session,
Genode::Affinity::Location location)
:
Thread_base("vCPU", stack_size, Type::NORMAL, cpu_session)
{
@ -113,6 +119,9 @@ class Vmm::Vcpu_same_pd : public Vmm::Vcpu_thread, Genode::Thread_base
/* tell generic thread code that this becomes a vCPU */
this->tid().is_vcpu = true;
/* place the thread on CPU described by location object */
cpu_session->affinity(Thread_base::cap(), location);
}
~Vcpu_same_pd()

View File

@ -1 +1 @@
320f1607901ba6ba2fe18905997a611c7046b9b0
f9a8e04cc3b086d8cbdff95cd5fcd1f7a3fdaad7

View File

@ -3,7 +3,8 @@ VERSION := git
DOWNLOADS := seoul.git
URL(seoul) := https://github.com/alex-ab/seoul.git
REV(seoul) := genode_13_08
# branch genode_virtualsmp
REV(seoul) := 86c743a519abb87d3a729db07137222d836420a6
DIR(seoul) := src/app/seoul
#

View File

@ -24,6 +24,8 @@ set use_fancy_stuff 0
set memory_vmm_vm "128M"
set vcpus_to_be_used 2
set multiboot_files {
<rom name="munich"/>
<rom name="bzImage-3.1" cmdline="root=/dev/ram0 earlyprintk=ttyS0 console=ttyS0 text"/>

View File

@ -22,6 +22,8 @@ set use_fancy_stuff 0
set memory_vmm_vm "128M"
set vcpus_to_be_used 1
source ${genode_dir}/repos/ports/run/seoul.inc
if {[is_qemu_available]} {

View File

@ -26,6 +26,8 @@ set use_fancy_stuff 1
set memory_init "288M"
set memory_vmm_vm "128M"
set vcpus_to_be_used 1
set multiboot_files {
<rom name="munich"/>
<rom name="bzImage-3.1" cmdline="root=/dev/ram0 earlyprintk=ttyS0 vga=0x314"/>

View File

@ -29,9 +29,12 @@ set use_fancy_stuff 0
set memory_vmm_vm "950M"
# adjust also '-j option' accordingly - see benchmark_cmd
set vcpus_to_be_used 1
set multiboot_files {
<rom name="munich"/>
<rom name="bzImage-3.1" cmdline="root=/dev/ram0 earlyprintk=ttyS0 console=ttyS0 text"/>
<rom name="bzImage-3.1" cmdline="root=/dev/ram0 earlyprintk=ttyS0 console=ttyS0 text benchmark_cmd='make -C /usr/src/linux-* defconfig && make -j 1 -C /usr/src/linux-* bzImage'"/>
<rom name="kernelbuild-e2fs.bz2"/>
}

View File

@ -22,6 +22,8 @@ set use_fancy_stuff 0
set memory_vmm_vm "128M"
set vcpus_to_be_used 1
set multiboot_files {
<rom name="munich"/>
<rom name="bzImage-3.1" cmdline="root=/dev/ram0 earlyprintk=ttyS0 text"/>

View File

@ -83,9 +83,12 @@ puts $vm_cfg_fd {
<ioapic/>
<pcihostbridge bus_num="0" bus_count="0x10" io_base="0xcf8"
mem_base="0xe0000000"/>
<pmtimer io_port="0x8000"/>
<pmtimer io_port="0x8000"/>}
for {set i 0} {$i < $vcpus_to_be_used} {incr i 1} {
puts $vm_cfg_fd {
<vcpu/> <halifax/> <vbios/> <lapic/>}
}
if {!$use_multiboot} {
puts $vm_cfg_fd {
@ -120,7 +123,7 @@ create_boot_directory
#
append config {
<config verbose="yes">
<config verbose="yes" prio_levels="4">
<parent-provides>
<service name="ROM"/>
<service name="RAM"/>
@ -143,33 +146,33 @@ append config {
<provides><service name="Timer"/></provides>
</start>
<start name="rtc_drv">
<start name="rtc_drv" priority="-1">
<resource name="RAM" quantum="1M"/>
<provides><service name="Rtc"/></provides>
</start>}
append_if [expr !$use_usb] config {
<start name="ps2_drv">
<start name="ps2_drv" priority="-1">
<resource name="RAM" quantum="3M"/>
<provides><service name="Input"/></provides>
<route> <any-service><parent/></any-service> </route>
</start> }
append_if $use_block_sata config {
<start name="ahci">
<start name="ahci" priority="-1">
<resource name="RAM" quantum="1M" />
<provides><service name="Block"/></provides>
</start>}
append_if $use_block_ide config {
<start name="atapi_drv">
<start name="atapi_drv" priority="-1">
<resource name="RAM" quantum="1M" />
<provides><service name="Block"/></provides>
<config ata="yes" />
</start>}
append_if [have_spec acpi] config {
<start name="acpi">
<start name="acpi" priority="-1">
<resource name="RAM" quantum="8M"/>
<binary name="acpi_drv"/>
<provides>
@ -183,7 +186,7 @@ append_if [have_spec acpi] config {
</start>}
append_if [expr ![have_spec acpi] && [have_spec pci]] config {
<start name="pci_drv">
<start name="pci_drv" priority="-1">
<resource name="RAM" quantum="3M"/>
<provides><service name="PCI"/></provides>
<route> <any-service><parent/></any-service> </route>
@ -191,7 +194,7 @@ append_if [expr ![have_spec acpi] && [have_spec pci]] config {
}
append_if $use_nic_session config {
<start name="nic_drv">
<start name="nic_drv" priority="-2">
<resource name="RAM" quantum="3M"/>
<provides><service name="Nic"/></provides>
<route> <any-service><any-child/><parent/></any-service> </route>
@ -199,7 +202,7 @@ append_if $use_nic_session config {
}
append_if [expr $use_nic_session && $use_nic_bridge] config {
<start name="nic_bridge">
<start name="nic_bridge" priority="-3">
<resource name="RAM" quantum="4M"/>
<provides><service name="Nic"/></provides>
<route>
@ -210,7 +213,7 @@ append_if [expr $use_nic_session && $use_nic_bridge] config {
}
append_if $use_framebuffer config {
<start name="fb_drv">
<start name="fb_drv" priority="-1">
<resource name="RAM" quantum="8M"/>
<provides><service name="Framebuffer"/></provides>
<route>
@ -223,7 +226,7 @@ append_if $use_framebuffer config {
if {!$use_fancy_stuff} {
append config {
<start name="seoul">
<start name="seoul" priority="-3">
<binary name="seoul"/>}
append config "
<resource name=\"RAM\" quantum=\"$memory_vmm_vm\"/>"
@ -245,7 +248,7 @@ append config {
}
append_if $use_usb config {
<start name="usb_drv">
<start name="usb_drv" priority="-1">
<resource name="RAM" quantum="7M"/>
<provides><service name="Input"/></provides>
<config uhci="yes" ehci="yes" xhci="yes">
@ -254,7 +257,7 @@ append_if $use_usb config {
</start>}
append_if $use_fancy_stuff config {
<start name="nitpicker">
<start name="nitpicker" priority="-1">
<resource name="RAM" quantum="8M"/>
<route>
<service name="Timer"> <child name="timer"/></service>
@ -263,7 +266,7 @@ append_if $use_fancy_stuff config {
</route>
<provides><service name="Nitpicker"/></provides>
</start>
<start name="launchpad">
<start name="launchpad" priority="-2">
<resource name="RAM" quantum="64000M"/>
<configfile name="launchpad-config"/>
<route>
@ -305,7 +308,7 @@ if {$use_fancy_stuff} {
<service name="Rtc"/>
</parent-provides>
<start name="fb.seoul">
<start name="fb.seoul" priority="-1">
<binary name="liquid_fb"/>
<resource name="RAM" quantum="16M"/>
<provides>
@ -318,7 +321,7 @@ if {$use_fancy_stuff} {
<config xpos="10" ypos="10" width="800" height="600" animate="off"/>
</start>
<start name="seoul">
<start name="seoul" priority="-1">
<binary name="seoul"/>
<resource name="RAM" quantum="256M"/>
<route>

View File

@ -683,9 +683,11 @@ class Vcpu_dispatcher : public Vcpu_handler,
Synced_motherboard &motherboard,
bool has_svm,
bool has_vmx,
Vmm::Vcpu_thread *vcpu_thread)
Vmm::Vcpu_thread *vcpu_thread,
Genode::Cpu_session *cpu_session,
Genode::Affinity::Location &location)
:
Vcpu_handler(STACK_SIZE, cap_connection),
Vcpu_handler(STACK_SIZE, cap_connection, cpu_session, location),
_vcpu(vcpu_lock, unsynchronized_vcpu),
_vcpu_thread(vcpu_thread),
_guest_memory(guest_memory),
@ -837,6 +839,7 @@ class Machine : public StaticReceiver<Machine>
bool _alloc_fb_mem; /* For detecting FB alloc message */
bool _colocate_vm_vmm;
unsigned short _vcpus_up;
Nic::Session *_nic;
Rtc::Session *_rtc;
@ -911,13 +914,17 @@ class Machine : public StaticReceiver<Machine>
if (verbose_debug)
Logging::printf("OP_VCPU_CREATE_BACKEND\n");
_vcpus_up ++;
Vmm::Vcpu_thread * vcpu_thread;
Genode::Cpu_session * cpu = Genode::env()->cpu_session();
Genode::Cpu_session * cpu_session = Genode::env()->cpu_session();
Genode::Affinity::Space cpu_space = cpu_session->affinity_space();
Genode::Affinity::Location location = cpu_space.location_of_index(_vcpus_up);
if (_colocate_vm_vmm)
vcpu_thread = new Vmm::Vcpu_same_pd(Vcpu_dispatcher::STACK_SIZE, cpu);
vcpu_thread = new Vmm::Vcpu_same_pd(Vcpu_dispatcher::STACK_SIZE, cpu_session, location);
else
vcpu_thread = new Vmm::Vcpu_other_pd(cpu);
vcpu_thread = new Vmm::Vcpu_other_pd(cpu_session, location);
Vcpu_dispatcher *vcpu_dispatcher =
new Vcpu_dispatcher(_motherboard_lock,
@ -927,7 +934,9 @@ class Machine : public StaticReceiver<Machine>
_motherboard,
_hip->has_feature_svm(),
_hip->has_feature_vmx(),
vcpu_thread);
vcpu_thread,
cpu_session,
location);
msg.value = vcpu_dispatcher->sel_sm_ec();
return true;
@ -1216,7 +1225,8 @@ class Machine : public StaticReceiver<Machine>
_timeouts(_timeouts_lock, &_unsynchronized_timeouts),
_guest_memory(guest_memory),
_boot_modules(boot_modules),
_colocate_vm_vmm(colocate)
_colocate_vm_vmm(colocate),
_vcpus_up(0)
{
_timeouts()->init();
@ -1304,6 +1314,10 @@ class Machine : public StaticReceiver<Machine>
*/
void boot()
{
PINF("VM and VMM are %s. VM is starting with %u %s.",
_colocate_vm_vmm ? "co-located" : "not co-located",
_vcpus_up, _vcpus_up > 1 ? "vCPUs" : "vCPU");
/* init VCPUs */
for (VCpu *vcpu = _unsynchronized_motherboard.last_vcpu; vcpu; vcpu = vcpu->get_last()) {
@ -1462,8 +1476,6 @@ int main(int argc, char **argv)
machine.setup_devices(Genode::config()->xml_node().sub_node("machine"));
PINF("VM and VMM %s.", colocate ? "co-located" : "not co-located");
Genode::printf("\n--- Booting VM ---\n");
machine.boot();

View File

@ -60,8 +60,8 @@ class Vcpu_dispatcher : public Vmm::Vcpu_dispatcher<Genode::Thread_base>
Vcpu_dispatcher(Cap_connection &cap, Type type)
:
Vmm::Vcpu_dispatcher<Genode::Thread_base>(STACK_SIZE, cap),
_vcpu_thread(STACK_SIZE, Genode::env()->cpu_session())
Vmm::Vcpu_dispatcher<Genode::Thread_base>(STACK_SIZE, cap, Genode::env()->cpu_session(), Genode::Affinity::Location()),
_vcpu_thread(STACK_SIZE, Genode::env()->cpu_session(), Genode::Affinity::Location())
{
using namespace Nova;

View File

@ -80,10 +80,11 @@ int SUPR3CallVMMR0Ex(PVMR0 pVMR0, VMCPUID idCpu, unsigned
}
extern "C"
bool create_emt_vcpu(pthread_t * thread, size_t stack_size,
const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg)
void *(*start_routine)(void *), void *arg,
Genode::Cpu_session * cpu_session,
Genode::Affinity::Location location)
{
/* no hardware acceleration support */
return false;

View File

@ -178,11 +178,11 @@ bool Vmm_memory::unmap_from_vm(RTGCPHYS GCPhys)
extern "C" void pthread_yield(void) { Nova::ec_ctrl(Nova::EC_YIELD); }
extern "C"
bool create_emt_vcpu(pthread_t * pthread, size_t stack,
const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg,
Genode::Cpu_session * cpu_session)
Genode::Cpu_session * cpu_session,
Genode::Affinity::Location location)
{
Nova::Hip * hip = hip_rom.local_addr<Nova::Hip>();
@ -191,11 +191,11 @@ bool create_emt_vcpu(pthread_t * pthread, size_t stack,
if (hip->has_feature_vmx())
vcpu_handler = new Vcpu_handler_vmx(stack, attr, start_routine, arg,
cpu_session);
cpu_session, location);
if (hip->has_feature_svm())
vcpu_handler = new Vcpu_handler_svm(stack, attr, start_routine, arg,
cpu_session);
cpu_session, location);
*pthread = vcpu_handler;
return true;

View File

@ -526,11 +526,13 @@ class Vcpu_handler : public Vmm::Vcpu_dispatcher<pthread>
Vcpu_handler(size_t stack_size, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg,
Genode::Cpu_session * cpu_session)
Genode::Cpu_session * cpu_session,
Genode::Affinity::Location location)
:
Vmm::Vcpu_dispatcher<pthread>(stack_size, _cap_connection,
cpu_session, location,
attr ? *attr : 0, start_routine, arg),
_vcpu(cpu_session),
_vcpu(cpu_session, location),
_ec_sel(Genode::cap_map()->insert()),
_irq_win(false)
{ }

View File

@ -83,8 +83,11 @@ class Vcpu_handler_svm : public Vcpu_handler
Vcpu_handler_svm(size_t stack_size, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg,
Genode::Cpu_session * cpu_session)
: Vcpu_handler(stack_size, attr, start_routine, arg, cpu_session)
Genode::Cpu_session * cpu_session,
Genode::Affinity::Location location)
:
Vcpu_handler(stack_size, attr, start_routine, arg, cpu_session,
location)
{
using namespace Nova;

View File

@ -117,8 +117,11 @@ class Vcpu_handler_vmx : public Vcpu_handler
Vcpu_handler_vmx(size_t stack_size, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg,
Genode::Cpu_session * cpu_session)
: Vcpu_handler(stack_size, attr, start_routine, arg, cpu_session)
Genode::Cpu_session * cpu_session,
Genode::Affinity::Location location)
:
Vcpu_handler(stack_size, attr, start_routine, arg, cpu_session,
location)
{
using namespace Nova;

View File

@ -27,8 +27,20 @@
/* libc memory allocator */
#include <libc_mem_alloc.h>
/**
* Returns true if a vCPU could be started. If false we run without
* hardware acceleration support.
*/
bool create_emt_vcpu(pthread_t * pthread, size_t stack,
const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg,
Genode::Cpu_session * cpu_session,
Genode::Affinity::Location location);
uint64_t genode_cpu_hz();
void inline genode_VMMR0_DO_GVMM_CREATE_VM(PSUPVMMR0REQHDR pReqHdr)
{
GVMMCREATEVMREQ &req = reinterpret_cast<GVMMCREATEVMREQ &>(*pReqHdr);

View File

@ -20,6 +20,8 @@
/* Genode libc pthread binding */
#include "thread.h"
#include "sup.h"
/* libc */
#include <pthread.h>
#include <errno.h>
@ -55,15 +57,6 @@ static Genode::Cpu_session * get_cpu_session(RTTHREADTYPE type) {
extern "C" {
/**
* Returns true if a vCPU could be started. If false we run without
* hardware acceleration support.
*/
bool create_emt_vcpu(pthread_t * pthread, size_t stack,
const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg,
Genode::Cpu_session *);
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg)
{
@ -86,9 +79,12 @@ extern "C" {
Assert(rtthread->enmType == RTTHREADTYPE_EMULATION);
if (rtthread->enmType == RTTHREADTYPE_EMULATION) {
Genode::Cpu_session * cpu_session = get_cpu_session(RTTHREADTYPE_EMULATION);
Genode::Affinity::Space cpu_space = cpu_session->affinity_space();
/* Genode::Affinity::Location location = cpu_space.location_of_index(i); */
Genode::Affinity::Location location;
if (create_emt_vcpu(thread, stack_size, attr, start_routine, arg,
get_cpu_session(RTTHREADTYPE_EMULATION)))
cpu_session, location))
return 0;
/* no haredware support, create normal pthread thread */
}