51
DECLARE_OBJ_CHECKERS(RamDiscardManager, RamDiscardManagerClass,
52
RAM_DISCARD_MANAGER, TYPE_RAM_DISCARD_MANAGER);
53
54
+#define TYPE_RAM_DISCARD_SOURCE "ram-discard-source"
55
+typedef struct RamDiscardSourceClass RamDiscardSourceClass;
56
+typedef struct RamDiscardSource RamDiscardSource;
57
+DECLARE_OBJ_CHECKERS(RamDiscardSource, RamDiscardSourceClass,
58
+ RAM_DISCARD_SOURCE, TYPE_RAM_DISCARD_SOURCE);
59
+
60
#ifdef CONFIG_FUZZ
61
void fuzz_dma_read_cb(size_t addr,
62
size_t len,
598
/**
599
* typedef ReplayRamDiscardState:
600
*
595
- * The callback handler for #RamDiscardManagerClass.replay_populated/
596
- * #RamDiscardManagerClass.replay_discarded to invoke on populated/discarded
601
+ * The callback handler for #RamDiscardSourceClass.replay_populated/
602
+ * #RamDiscardSourceClass.replay_discarded to invoke on populated/discarded
603
* parts.
604
*
605
* @section: the #MemoryRegionSection of populated/discarded part
611
void *opaque);
612
613
/*
608
- * RamDiscardManagerClass:
609
- *
610
- * A #RamDiscardManager coordinates which parts of specific RAM #MemoryRegion
611
- * regions are currently populated to be used/accessed by the VM, notifying
612
- * after parts were discarded (freeing up memory) and before parts will be
613
- * populated (consuming memory), to be used/accessed by the VM.
614
+ * RamDiscardSourceClass:
615
*
615
- * A #RamDiscardManager can only be set for a RAM #MemoryRegion while the
616
- * #MemoryRegion isn't mapped into an address space yet (either directly
617
- * or via an alias); it cannot change while the #MemoryRegion is
618
- * mapped into an address space.
616
+ * A #RamDiscardSource provides information about which parts of a specific
617
+ * RAM #MemoryRegion are currently populated (accessible) vs discarded.
618
*
620
- * The #RamDiscardManager is intended to be used by technologies that are
621
- * incompatible with discarding of RAM (e.g., VFIO, which may pin all
622
- * memory inside a #MemoryRegion), and require proper coordination to only
623
- * map the currently populated parts, to hinder parts that are expected to
624
- * remain discarded from silently getting populated and consuming memory.
625
- * Technologies that support discarding of RAM don't have to bother and can
626
- * simply map the whole #MemoryRegion.
627
- *
628
- * An example #RamDiscardManager is virtio-mem, which logically (un)plugs
629
- * memory within an assigned RAM #MemoryRegion, coordinated with the VM.
630
- * Logically unplugging memory consists of discarding RAM. The VM agreed to not
631
- * access unplugged (discarded) memory - especially via DMA. virtio-mem will
632
- * properly coordinate with listeners before memory is plugged (populated),
633
- * and after memory is unplugged (discarded).
634
- *
635
- * Listeners are called in multiples of the minimum granularity (unless it
636
- * would exceed the registered range) and changes are aligned to the minimum
637
- * granularity within the #MemoryRegion. Listeners have to prepare for memory
638
- * becoming discarded in a different granularity than it was populated and the
639
- * other way around.
619
+ * This is an interface that state providers (like virtio-mem or
620
+ * RamBlockAttributes) implement to provide discard state information. A
621
+ * #RamDiscardManager wraps sources and manages listener registrations and
622
+ * notifications.
623
*/
641
-struct RamDiscardManagerClass {
624
+struct RamDiscardSourceClass {
625
/* private */
626
InterfaceClass parent_class;
627
631
* @get_min_granularity:
632
*
633
* Get the minimum granularity in which listeners will get notified
651
- * about changes within the #MemoryRegion via the #RamDiscardManager.
634
+ * about changes within the #MemoryRegion via the #RamDiscardSource.
635
*
653
- * @rdm: the #RamDiscardManager
636
+ * @rds: the #RamDiscardSource
637
* @mr: the #MemoryRegion
638
*
639
* Returns the minimum granularity.
640
*/
658
- uint64_t (*get_min_granularity)(const RamDiscardManager *rdm,
641
+ uint64_t (*get_min_granularity)(const RamDiscardSource *rds,
642
const MemoryRegion *mr);
643
644
/**
645
* @is_populated:
646
*
647
* Check whether the given #MemoryRegionSection is completely populated
665
- * (i.e., no parts are currently discarded) via the #RamDiscardManager.
648
+ * (i.e., no parts are currently discarded) via the #RamDiscardSource.
649
* There are no alignment requirements.
650
*
668
- * @rdm: the #RamDiscardManager
651
+ * @rds: the #RamDiscardSource
652
* @section: the #MemoryRegionSection
653
*
654
* Returns whether the given range is completely populated.
655
*/
673
- bool (*is_populated)(const RamDiscardManager *rdm,
656
+ bool (*is_populated)(const RamDiscardSource *rds,
657
const MemoryRegionSection *section);
658
659
/**
660
* @replay_populated:
661
*
662
* Call the #ReplayRamDiscardState callback for all populated parts within
680
- * the #MemoryRegionSection via the #RamDiscardManager.
663
+ * the #MemoryRegionSection via the #RamDiscardSource.
664
*
665
* In case any call fails, no further calls are made.
666
*
684
- * @rdm: the #RamDiscardManager
667
+ * @rds: the #RamDiscardSource
668
* @section: the #MemoryRegionSection
669
* @replay_fn: the #ReplayRamDiscardState callback
670
* @opaque: pointer to forward to the callback
671
*
672
* Returns 0 on success, or a negative error if any notification failed.
673
*/
691
- int (*replay_populated)(const RamDiscardManager *rdm,
674
+ int (*replay_populated)(const RamDiscardSource *rds,
675
MemoryRegionSection *section,
676
ReplayRamDiscardState replay_fn, void *opaque);
677
679
* @replay_discarded:
680
*
681
* Call the #ReplayRamDiscardState callback for all discarded parts within
699
- * the #MemoryRegionSection via the #RamDiscardManager.
682
+ * the #MemoryRegionSection via the #RamDiscardSource.
683
*
701
- * @rdm: the #RamDiscardManager
684
+ * @rds: the #RamDiscardSource
685
* @section: the #MemoryRegionSection
686
* @replay_fn: the #ReplayRamDiscardState callback
687
* @opaque: pointer to forward to the callback
688
*
689
* Returns 0 on success, or a negative error if any notification failed.
690
*/
708
- int (*replay_discarded)(const RamDiscardManager *rdm,
691
+ int (*replay_discarded)(const RamDiscardSource *rds,
692
MemoryRegionSection *section,
693
ReplayRamDiscardState replay_fn, void *opaque);
694
+};
695
712
- /**
713
- * @register_listener:
714
- *
715
- * Register a #RamDiscardListener for the given #MemoryRegionSection and
716
- * immediately notify the #RamDiscardListener about all populated parts
717
- * within the #MemoryRegionSection via the #RamDiscardManager.
718
- *
719
- * In case any notification fails, no further notifications are triggered
720
- * and an error is logged.
721
- *
722
- * @rdm: the #RamDiscardManager
723
- * @rdl: the #RamDiscardListener
724
- * @section: the #MemoryRegionSection
725
- */
726
- void (*register_listener)(RamDiscardManager *rdm,
727
- RamDiscardListener *rdl,
728
- MemoryRegionSection *section);
696
+/**
697
+ * RamDiscardManager:
698
+ *
699
+ * A #RamDiscardManager coordinates which parts of specific RAM #MemoryRegion
700
+ * regions are currently populated to be used/accessed by the VM, notifying
701
+ * after parts were discarded (freeing up memory) and before parts will be
702
+ * populated (consuming memory), to be used/accessed by the VM.
703
+ *
704
+ * A #RamDiscardManager can only be set for a RAM #MemoryRegion while the
705
+ * #MemoryRegion isn't mapped into an address space yet (either directly
706
+ * or via an alias); it cannot change while the #MemoryRegion is
707
+ * mapped into an address space.
708
+ *
709
+ * The #RamDiscardManager is intended to be used by technologies that are
710
+ * incompatible with discarding of RAM (e.g., VFIO, which may pin all
711
+ * memory inside a #MemoryRegion), and require proper coordination to only
712
+ * map the currently populated parts, to hinder parts that are expected to
713
+ * remain discarded from silently getting populated and consuming memory.
714
+ * Technologies that support discarding of RAM don't have to bother and can
715
+ * simply map the whole #MemoryRegion.
716
+ *
717
+ * An example #RamDiscardSource is virtio-mem, which logically (un)plugs
718
+ * memory within an assigned RAM #MemoryRegion, coordinated with the VM.
719
+ * Logically unplugging memory consists of discarding RAM. The VM agreed to not
720
+ * access unplugged (discarded) memory - especially via DMA. virtio-mem will
721
+ * properly coordinate with listeners before memory is plugged (populated),
722
+ * and after memory is unplugged (discarded).
723
+ *
724
+ * Listeners are called in multiples of the minimum granularity (unless it
725
+ * would exceed the registered range) and changes are aligned to the minimum
726
+ * granularity within the #MemoryRegion. Listeners have to prepare for memory
727
+ * becoming discarded in a different granularity than it was populated and the
728
+ * other way around.
729
+ */
730
+struct RamDiscardManager {
731
+ Object parent;
732
730
- /**
731
- * @unregister_listener:
732
- *
733
- * Unregister a previously registered #RamDiscardListener via the
734
- * #RamDiscardManager after notifying the #RamDiscardListener about all
735
- * populated parts becoming unpopulated within the registered
736
- * #MemoryRegionSection.
737
- *
738
- * @rdm: the #RamDiscardManager
739
- * @rdl: the #RamDiscardListener
740
- */
741
- void (*unregister_listener)(RamDiscardManager *rdm,
742
- RamDiscardListener *rdl);
733
+ RamDiscardSource *rds;
734
+ MemoryRegion *mr;
735
+ QLIST_HEAD(, RamDiscardListener) rdl_list;
736
};
737
738
uint64_t ram_discard_manager_get_min_granularity(const RamDiscardManager *rdm,
744
/**
745
* ram_discard_manager_replay_populated:
746
*
754
- * A wrapper to call the #RamDiscardManagerClass.replay_populated callback
755
- * of the #RamDiscardManager.
747
+ * A wrapper to call the #RamDiscardSourceClass.replay_populated callback
748
+ * of the #RamDiscardSource sources.
749
*
750
* @rdm: the #RamDiscardManager
751
* @section: the #MemoryRegionSection
762
/**
763
* ram_discard_manager_replay_discarded:
764
*
772
- * A wrapper to call the #RamDiscardManagerClass.replay_discarded callback
773
- * of the #RamDiscardManager.
765
+ * A wrapper to call the #RamDiscardSourceClass.replay_discarded callback
766
+ * of the #RamDiscardSource sources.
767
*
768
* @rdm: the #RamDiscardManager
769
* @section: the #MemoryRegionSection
784
void ram_discard_manager_unregister_listener(RamDiscardManager *rdm,
785
RamDiscardListener *rdl);
786
787
+/*
788
+ * Note: later refactoring should take the source into account and the manager
789
+ * should be able to aggregate multiple sources.
790
+ */
791
+int ram_discard_manager_notify_populate(RamDiscardManager *rdm,
792
+ uint64_t offset, uint64_t size);
793
+
794
+ /*
795
+ * Note: later refactoring should take the source into account and the manager
796
+ * should be able to aggregate multiple sources.
797
+ */
798
+void ram_discard_manager_notify_discard(RamDiscardManager *rdm,
799
+ uint64_t offset, uint64_t size);
800
+
801
+/*
802
+ * Note: later refactoring should take the source into account and the manager
803
+ * should be able to aggregate multiple sources.
804
+ */
805
+void ram_discard_manager_notify_discard_all(RamDiscardManager *rdm);
806
+
807
+/*
808
+ * Replay populated sections to all registered listeners.
809
+ *
810
+ * Note: later refactoring should take the source into account and the manager
811
+ * should be able to aggregate multiple sources.
812
+ */
813
+int ram_discard_manager_replay_populated_to_listeners(RamDiscardManager *rdm);
814
+
815
/**
816
* memory_translate_iotlb: Extract addresses from a TLB entry.
817
* Called with rcu_read_lock held.
2525
}
2526
2527
/**
2507
- * memory_region_set_ram_discard_manager: set the #RamDiscardManager for a
2528
+ * memory_region_add_ram_discard_source: add a #RamDiscardSource for a
2529
* #MemoryRegion
2530
*
2510
- * This function must not be called for a mapped #MemoryRegion, a #MemoryRegion
2511
- * that does not cover RAM, or a #MemoryRegion that already has a
2512
- * #RamDiscardManager assigned. Return 0 if the rdm is set successfully.
2531
+ * @mr: the #MemoryRegion
2532
+ * @source: #RamDiscardSource to add
2533
+ */
2534
+int memory_region_add_ram_discard_source(MemoryRegion *mr, RamDiscardSource *source);
2535
+
2536
+/**
2537
+ * memory_region_del_ram_discard_source: remove a #RamDiscardSource for a
2538
+ * #MemoryRegion
2539
*
2540
* @mr: the #MemoryRegion
2515
- * @rdm: #RamDiscardManager to set
2541
+ * @source: #RamDiscardSource to remove
2542
*/
2517
-int memory_region_set_ram_discard_manager(MemoryRegion *mr,
2518
- RamDiscardManager *rdm);
2543
+void memory_region_del_ram_discard_source(MemoryRegion *mr, RamDiscardSource *source);
2544
2545
/**
2546
* memory_region_find: translate an address/size relative to a