@@ -35,7 +35,7 @@ static u64 native_steal_clock(int cpu)
3535DEFINE_STATIC_CALL (pv_steal_clock , native_steal_clock );
3636
3737struct pv_time_stolen_time_region {
38- struct pvclock_vcpu_stolen_time * kaddr ;
38+ struct pvclock_vcpu_stolen_time __rcu * kaddr ;
3939};
4040
4141static DEFINE_PER_CPU (struct pv_time_stolen_time_region , stolen_time_region ) ;
@@ -52,7 +52,9 @@ early_param("no-steal-acc", parse_no_stealacc);
5252/* return stolen time in ns by asking the hypervisor */
5353static u64 para_steal_clock (int cpu )
5454{
55+ struct pvclock_vcpu_stolen_time * kaddr = NULL ;
5556 struct pv_time_stolen_time_region * reg ;
57+ u64 ret = 0 ;
5658
5759 reg = per_cpu_ptr (& stolen_time_region , cpu );
5860
@@ -61,28 +63,37 @@ static u64 para_steal_clock(int cpu)
6163 * online notification callback runs. Until the callback
6264 * has run we just return zero.
6365 */
64- if (!reg -> kaddr )
66+ rcu_read_lock ();
67+ kaddr = rcu_dereference (reg -> kaddr );
68+ if (!kaddr ) {
69+ rcu_read_unlock ();
6570 return 0 ;
71+ }
6672
67- return le64_to_cpu (READ_ONCE (reg -> kaddr -> stolen_time ));
73+ ret = le64_to_cpu (READ_ONCE (kaddr -> stolen_time ));
74+ rcu_read_unlock ();
75+ return ret ;
6876}
6977
7078static int stolen_time_cpu_down_prepare (unsigned int cpu )
7179{
80+ struct pvclock_vcpu_stolen_time * kaddr = NULL ;
7281 struct pv_time_stolen_time_region * reg ;
7382
7483 reg = this_cpu_ptr (& stolen_time_region );
7584 if (!reg -> kaddr )
7685 return 0 ;
7786
78- memunmap (reg -> kaddr );
79- memset (reg , 0 , sizeof (* reg ));
87+ kaddr = rcu_replace_pointer (reg -> kaddr , NULL , true);
88+ synchronize_rcu ();
89+ memunmap (kaddr );
8090
8191 return 0 ;
8292}
8393
8494static int stolen_time_cpu_online (unsigned int cpu )
8595{
96+ struct pvclock_vcpu_stolen_time * kaddr = NULL ;
8697 struct pv_time_stolen_time_region * reg ;
8798 struct arm_smccc_res res ;
8899
@@ -93,17 +104,19 @@ static int stolen_time_cpu_online(unsigned int cpu)
93104 if (res .a0 == SMCCC_RET_NOT_SUPPORTED )
94105 return - EINVAL ;
95106
96- reg -> kaddr = memremap (res .a0 ,
107+ kaddr = memremap (res .a0 ,
97108 sizeof (struct pvclock_vcpu_stolen_time ),
98109 MEMREMAP_WB );
99110
111+ rcu_assign_pointer (reg -> kaddr , kaddr );
112+
100113 if (!reg -> kaddr ) {
101114 pr_warn ("Failed to map stolen time data structure\n" );
102115 return - ENOMEM ;
103116 }
104117
105- if (le32_to_cpu (reg -> kaddr -> revision ) != 0 ||
106- le32_to_cpu (reg -> kaddr -> attributes ) != 0 ) {
118+ if (le32_to_cpu (kaddr -> revision ) != 0 ||
119+ le32_to_cpu (kaddr -> attributes ) != 0 ) {
107120 pr_warn_once ("Unexpected revision or attributes in stolen time data\n" );
108121 return - ENXIO ;
109122 }
0 commit comments