@@ -35,6 +35,7 @@ import (
3535 "time"
3636
3737 "github.com/vhive-serverless/vhive/snapshotting"
38+ "golang.org/x/sys/unix"
3839
3940 log "github.com/sirupsen/logrus"
4041
@@ -65,6 +66,13 @@ type StartVMResponse struct {
6566 GuestIP string
6667}
6768
69+ type GuestRegionUffdMapping struct {
70+ BaseHostVirtAddr uint64 `json:"base_host_virt_addr"`
71+ Size uint64 `json:"size"`
72+ Offset uint64 `json:"offset"`
73+ PageSizeKiB uint64 `json:"page_size_kib"`
74+ }
75+
6876const (
6977 testImageName = "ghcr.io/ease-lab/helloworld:var_workload"
7078 fileBackend = "File"
@@ -506,9 +514,6 @@ func (o *Orchestrator) LoadSnapshot(ctx context.Context, originVmID string, vmID
506514 BackendPath : snap .GetMemFilePath (),
507515 }
508516
509- var sendfdConn * net.UnixConn
510- uffdListenerCh := make (chan struct {}, 1 )
511-
512517 if o .GetUPFEnabled () {
513518 logger .Debug ("TEST: UPF is enabled" )
514519 conf .MemBackend .BackendType = uffdBackend
@@ -522,31 +527,9 @@ func (o *Orchestrator) LoadSnapshot(ctx context.Context, originVmID string, vmID
522527 return nil , nil , err
523528 }
524529
525- logger .Debug ("TEST: start listening to uffd socket" )
526- if _ , err := os .Stat (conf .MemBackend .BackendPath ); err == nil {
527- os .Remove (conf .MemBackend .BackendPath )
528- }
529-
530- go func () {
531- listener , err := net .Listen ("unix" , conf .MemBackend .BackendPath )
532- if err != nil {
533- logger .Error ("failed to listen to uffd socket" )
534- return
535- }
536- defer listener .Close ()
537-
538- logger .Debug ("Listening ..." )
539- conn , err := listener .Accept ()
540- if err != nil {
541- logger .Error ("failed to accept connection to uffd socket" )
542- return
543- }
530+ // ===========================
544531
545- sendfdConn , _ = conn .(* net.UnixConn )
546- close (uffdListenerCh )
547- }()
548-
549- time .Sleep (10 * time .Second ) // TODO: sleep for 10 seconds to wait for the uffd socket to be ready
532+ // ===========================
550533 }
551534
552535 tStart = time .Now ()
@@ -590,11 +573,76 @@ func (o *Orchestrator) LoadSnapshot(ctx context.Context, originVmID string, vmID
590573 <- loadDone
591574
592575 if o .GetUPFEnabled () {
576+ logger .Debug ("TEST: start listening to uffd socket" )
577+ if _ , err := os .Stat (conf .MemBackend .BackendPath ); err == nil {
578+ os .Remove (conf .MemBackend .BackendPath )
579+ }
593580
594- logger .Debug ("TEST: Registering VM with snap with the memory manager" )
581+ var sendfdConn * net.UnixConn
582+ uffdListenerCh := make (chan struct {}, 1 )
583+ var userfaultFD * os.File
584+ var baseHostVirtAddr uint64
585+
586+ go func () {
587+ defer close (uffdListenerCh )
588+ listener , err := net .Listen ("unix" , conf .MemBackend .BackendPath ) // TODO: find a better Listener API
589+ if err != nil {
590+ logger .Error ("failed to listen to uffd socket" )
591+ return
592+ }
593+ defer listener .Close ()
594+
595+ logger .Debug ("Listening ..." )
596+ conn , err := listener .Accept () // blocking
597+ if err != nil {
598+ logger .Error ("failed to accept connection to uffd socket" )
599+ return
600+ }
601+
602+ sendfdConn , _ = conn .(* net.UnixConn )
603+
604+ // Parse mapping and fd
605+ buff := make ([]byte , 256 ) // set a maximum buffer size
606+ oobBuff := make ([]byte , unix .CmsgSpace (4 ))
607+ n , oobn , _ , _ , err := sendfdConn .ReadMsgUnix (buff , oobBuff )
608+ if err != nil {
609+ logger .Error ("failed to reading from uffd socket" )
610+ return
611+ }
612+ buff = buff [:n ]
613+
614+ var fd int
615+ if oobn > 0 {
616+ scms , err := unix .ParseSocketControlMessage (oobBuff [:oobn ])
617+ if err != nil {
618+ logger .Error ("failed to parse socket control message" )
619+ return
620+ }
621+ for _ , scm := range scms {
622+ fds , err := unix .ParseUnixRights (& scm )
623+ if err != nil {
624+ logger .Error ("failed to parse unix rights" )
625+ return
626+ }
627+ if len (fds ) > 0 {
628+ fd = fds [0 ] // Assuming only one fd is sent.
629+ break
630+ }
631+ }
632+ }
633+ userfaultFD = os .NewFile (uintptr (fd ), "userfaultfd" )
634+
635+ var mapping []GuestRegionUffdMapping
636+ if err := json .Unmarshal (buff , & mapping ); err != nil {
637+ logger .Error ("failed to unmarshal data" )
638+ return
639+ }
640+ baseHostVirtAddr = mapping [0 ].BaseHostVirtAddr
641+ }()
595642
596643 <- uffdListenerCh
597644
645+ logger .Debug ("TEST: Registering VM with snap with the memory manager" )
598646 stateCfg := manager.SnapshotStateCfg {
599647 VMID : vmID ,
600648 GuestMemPath : o .getMemoryFile (vmID ),
@@ -609,8 +657,8 @@ func (o *Orchestrator) LoadSnapshot(ctx context.Context, originVmID string, vmID
609657 logger .Error (err , "failed to register new VM with memory manager" )
610658 }
611659
612- logger .Debug ("TEST: activate VM in mm" )
613- if activateErr = o .memoryManager .Activate (originVmID , sendfdConn ); activateErr != nil {
660+ logger .Debug ("TEST: activate VM in mm" ) // TODO: pass too many params in Activate
661+ if activateErr = o .memoryManager .Activate (originVmID , userfaultFD , baseHostVirtAddr ); activateErr != nil {
614662 logger .Warn ("Failed to activate VM in the memory manager" , activateErr )
615663 }
616664 }
0 commit comments